【问题标题】:WebFlux: Can't authenticate JWT token from Azure B2CWebFlux:无法从 Azure B2C 验证 JWT 令牌
【发布时间】:2022-01-18 07:19:06
【问题描述】:

我正在尝试实现将 Azure B2C 与 Spring Boot 的 Webflux Security 结合使用的能力。 虽然没有官方库可以实际执行此操作,但 someone at Microsoft 表示 Spring Security 5 的本机功能可以支持 Azure B2C。我已经关注了这个repository(虽然它不是基于 webflux 的)来了解如何实现这一点。 JWT 令牌通过应用程序的受众 UUID 进行验证。

一旦我尝试为请求实际提供 JWT 令牌,我会收到一个 HTTP 401 错误,指出 Authentication failed: Failed to validate the token

问题是在示例存储库中,他们使用端点 https://login.microsoftonline.com/{tenantId}/v2.0 作为颁发者 url。

另一方面,从 B2C 返回的 JWT 令牌的发行者为 https://{tenantName}.b2clogin.com/{tenantId}/v2.0/

如果我改用 issuer https://{tenantName}.b2clogin.com/{tenantId}/v2.0/,JWT 解码器将无法找到配置。

所以现在我觉得颁发者 URL 实际是什么不一致,这阻止了 Webflux 实际能够执行身份验证。

这是我的安全代码。


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.security.web.server.SecurityWebFilterChain;

@EnableWebFluxSecurity
public class SecurityConfiguration {

    @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
    String issuerUri;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)throws Exception {
        return http.cors().and().csrf().disable()
                .authorizeExchange()
                .anyExchange()
                .authenticated()
                .and().oauth2ResourceServer().jwt().and().and().build();

    }

    @Bean
    ReactiveJwtDecoder jwtDecoder() {
        NimbusReactiveJwtDecoder jwtDecoder = (NimbusReactiveJwtDecoder) ReactiveJwtDecoders.fromIssuerLocation(issuerUri);

        OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator();
        OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
        OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);

        jwtDecoder.setJwtValidator(withAudience);

        return jwtDecoder;
    }
}

观众验证器。

import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
import org.springframework.security.oauth2.jwt.Jwt;

public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
    OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);

    public OAuth2TokenValidatorResult validate(Jwt jwt) {
        if (jwt.getAudience().contains("messaging")) {
            return OAuth2TokenValidatorResult.success();
        } else {
            return OAuth2TokenValidatorResult.failure(error);
        }
    }
}

application.yml

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: https://login.microsoftonline.com/{tenantId}/discovery/v2.0/keys 
          issuer-uri: https://login.microsoftonline.com/{tenantId}/v2.0
          audience: {audience-id}

所以,我有三个问题:

  1. 颁发者 URL 到底是怎么回事?
  2. 如何允许 Spring Security 5 响应式与 Azure B2C 一起使用?
  3. 我注意到 JWT 解码器在启动时只被调用一次。调用端点时不会调用它。为什么会这样?

【问题讨论】:

  • 您是否尝试将issuer-uri 属性设置为b2clogin.com URL,但在@Bean ReactiveJwtDecoder 中使用login.microsoftonline.com URL?
  • @SteveRiesenberg 在采用这种方法时,恐怕我会遇到同样的错误。我想知道我缺少什么细节?
  • 您可以尝试启用调试日志记录,logging.level.org.springframework.security=debug 并提供日志。
  • @SteveRiesenberg 实际上,我有用于跟踪安全性的日志记录级别。但是,除了:2021-12-17 22:15:18.062 DEBUG 97155 --- [r-http-kqueue-3] o.s.s.w.s.a.AuthenticationWebFilter : Authentication failed: Failed to validate the token 之外,这并没有为我提供任何其他日志
  • {tenantId} 来自哪里?在您引用的示例中,它是 ${tenant-id}(注意美元符号)。

标签: azure spring-security azure-ad-b2c spring-webflux spring-security-oauth2


【解决方案1】:

颁发者 URL https://login.microsoftonline.com/{tenantId}/v2.0 用于 Azure AD。

由于 Azure B2C 依赖于已定义的配置文件,因此您必须使用 https://{tenantName}.b2clogin.com/tfp/{tenantId}/{profileName}/v2.0/ 作为颁发者 URL。

虽然 https://{tenantName}.b2clogin.com/{tenantId}/{profileName}/v2.0/ 也是有效的颁发者,但 Spring Security 会抱怨颁发者 URL 不一致,因为颁发者实际上是 https://{tenantName}.b2clogin.com/{tenantId}/v2.0/

Azure B2C 似乎没有一般颁发者,也没有包含所有密钥的 JWK 列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-19
    • 2021-11-16
    • 2019-07-29
    • 2021-08-21
    • 2018-12-25
    • 2016-07-06
    • 2017-07-31
    • 2023-02-24
    相关资源
    最近更新 更多