spring jwt解码器openid令牌
外部OAuth2提供程序没有公共JwkUri,因此我也尝试使用以下代码段覆盖默认行为:spring jwt解码器openid令牌,spring,spring-security,oauth-2.0,spring-security-oauth2,Spring,Spring Security,Oauth 2.0,Spring Security Oauth2,外部OAuth2提供程序没有公共JwkUri,因此我也尝试使用以下代码段覆盖默认行为: @EnableWebSecurity public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRe
@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;
}
}
然而,SpringSecurity仍然使用默认实现,我得到以下错误
[missing_signature_verifier] Failed to find a Signature Verifier for Client Registration: 'esia'. Check to ensure you have configured the JwkSet URI.
另外,我尝试设置自定义AuthenticationProvider,但spring忽略了它
我想问题在于spring的OAuth2LoginConfigurater方法init(bHTTP)调用了新的OidcAuthorizationCodeAuthenticationProvider(accessTokenResponseClient,oidcUserService)用于5.1.3版本。看起来您无法轻松解决这个问题 它源于 这种情况发生在调用私有方法时
@覆盖
公共身份验证(身份验证)引发AuthenticationException{
...
OidcIdToken idToken=createOidcToken(clientRegistration,accessTokenResponse);
...
}
我看到的一个选项是,如果您复制此代码,并自己修改它。扩展类本身没有意义,因为所有逻辑几乎都发生在authenticate
方法中。所以你仍然在覆盖它。然后使用http.authenticationProvider
方法添加提供者
另一个选项是重写OAuth2LoginConfiguler
类的方法,并在那里做一些聪明的事情。就像通过反射填充图像一样
两者都不是公认的首选解决方案。我相信这就是5.2版本发生重构的原因
考虑到最新的5.2.x版本
您就快到了,但必须覆盖正确的bean
@Bean
public JwtDecoderFactory<ClientRegistration> jwtDecoderFactory() {
final JwtDecoder decoder = jwtDecoder();
return context -> decoder;
}
@Bean
公共JwtDecoderFactory JwtDecoderFactory(){
最终JwtDecoder解码器=JwtDecoder();
返回上下文->解码器;
}
如果你不想使用lambdas
@Bean
公共JwtDecoderFactory JwtDecoderFactory(){
最终JwtDecoder解码器=JwtDecoder();
返回新的JwtDecoderFactory(){
@凌驾
公共JwtDecoder createDecoder(ClientRegistration上下文){
返回解码器;
}
};
}
我是怎么弄明白的,我看了一下这个班
JwtDecoderFactory JwtDecoderFactory=getJwtDecoderFactoryBean();
获取bean的私有方法如下所示
private JwtDecoderFactory getJwtDecoderFactoryBean(){
ResolvableType=ResolvableType.forClassWithGenerics(JwtDecoderFactory.class,ClientRegistration.class);
字符串[]名称=this.getBuilder().getSharedObject(ApplicationContext.class).getBeanNamesfortType(类型);
如果(names.length>1){
抛出新的NonuniqueBeandDefinitionException(类型、名称);
}
如果(names.length==1){
返回(JwtDecoderFactory)this.getBuilder().getSharedObject(ApplicationContext.class).getBean(名称[0]);
}
返回null;
}
即使在5.2.x版本中,我也面临同样的问题。在我的例子中,真正的问题不在JWT解码器中。我已经通过设置jwk set uri属性解决了这个问题(您可以通过正在使用的提供商更改提供商名称,例如okta、google等):
(在寻找覆盖Jwt和Oidc令牌验证的解决方案时发现了这一点。Filip帮助我找到了解决方案,所以我想我应该添加这一点,以帮助遵循相同搜索的任何人。)
对于时间旅行测试场景,我们的jvm时钟设置为未来几个月。由于对Jwt和Oidc令牌时间戳进行了验证,登录失败
这一添加适用于我们在Spring Security 5.2.1上的应用程序
@Bean
public JwtDecoderFactory<ClientRegistration> getJWTDecoder() {
OidcIdTokenDecoderFactory factory = new OidcIdTokenDecoderFactory();
factory.setJwtValidatorFactory(new Function<ClientRegistration, OAuth2TokenValidator<Jwt>>() {
@Override
public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
return new CustomTimestampIgnoringOidcTokenValidator(clientRegistration);
}
});
}
@Bean
公共JwtDecoderFactory getJWTDecoder(){
OidcIdTokenDecoderFactory=新的OidcIdTokenDecoderFactory();
setJwtValidatorFactory(新函数(){
@凌驾
公共OAuth2TokenValidator应用(ClientRegistration ClientRegistration){
返回新的CustomTimesIgnoringOidCtokenValidator(clientRegistration);
}
});
}
这只是将默认验证器替换为只验证其他声明的自定义验证器。我使用的是最新版本5.1.3.Release,它还没有此工厂。我已更新了答案。除了用自己的身份验证提供程序替换整个身份验证提供程序之外,没有什么好的解决方案。
@Bean
public JwtDecoderFactory<ClientRegistration> getJWTDecoder() {
OidcIdTokenDecoderFactory factory = new OidcIdTokenDecoderFactory();
factory.setJwtValidatorFactory(new Function<ClientRegistration, OAuth2TokenValidator<Jwt>>() {
@Override
public OAuth2TokenValidator<Jwt> apply(ClientRegistration clientRegistration) {
return new CustomTimestampIgnoringOidcTokenValidator(clientRegistration);
}
});
}