Expected Behavior
It is possible to define multiple issuer URIs at spring.security.oauth2.resourceserver.issuer-uris. Spring Security considers all configured JWK Issuers to validate tokens.
Current Behavior
Only one JWK issuer can be configured.
Context
We are building a service that will run in multiple regions. For service-to-service authorization, we are using JWTs that are signed with JWKs which are specific to the region that the requesting service is deployed to (concretely, we are using k8s’ service account tokens). In failure scenarios, client services shall fail over to a service that is deployed in a different region. Hence, our service needs to be able to validate tokens from all regions that our clients might be deployed in.
In a comment on #7474 somebody requested functionality to have different JWK sets for different types of tenants. It was explained that this should be solved via an AuthenticationManagerResolver. We think that our use case is different. We do not have different types of tenants. Instead, we only have one type of tenant, but different potential issuers for tokens.
Implementation Considerations
We are willing to provide a PR for this functionality. Our current design considerations are below. We would be happy to receive feedback!
- Must a PR that provides this functionality implement it for both the blocking and the reactive implementation? Or would an implementation only for reactive be acceptable?
- Our proposed implementation is to create a
ReactiveJwtDecoderthat dispatches to delegateReactiveJwtDecoders based on theissclaim in a JWT. The delegates would be configured for every issuer URI like they are today. - A disadvantage of the above proposal is that we would have to parse the JWT twice: once in the dispatching
ReactiveJwtDecoder, and once in the actualReactiveJwtDecoder. The alternative we see is to make the builders inNimbusReactiveJwtDecoderaware of the issuer checks. We could then build just oneNimbusReactiveJwtDecoderwith ajwtProcessorthat does the dispatching based onissto the correctjwtProcessor. This setup would avoid the double parsing, but would likely also be more complicated in the code, especially because the issuer concern is pulled into the already elaborate builders inNimbusReactiveJwtDecoder. We would welcome guidance on the best approach here! - What is the appropriate deprecation strategy for the single-value property
issuer-uri? Should it be marked deprecated in favour ofissuer-uris? Or should the former be appended to the latter? spring-securitycurrently supports theisscheck if one configures ajwk-set-uritogether with anissuer-uri. Would it be required to support this feature also for multiple JWK Set URIs? If so, how should the mapping of the JWK Set URIs to the expected Issuer URIs happen? Should they just be declared as lists in the same order?spring-securitycurrently checks the Issuer URI synchronously on startup. Given our use case, we don’t want the application startup to fail just because one issuer could not be reached, since other regions should remain functional if one region goes down. A conservative approach would be to let the startup succeed if at least one issuer could be reached. However, it would then be good to re-check the failed issuers from time to time, so that they can become functional again without having to restart the service. I think the details can be done in a separate PR. It would potentially mean introducing proxyReactiveJwtDecoders that act while the issuer is down, check the issuer periodically, and switch to the actualReactiveJwtDecoderonce the issuer was reached.
(updated to reflect better understandig of the implementation)
Comment From: jzheaux
Hi, @jGleitz, thanks for the detailed write-up.
We do not have different types of tenants. Instead, we only have one type of tenant, but different potential issuers for tokens.
This still seems to be something that JwtIssuerAuthenticationManagerResolver can handle and is intended for. Have you already tried using it, and if so, where did you get into trouble with that approach?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: jGleitz
Hi! Thank you for your response. We noticed that
a) I misunderstood the purpose of JwtIssuerAuthenticationManagerResolver and it might suit our use case, we have to check.
b) we might be able to pull authorization concerns out of the service and into the service mesh.
We are going to close this issue for now until we have checked everything on our side, and will get back if we think that there is an area where Spring Security could be improved.
Thank you for your support!