0

I have configured Spring Boot as an OAuth2 Resource Server using Google as the Authorization Server. I am now successfully making requests (eg. via PostMan) to a secured @Controller. These are the relevant Spring Security properties:

spring.security.oauth2.resourceserver.jwt.issuer-uri=https://accounts.google.com
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://www.googleapis.com/oauth2/v3/certs

When I obtain a JWT token from Google via PostMan, I am then able to successfully make an http request to my secured @Controller using Bearer ${id_token} as the Authorization header. I am also able to decode the token (eg. using jwt.io) and see the issuer is "iss": "https://accounts.google.com"

However, when I obtain a JWT token from Google via a Javascript SPA (eg. React using the react-google-login component) the JWT token has "iss": "accounts.google.com" <<< Notice it's missing the https://

According to Google's OAuth 2.0 / OpenID Connect documentation, Google may return either "iss": "https://accounts.google.com" or "iss": "accounts.google.com". They say validation should:

Verify that the value of the iss claim in the ID token is equal to https://accounts.google.com or accounts.google.com.

Although not specific to Spring, this StackOverflow question also mentions that Google can return either value: Can I get a consistent 'iss' value for a Google OpenIDConnect id_token?

As far as I can tell Spring Boot configures the JwtIssuerValidator class to validate against ONLY the value of the jwt.issuer-uri property. This does not seem sufficient because Google can return either of these values, as seen in my testing where PostMan returns JWT with an iss value with https and React returns an iss value without https

I have been able to workaround this issue by overriding the JwtDecoder bean as described in the Exposing a JwtDecoder @Bean section of the Spring Security docs.

In summary:

  • Is my understanding as described above correct? Essentially, Google can return one of two supported values for iss but Spring Security by default always expect only one value?
  • Is there a way to overcome this via OOTB configuration? Perhaps I missed something in the docs?
  • Assuming my understanding is correct and there's no OOTB solution, is the best option to override the JwtDecoder as I have done? It doesn't seem quite right because now I'm not validating the issuer at all.

Happy to clarify or add more info if needed. Thanks for your consideration and your patience!

Justin
  • 6,031
  • 11
  • 48
  • 82
  • This is an interesting issue, because I wouldn’t think react would change the parsed token, and I haven’t seen google return this in a typical login scenario. But one question that might clarify things: you say you’re using postman with the id_token. Did you mean id token or access token? If you use the access token do you get the same result? – Steve Riesenberg Feb 24 '22 at 03:30
  • I don't think React is changing the parsed token. The Google docs are pretty clear that either value can be returned for iss: "Always https://accounts.google.com or accounts.google.com for Google ID tokens." However, I have no idea how or why one value is returned vs the other. – Justin Feb 24 '22 at 03:37
  • As for the id token or access token, I'm sending the id token. I couldn't get it to work using the access token and eventually realized Spring Security would successfully accept the id token. I don't know if that is due to a config issue on my part or not. I haven't found a good example of Spring Boot configured as a Resource Server using Google as Authorization Server to compare it to. I could push this config to GitHub tomorrow if that helps. Thanks for your suggestions. It's appreciated. – Justin Feb 24 '22 at 03:40
  • I'm working on a Federated Login sample for Spring Authorization Server using Google, so I can probably try it myself as well, but if you want to throw up your config that would be helpful. You may be right that it's out of our control, so we should be able to plug in our own validator(s) to solve it. Have you seen the section on [custom validators](https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-validation-custom)? *Edit:* Also, I would think you definitely want to be using access token, not id token. – Steve Riesenberg Feb 24 '22 at 04:25
  • @SteveRiesenberg regarding the access token vs id token I've not been able to get it working. I've just created a separate SO Question specifically for this issue. It provides more detail than I can add in a comment. https://stackoverflow.com/questions/71254326/spring-boot-authorization-server-google-oauth2-openid-connect-should-work-with – Justin Feb 24 '22 at 15:26
  • @SteveRiesenberg I've pushed a simple repo that you can hopefully use to recreate the issue. The ReadMe should have the instructions you need. https://github.com/justinhrobbins/spring-resourceserver-oauth-google – Justin Feb 24 '22 at 17:41
  • Thanks. I've attempted to answer this in your other question linked above, as I think this question isn't the core of your issue. It was a bit more involved than I expected. – Steve Riesenberg Feb 24 '22 at 19:35

0 Answers0