JHipster: Receive 401 Unauthorized when making API call to microservice
Asked Answered
P

1

6

I am currently using Jhipster to generate the following components:

  • UAA - Auth Server
  • API Gateway
  • Microservice - Product1
  • Service Discovery - Consul

Other components:

  • Custom Frontend (Angular 4) - in a separate project

Also important to note is that the custom frontend is using Jhipster angular 4 code that can be found in a vanilla Jhipster Api Gateway. This includes the customHttpProvider.

The classes included can be seen in image below: enter image description here

At the moment I am able to login successfully with this setup and call the API's on the UAA, however, when I try to call any of the APIS on Product I get a 401 Unauthorised, for e.g. Post to Product1/api/zcd.

The services are all visible and green in Consul and the Gateway also has both the UAA and Product1 as registered and available routes.

enter image description here

So far I have found that it does not appear that the AuthInterceptor is being called when I make the api call to Product. I tried manually appending the jwt token to the methods and this fixes the problem, but I cant understand why the customHttpProvider is not being used to intercept the request and appending the token.

My ProductService below works when I insert the token manually as shown but this is obviously not the right way to do it.

@Injectable()
export class ProductService {

    private options = new Headers();

    constructor(private http: Http) {
        this.options.append('Authorization', 'Bearer ' + 'token is inserted here');
    }

    priceProduct(productPriceRequest: productPriceRequest): Observable<IdResponse> {
        return this.http.post('Product1/api/zcd', productPriceRequest, { headers: this.options })
            .map(response => response.json());
    }
}
Prinz answered 24/8, 2017 at 13:18 Comment(8)
There is nothing in relation to the api call in the Product1 log. It does hit the Gateway and reports the following line: r.f.g.accesscontrol.AccessControlFilter : Access Control: allowing access for /Product1/api/zcd, as it matches the following authorized microservice endpoint: /Product1/api However it does not get past this point and no further logs are evident in both the UAA (identity) and (Microservice) Product1Prinz
I have noticed in the OAuth2AuthenticationProcessingFilter, the isAuthenticated method is polled every few seconds (im guessing by making a call to the UAA) however the authentication field is only ever null.Prinz
Try enabling debug logging level on Product1 on spring security. You could also put a breakpoint in SendForwardFilter run() method:to see if it does send request to Product1 github.com/spring-cloud/spring-cloud-netflix/blob/master/…Liberec
So I found a solution to one of the problems which had to do with renaming the jwt token store bean (I will post this for reference later), however I have confirmed now that the token is not getting appended during the request. As part of my frontend code I have taken a number of the Jhipster classes such as customHttpProvider. I have also verified that the AuthInterceptor (also Jhipster code) is not being hit when I make the request to Product. Do you have any ideas why this would be the case. Also I debuuged on the SendForwarfdFilter and confirmed no token is present on the context.Prinz
Also to add, I connected Product to a vanilla Jhipster gateway frontend and made a simple button to hit the api and it works. Therefore I am feeling confident that I am missing something crucial in the frontend.Prinz
Updated question as requested.Prinz
As you found out, request has no Authorization header with token. So the problem is in your angular code which we don't know, so my only suggestion is to use Chrome debugger to follow what's going on step by step in working code (JHipster) and compare with your code. It could be a problem at initialization, anyway I think you're close to the solution. BTW, the question should not be tagged as JHipster and title is misleading too now that you have made progress.Liberec
Thanks for your help Gaël MarziouPrinz
P
2

Solved:

There were two things that were causing problems for me. Important to note is that they were not directly linked to JHipster but rather issues that occurred integrating Jhipster with:

Problems:

  1. Axon 3
  2. Custom Angular 4 frontend that has Lazy Loaded Modules.

Solutions:

    • I had included axon 3 into the Product Microservice and as part of axons configuration, it initializes a token store (has nothing to do with security).
    • The tokenStore bean in MicroserviceSecurityConfiguration that is meant to be of type JwtTokenStore was being overridden as an InMemoryTokenStore.
    • The solution was to rename the tokenStore bean in MicroserviceSecurityConfiguration to jwtTokenStore.
    • I had a number of lazy loaded modules. As per the documentation in this circumstance, there is SharedServiceModule that uses forRoot() and is imported in AppModule.
    • However when I had a service .e.g ProductService that was being imported in ProductModule, it was overriding the Http Factory that was being imported in the SharedServiceModule (same behaviour when importing Http Factory in AppModule).
    • The solution was to create a HttpProviderService that is provided at the same level as the customHttpProvider function (in SharedServiceModule). This then administers Http for all other Services at lower levels in the application. SharedServiceModule HttpProviderService
Prinz answered 28/8, 2017 at 15:40 Comment(3)
Interesting, thanks for sharing. Regarding RouterModule.forRoot(), someone reported that JHipster should not use everywhere but only in the app module and use RouterModule.forChild() elsewhere. Maybe it had an impact on your app.Liberec
Hi Gaël, not to sure what you are saying, but if I understand correctly, that is the setup I have in regards to routing. In my AppModule I have imported a MainRoutingModule and AppLazyRoutingModule which both use forRoot() and and then in all the other modules .e.g Prouct 1, Product 2 etc, they all have their own routing Modules that implement RouterModule.forChild(). The forRoot that I mentioned above in my solution has to do with my SharedServiceModule that uses static forRoot(): ModuleWithProviders interface.Prinz
OK, I misunderstood.Liberec

© 2022 - 2024 — McMap. All rights reserved.