我正在尝试实现将Azure B2C与 Boot 的Webflux Security结合使用的能力,虽然没有官方的库来实现这一点,微软的某个人说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/
。
如果使用发行者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到底是怎么回事?
1.如何允许Spring Security 5React式与Azure B2C一起工作?
1.我注意到JWT解码器在启动时只被调用一次,在端点被调用时它不会被调用,为什么会这样呢?
2条答案
按热度按时间67up9zun1#
颁发者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列表。
jq6vz3qz2#
基本实施
默认情况下,如果您想要完整的标准设置,并从资源YML配置文件中提取值,那么现在就可以使用这些方法了。下面是用于绝对准系统实现的securityWebFilterChain,它包括执行所有三项检查(颁发者、密钥验证和令牌过期):
执行此实现意味着您 * 必须 * 拥有这些默认资源位置的正确的application.yml文件条目。
使用代理设置实现
只要你不在公司防火墙后面,上述基本设置的一切都将工作得很好。如果你在防火墙后面,你必须找到一种方法来将代理设置包含在实现中。令所有人懊恼的是,由于某种原因,Spring Security 5的这个特定部分的默认实现不支持与代理相关的JAVA_OPT设置。要解决这个问题,你必须实现你自己的代理覆盖。2是的,我试过覆盖代理bean。3它也没有被接受。4我能让它工作的唯一方法是示例化一个web客户端,同时直接覆盖代理设置。
这意味着必须为oauth2上的JWT方法注入customerDecoder,并在该customer解码器中示例化一个具有自定义客户端连接器定义(该定义显式定义了其代理设置)的web客户端。当然,由于要重载解码器,因此必须重新定义默认情况下通常包含的所有特性(包括前面提到的3种令牌验证类型)。
恶心。
如果你问我的话,很多奇怪的东西应该是标准的。下面是我最后得到的在非防火墙和防火墙情况下都有效的东西: