spring jwt decoder openid token

两盒软妹~` 提交于 2021-01-28 13:31:13

问题


External OAuth2 Provider doesn't have public JwkUri, so I tried too override default behavior using following code snippet:

@EnableWebSecurity
public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter {
 @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("**/oauth2/code/esia**", "**/code/esia**", "**esia**").permitAll()
            .antMatchers("/user").fullyAuthenticated()
            .anyRequest().authenticated()
            .and()
            .csrf().disable()
            .cors().disable()
            .oauth2Client()
            .clientRegistrationRepository(this.clientRegistrationRepository)
            .authorizationCodeGrant()
            .authorizationRequestResolver(new CustomAuthorizationRequestResolver(
                    this.clientRegistrationRepository, esiaConfig, signatureUtil, timeUtil))
            .accessTokenResponseClient(customAccessTokenResponseClient())
            .and().and().oauth2Login().tokenEndpoint().accessTokenResponseClient(customAccessTokenResponseClient())
            .and().and().oauth2ResourceServer().jwt();
}
@Bean
JwtDecoder jwtDecoder() {
 return  new CustomJwtDecoder();
}
}

class CustomJwtDecoder implements JwtDecoder {
@Override
public Jwt decode(String token) throws JwtException {
    System.out.println(token);
    return null;
}
}

However Spring Security somehow still uses default realization and I am getting the following error...

[missing_signature_verifier] Failed to find a Signature Verifier for Client Registration: 'esia'. Check to ensure you have configured the JwkSet URI.

Also, I tried to set custom AuthenticationProvider but spring ignores it.

I guess the catch is that spring`s OAuth2LoginConfigurer method init(B http) calls new OidcAuthorizationCodeAuthenticationProvider(accessTokenResponseClient, oidcUserService)


回答1:


For 5.1.3.RELEASE it looks like you cannot get around this problem easily.

It stems from the OidcAuthorizationCodeAuthenticationProvider.getJwtDecoder

This happens in line 156 which is a call to a private method

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        ...
        OidcIdToken idToken = createOidcToken(clientRegistration, accessTokenResponse);
        ...
    }

The one option I see is if you make a copy of this code, and modify it yourself. Extending the class itself is not meaningful because all of the logic happens pretty much in the authenticate method. So you're still overriding it. then you add your provider using the http.authenticationProvider method

Another option is to override the SecurityConfigurerAdapter.postProcess method of the OAuth2LoginConfigurer class and do something clever there. Like populating the JWT decoder map through reflection.

Neither are admittedly preferred solutions. I believe that's why the refactoring happened for the 5.2 release.

Given the latest 5.2.x release then You're almost there, but you must override the correct bean

    @Bean
    public JwtDecoderFactory<ClientRegistration> jwtDecoderFactory() {
        final JwtDecoder decoder = jwtDecoder();
        return context -> decoder;

    }

and if you don't want to use lambdas

    @Bean
    public JwtDecoderFactory<ClientRegistration> jwtDecoderFactory() {
        final JwtDecoder decoder = jwtDecoder();
        return new JwtDecoderFactory<ClientRegistration>() {
            @Override
            public JwtDecoder createDecoder(ClientRegistration context) {
                return decoder;
            }
        };

    }

How did I figure this out, well I took a look at the OAuth2LoginConfigurer.java class which does

    JwtDecoderFactory<ClientRegistration> jwtDecoderFactory = getJwtDecoderFactoryBean();

and the private method that fetches the bean look like this

    private JwtDecoderFactory<ClientRegistration> getJwtDecoderFactoryBean() {
        ResolvableType type = ResolvableType.forClassWithGenerics(JwtDecoderFactory.class, ClientRegistration.class);
        String[] names = this.getBuilder().getSharedObject(ApplicationContext.class).getBeanNamesForType(type);
        if (names.length > 1) {
            throw new NoUniqueBeanDefinitionException(type, names);
        }
        if (names.length == 1) {
            return (JwtDecoderFactory<ClientRegistration>) this.getBuilder().getSharedObject(ApplicationContext.class).getBean(names[0]);
        }
        return null;
    }



回答2:


I was facing the same issue even with 5.2.x release. In my case, the real problem was not in the JwtDecoder. I have fixed the issue by setting the jwk-set-uri property (you can change the provider name by the provider which you are using e.g okta, google etc.) :

security.oauth2.client.provider.azure.jwk-set-uri: https://login.microsoftonline.com/{tenant}/discovery/keys



来源:https://stackoverflow.com/questions/54512182/spring-jwt-decoder-openid-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!