0

We have the following scenario:

  1. Multiple 'legacy' Spring Security Oauth2 Auth Servers (2.3.4) - each with a different RSA key configured for creation of the JWT tokens.
  2. Single newer (SS 5.3.3, SB 2.3.1) Resource Server which we want to accept tokens from either auth server.

Problem is the resource server is only configured with 1 key (currently)- so it can only accept tokens from 1 auth-server.
Is there any conceivable way to support multiple keys in our resource server to decode JWTs coming from different auth-servers?

We basically want to do this but with multiple keys: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2resourceserver-jwt-decoder-public-key

Spring Security 5.3 indicates this may be possible with 'multi-tenancy' https://docs.spring.io/spring-security/site/docs/current/reference/html5/#webflux-oauth2resourceserver-multitenancy

It's a basic configuration

    @Value("${security.oauth2.resourceserver.jwt.key-value}")
    RSAPublicKey key;


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http

                // using new Spring Security SpE"{{LOCATOR_BASE_URL}}"L
                //https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#webflux-oauth2resourceserver-jwt-authorization
                .authorizeRequests(authorizeRequests ->
                                authorizeRequests

                                        .antMatchers("/shipments/**").hasAuthority("SCOPE_DOMPick")
                                                                               .anyRequest().authenticated()
                )

                .csrf().disable()

                // ****** this is the new DSL way in Spring Security 5.2 instead of Spring Security Oauth @EnableResourceServer ******
                .oauth2ResourceServer(oauth2ResourceServer ->
                        oauth2ResourceServer
                                .jwt(jwt ->
                                        jwt.decoder(jwtDecoder())
                                )
                );

    }

    // static key
    @Bean
    JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withPublicKey(this.key).build();
Rhett
  • 51
  • 1
  • 6

1 Answers1

2

Yes Spring Security 5.3 allow's you to use multiple jwk-uri key's. Please read my answer here:

https://stackoverflow.com/a/61615389/12053054

If you cannot use this version of SS it is possible to manually configure spring security to use multiple jwk-uri key's. (Follow link i have provided to see how).

This part of Spring Security doc's specify how to do it with Spring Security 5.3: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2resourceserver-multitenancy

JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver
    ("https://idp.example.org/issuerOne", "https://idp.example.org/issuerTwo");

http
    .authorizeRequests(authorize -> authorize
        .anyRequest().authenticated()
    )
    .oauth2ResourceServer(oauth2 -> oauth2
        .authenticationManagerResolver(authenticationManagerResolver)
    );

Note that issuer url's are resolved from incoming token (JWT oauth2 token always contains issuer url where uri for jwk to verify JWT token can be found). By manual configuration (answer i have posted) you can add custom behavior for example: instead of finding which ulr should be used to verify token directly from JWT you can check header's for information that resolves which issuer URL (you have specified them in your spring app) should be used with this request to verify JWT token.

Norbert Dopjera
  • 691
  • 3
  • 16
  • Thanks I've seen this post already - the issue is we don't have JWK uris for either auth-server. We are strictly using predefined keys which are manually shared from auth-server to each resource server. It may be possible to retrofit the existing auth-servers to expose a jks endpoint but was hoping to avoid this if possible. – Rhett Jul 23 '20 at 20:12
  • You can still us this feature. Last link i my mentioned answer show's how to manually configure authentication. With manual configuration you can set up how token's should be verified. For example you can resolve which key should be used by value provided in header (jwk-key: key-1 | key-2) then based on this value you can verify token by your stored JWK. Class responsible for this configuration is called `JwtIssuerAuthenticationManagerResolver` you can look inside it's implementation and implement it and use it by yourself, as is show in code post. Still better way would be to expose JWK key's – Norbert Dopjera Jul 23 '20 at 22:13