Secure a Spring Microservices Architecture with OAuth

Matt Raible

Yes, that is correct. When your try to access http://localhost:8080/beers directly, it should prompt you to login with basic authentication. You can compare your code to this example’s code if it doesn’t work for you.

jmfenner

Great article, @mattraible and I’m definitely authenticating requests, however, I don’t think things are authorizing properly. I’m wanting my zuul edge server to apply some authorization decision, but everything is getting through. One of my users is in the group “Admin”; the other is not.

I suspect I’m just not grokking the http security correctly. Here’s the config in which I’m trying to assert that svc2 is open to all while svc1 requires membership in the Okta ‘Admin’ group that I defined:

http
.requestMatcher(new RequestHeaderRequestMatcher(“Authorization”))
.authorizeRequests()
.antMatchers("/svc2/").permitAll()
.antMatchers("/svc1/
").access(“hasRole(‘Admin’)”)
.antMatchers("/**").authenticated();

I’m finding spring security to be a bit dizzying in its options, and really appreciate your article. Any thoughts on the possible several things I’m missing?

Matt Raible

Can you try hasAuthority() instead of hasRole(). The hasRole() expression expects there to be a “ROLE_” prefix.

jmfenner

@mattraible , thanks. I’ll give that a try today.

You wrote another article on secure communication between services with jwt (https://developer.okta.com/…, and it strikes me this may be more what I need. So let me ask you your opinion:

The solution in this article causes a redirect to Okta for authentication when needed. But if I’m using Zuul as a gateway to other services, and assuming / expecting that incoming requests to Zuul will already be authenticated (such as through an Angular UI with the Okta widget), do I need the approach in this article, or just the jwt approach in the other article?

I’ve been drinking from the firehose lately taking in all these option for integration with Okta in Microservices systems. I’d really appreciate any thoughts you have on “best way”.

Thanks! Will let you know too about the hasAuthority change.

Matt Raible

The other article is more up-to-date than this one, so if that works for you, please use it. I’m working on an updated version of this one. We plan to publish it next week. Secure Server-to-Server Communication with Spring Boot and OAuth 2.0 might help too.

George Kofi

Thanks for the article @mattraible . You are making development easier for us. But I have an issue, I can’t get the roles of the authenticated user in my home.html template. I get the error “Property or field ‘roles’ cannot be found on object of type ‘java.util.LinkedHashMap’”. During debugging, I realised there is no key with name “roles” in authentication details. Any help would appreciated. Thanks again.

Matt Raible

You need to add “roles” as a claim in your ID token for this to work. There’s a step at the end of this section that shows you how.

George Kofi

Thanks for the quick response.
Yes I already did that. I have attached a screen shot of my configuration. I must mention though that I am using spring boot version 2.1.5.RELEASE and 2.1.1.RELEASE of spring-security-oauth2-autoconfigure . I am able to retrieve all other information about the authenticated user except the roles. I don’t really know what I am doing wrong.
https://uploads.disquscdn.c…

George Kofi

Yes, I already did that. I should mention though that I am using spring boot version 2.1.5.RELEASE and version 2.1.1.RELEASE of spring-security-oauth2-autoconfigure. See the attached image for my roles configuration. I don’t know what I am doing wrong.
https://uploads.disquscdn.c…

Matt Raible

Your filter setting should be “matches regex” rather than “starts with”. https://uploads.disquscdn.c…

George Kofi

Thanks @mattraible . It worked.
Really appreciate
Looking forward to more articles.

Vek

Hi Matt, in reference to above post of getting groups as granted authorities in spring authentication object, it works fine with custom auth server - but NOT when same is done at application sign on settings. Is there anything I am missing ?

Matt Raible

I’m not sure what you mean by application sign on settings. The only way I’ve ever included groups in the ID or access token is by adding a claim to the authorization server. I’m not aware of doing it any other way. You might try posting your question to our developer forums with more information about what you’re trying to do.

Vek

Hi Matt,

Thanks for your reply !!

I am referring to below article,

https://developer.okta.com/…

Your issuer URL in app prop file will be without default. In other sense you don’t have custom auth server and you are configuring claims at app level.

Vivek

Muhammad Yassein

Thnaks

Matt Raible

Ahhh, you’re talking about the “org” authorization server (that’s what we call it). The tokens from this server can not be validated externally. That’s why we recommend you create a custom authorization server. A “default” one is created for you.

aymen marouani

Hi,
Thanks a lot for the article, but I didn’t understand why we have the same OAuth configuration between the resource server (good beers service) and the gateway (edge server) ? Will the resource sever communicate again with Okta Server to validate the token obtained by the call from the Edge Server ?

Matt Raible

The resource server (the good beers service in this case) will do local token validation. Because the token is a JWT, it can verify it locally without making a call back to Okta. You can configure it to make a remote call for validation, but it’s not really necessary. If you were to use opaque tokens, which Spring Security supports, you would need to make a call back to the server for validation. There’s an open issue for Okta’s Spring Boot starter that discusses opaque token support.

aymen marouani

Thanks, but if I’m not wrong, I remember not seeing a public key to verify the signature, how the local vlidation is done ?

Brian Demers

Okta exposes the public keys through a JWKS endpoint, which can be found using the OIDC discovery endpoint, for example: https://{yourOktaDomain}/oauth2/default/.well-known/openid-configuration, look for the jwks_uri value.

Okta has two types of issuer (Okta Authorization Servers). Only the one formatted as https://{yourOktaDomain}/oauth2/{id} supports local JWT validation (were {id} is usually “default”)