How resource server validate (signature of) access token(JWT) in SpringBoot(nimbus)

I checked into this topic because I got the below error in my SpringBoot application:

.o.s.r.w.BearerTokenAuthenticationFilter : Authentication request for failed: org.springframework.security.oauth2.core.OAuth2AuthenticationException: An error occurred while attempting to decode the Jwt: Signed JWT rejected: Another algorithm expected, or no matching key(s) found

What are validated in this BearerTokenAuthenticationFilter:

  1. signature
  2. expirationTime

Here is the call hierarchy:

org.springframework.web.filter.OncePerRequestFilter.doFilter
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal
org.springframework.security.authentication.ProviderManager.authenticate
org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider.authenticate
org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport.decode
org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport.createJwt

    // Verify the signature
    JWTClaimsSet jwtClaimsSet = this.jwtProcessor.process(parsedJwt, null);

com.nimbusds.jwt.proc.DefaultJWTProcessor.process

  List<? extends Key> keyCandidates = getJWSKeySelector().selectJWSKeys(signedJWT.getHeader(), context);

  if (keyCandidates == null || keyCandidates.isEmpty()) {
    throw NO_JWS_KEY_CANDIDATES_EXCEPTION;
  }

    private static final BadJOSEException NO_JWS_KEY_CANDIDATES_EXCEPTION =
        new BadJOSEException("Signed JWT rejected: Another algorithm expected, or no matching key(s) found");

The question is:
How NimbusJwtDecoderJwkSupport be initialized?

By setup a BreakPoint at constructer method of it, we can easily found that
it is initialized at SpringBoot application startup:

org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwkConfiguration.jwtDecoderByIssuerUri

@Bean
@Conditional(IssuerUriCondition.class)
@ConditionalOnMissingBean
public JwtDecoder jwtDecoderByIssuerUri() {
    return JwtDecoders
            .fromOidcIssuerLocation(this.properties.getJwt().getIssuerUri());
}

org.springframework.security.oauth2.jwt.JwtDecoders.fromOidcIssuerLocation

    public static JwtDecoder fromOidcIssuerLocation(String oidcIssuerLocation) {
        Map<String, Object> openidConfiguration = getOpenidConfiguration(oidcIssuerLocation);
        String metadataIssuer = "(unavailable)";
        if (openidConfiguration.containsKey("issuer")) {
            metadataIssuer = openidConfiguration.get("issuer").toString();
        }
        if (!oidcIssuerLocation.equals(metadataIssuer)) {
            throw new IllegalStateException("The Issuer \"" + metadataIssuer + "\" provided in the OpenID Configuration " +
                    "did not match the requested issuer \"" + oidcIssuerLocation + "\"");
        }

        OAuth2TokenValidator<Jwt> jwtValidator =
                JwtValidators.createDefaultWithIssuer(oidcIssuerLocation);

        NimbusJwtDecoderJwkSupport jwtDecoder =
                new NimbusJwtDecoderJwkSupport(openidConfiguration.get("jwks_uri").toString());
        jwtDecoder.setJwtValidator(jwtValidator);

        return jwtDecoder;
    }

Where it uses spring.security.oauth2.resourceserver.jwt.issuer-uri property to fetch
jwks uri and all the public keys.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。