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!