解码 jwt 时,AuthenticationEvent 未发布错误

Posted

技术标签:

【中文标题】解码 jwt 时,AuthenticationEvent 未发布错误【英文标题】:AuthenticationEvent is not published on error while decoding jwt 【发布时间】:2021-07-10 12:52:58 【问题描述】:

由于我的验证器失败,在尝试解码 Jwt 时发生错误时,我无法捕获身份验证失败事件。我正在使用 Spring Security 5.2.1。请注意,当我根本没有在“授权”标头中传递令牌时,我会捕获授权失败事件。我想一些额外的配置必须通过 spring 配置来完成。

抛出异常:

org.springframework.security.oauth2.core.OAuth2AuthenticationException: An 
error occurred while attempting to decode the Jwt: This aud claim does not 
contain configured audience

审计的实施如下所述:https://www.baeldung.com/spring-boot-authentication-audit

当前的 spring 安全配置:

@EnableWebSecurity
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

private static final OAuth2Error INVALID_AUDIENCE =
        new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST,
                "This aud claim does not contain configured audience",
                "https://tools.ietf.org/html/rfc6750#section-3.1");


@Value("$spring.security.oauth2.claim-to-validate.audience")
private String audience;

@Value("$spring.security.oauth2.claim-to-validate.scope")
private String scope;

@Value("$spring.security.oauth2.resourceserver.jwt.public-key-location:#null")
private RSAPublicKey publicKeyLocation;

@Value("$spring.security.oauth2.resourceserver.jwt.jwk-set-uri:#null")
private String jwkSetUri;

@Value("$spring.security.oauth2.resourceserver.jwt.issuer-uri:#null")
private String issuerUri;


@Override
protected void configure(HttpSecurity http) throws Exception 
            http
                    .authorizeRequests()
                    .antMatchers( "/v1/resource/**")
                    .hasAuthority("SCOPE_" + scope)
                    .and()
                    .oauth2ResourceServer()
                    .jwt();


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.inMemoryAuthentication();


@Bean
public JwtDecoder jwtDecoder() 
    final OAuth2TokenValidator<Jwt> withAudience = audienceValidator(audience);

    final JwtDecoder jwtDecoder;

    if (publicKeyLocation != null) 
        jwtDecoder = NimbusJwtDecoder.withPublicKey(publicKeyLocation).build();
     else if (StringUtils.hasLength(jwkSetUri)) 
        jwtDecoder = NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
     else if (StringUtils.hasLength(issuerUri)) 
        jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuerUri);
     else 
        throw new IllegalStateException(
                "Invalid OAuth2 configuration: provide value for any of " +
                        "'publicKeyLocation', 'jwkSetUri' or 'issuerUri'");
    

    ((NimbusJwtDecoder) jwtDecoder).setJwtValidator(withAudience);

    return jwtDecoder;


OAuth2TokenValidator<Jwt> audienceValidator(String audience) 
    return jwt -> 
        Assert.notNull(jwt, "token cannot be null");

        final List<String> audiences = jwt.getAudience();

        return audiences.contains(audience) ?
                OAuth2TokenValidatorResult.success() :
                OAuth2TokenValidatorResult.failure(INVALID_AUDIENCE);
    ;


【问题讨论】:

我发现这个 ***.com/questions/41076500/… 相关。我已经创建了一个发布者,但不知道我需要注册它。 一个更古老但相关的话题:***.com/questions/30278293/… 我已经为 AuthenticationEventPublisher 添加了自定义映射(通过 setAdditionalExceptionMappings(Properties props))。但它在测试期间以某种方式被重置。在 5.3.0 中添加了更明智的方法:github.com/spring-projects/spring-security/issues/7825 我想我在不幸中找到了兄弟:github.com/spring-projects/spring-security/issues/7793。我做了指向那里的每一步。 【参考方案1】:

将 Spring Security 更新到 5.3.0 或更高版本,并在 Spring Security Configuration 中声明自定义 AuthenticationEventPublisher bean,如下所示:

@Autowired
private ApplicationEventPublisher publisher;

@Bean
public AuthenticationEventPublisher authenticationEventPublisher() 
    final Properties properties = new Properties();
    properties.put(
        OAuth2AuthenticationException.class.getCanonicalName(),
        AuthenticationFailureBadCredentialsEvent.class.getCanonicalName());

    final DefaultAuthenticationEventPublisher eventPublisher = new DefaultAuthenticationEventPublisher(publisher);

    eventPublisher.setAdditionalExceptionMappings(properties);

    return eventPublisher;

请注意,在 5.3.0 中,您可以直接添加不带属性结构的映射。

如果您需要继续使用 5.2.x,请使用此处指出的解决方法:https://github.com/spring-projects/spring-security/issues/7793

【讨论】:

以上是关于解码 jwt 时,AuthenticationEvent 未发布错误的主要内容,如果未能解决你的问题,请参考以下文章

解码 jwt 时,AuthenticationEvent 未发布错误

JWT解码时字符串声明类型错误?

JWT-解码需要未定义,jwt解码未定义

JWT 在 jwt.io 上解码,但不在应用程序中

Spring Boot > 2.2.7 的令牌类型为“at+jwt”时 JWT 错误的解码

JWT在jwt.io上解码,但在应用程序中没有