Spring Security:提取 oidc 角色声明给 Spring 当局
Posted
技术标签:
【中文标题】Spring Security:提取 oidc 角色声明给 Spring 当局【英文标题】:Spring Security: extract oidc role claims to spring authorities 【发布时间】:2021-10-25 08:05:25 【问题描述】:我正在尝试从 OAuth2AuthenticationToken
获取角色声明,以将其检测为 Spring Security 权限。在 OIDC 提供商端(在我的情况下为 Azure AD)定义了一个自定义角色,它嵌套在 DefaultOidcUser
中,但不会自动添加到权限:
我试图从 Jwt 令牌like this 中提取它们
但是,当我这样做时,以下方法都不会被调用(无论是在登录期间,还是在以后,即使在默认配置中也是如此):
JwtGrantedAuthoritiesConverter.convert(Jwt)
JwtAuthenticationConverter.convert(Jwt)
JwtAuthenticationConverter.extractAuthorities(Jwt)
我目前的配置是:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
@Override
public void configure(HttpSecurity http) throws Exception
// @formatter:off
http
.csrf()
<some more config that has nothing to do with oauth/oidc>
.and()
.oauth2Login()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter())
.and()
.and()
.oauth2Client()
;
private JwtAuthenticationConverter jwtAuthenticationConverter()
// create a custom JWT converter to map the roles from the token as granted authorities
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
我也试过了
CustomJwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken>
但无济于事。
任何帮助将不胜感激。
【问题讨论】:
我也尝试了使用 org.springframework.security.oauth.boot.spring-security-oauth2-autoconfigure 的方法,这里建议 baeldung.com/… 但是再次没有调用 extractAuthorities 方法。 实际上,我们通常会与您尝试实现的相反,我们尝试将 JWT 转换为 Spring Security 的GrantedAuthority
。你看过文档docs.spring.io/spring-security/site/docs/current/reference/… 吗?几个月前我有一个几乎类似的问题,我的错误是我混合了 Oauth2 和 Oidc。
我在上面的评论中的意思是,我认为在 Oidc 的情况下我们不能使用JwtAuthenticationConverter
。我不是百分百确定。参见这里docs.spring.io/spring-security/site/docs/current/reference/…
@akuma8 我改进了这个问题,因为我的最终目标是一个不同的目标,并且由于您的回答引导我走向正确的方向,我设法实现了它。非常感谢!
【参考方案1】:
使用权限映射器来实现它,该映射器还从 oidcToken 中提取声明:
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
[...]
@Bean
public GrantedAuthoritiesMapper userAuthoritiesMapper()
return authorities ->
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(
authority ->
// Check for OidcUserAuthority because Spring Security 5.2 returns
// each scope as a GrantedAuthority, which we don't care about.
if (authority instanceof OidcUserAuthority)
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
mappedAuthorities.addAll(SecurityUtils.extractAuthorityFromClaims(oidcUserAuthority.getUserInfo().getClaims()));
mappedAuthorities.addAll(SecurityUtils.extractAuthorityFromClaims(oidcUserAuthority.getIdToken().getClaims()));
);
return mappedAuthorities;
;
在 SecurityUtils 内部:
public static List<GrantedAuthority> extractAuthorityFromClaims(Map<String, Object> claims)
return mapRolesToGrantedAuthorities(getRolesFromClaims(claims));
private static List<GrantedAuthority> mapRolesToGrantedAuthorities(Collection<String> roles)
return roles.stream().filter(role -> role.startsWith("ROLE_")).map(SimpleGrantedAuthority::new).collect(Collectors.toList());
之后,自定义角色应该出现在 mappedAuthorities 中,并与它一起出现在令牌的权限中。从而使注释“hasRole”和“hasAuthority”可以使用。
【讨论】:
以上是关于Spring Security:提取 oidc 角色声明给 Spring 当局的主要内容,如果未能解决你的问题,请参考以下文章
带有 oidc 的 Spring Security:刷新令牌
钥匙斗篷 |使用 Spring Security 的 OIDC 反向通道(单)注销
在多租户 stup 中使用 Spring Security OAuth 动态注册 OIDC 客户端
针对 Azure OIDC OAuth2 流的 Spring Security