问题描述
我让Jhipster与Oauth2 + Keycloak一起运行。
我有一个用例,需要从Jhipster React UI更新用户的姓氏和名字,因此我通过服务帐户使用Keycloak管理客户端来更新Keycloak中的用户属性。
问题在于需要将信息重新获取到OIDC令牌,以使用户立即看到更改。 (此处类似的问题:https://github.com/jhipster/generator-jhipster/issues/7398)
有没有建议如何设置Spring Security以便能够使用最新的信息形式Keycloak或任何明确的调用来重新获取/刷新我的令牌?
感谢answears!
解决方法
因此,从工作流程的角度来看,我能够通过以下方式解决问题:
- 通过 Keycloak 管理客户端更改数据
- 更改 Spring Security Context 中的数据
我对 spring 安全性有一个错误的假设,即每次调用时它都会根据存储在上下文中的实际令牌验证令牌数据。事实证明,通过更改上下文中的数据,spring security 没有问题,因此在下次登录时,我可以获得与实际数据内联的有效令牌。
这是我能够改变上下文的代码:
public void updateUserRole(AbstractAuthenticationToken abstractAuthenticationToken)
{
SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneByLogin)
.ifPresent(user -> {
Set<Authority> authorities = user.getAuthorities();
Authority authority = new Authority();
authority.setName(AuthoritiesConstants.USER);
authorities.remove(AuthoritiesConstants.INVITED);
authorities.add(authority);
user.setAuthorities(authorities);
this.clearUserCaches(user);
log.debug("Changed Information for User: {}",user);
});
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = List.of(new SimpleGrantedAuthority(AuthoritiesConstants.USER));
Map<String,Object> claims = ((OidcIdToken)((DefaultOidcUser)((OAuth2AuthenticationToken)abstractAuthenticationToken).getPrincipal()).getIdToken()).getClaims();
String userNameKey = ((OAuth2AuthenticationToken)authentication).getAuthorizedClientRegistrationId();
String tokenValue = ((OidcIdToken) ((DefaultOidcUser) ((OAuth2AuthenticationToken) abstractAuthenticationToken).getPrincipal()).getIdToken()).getTokenValue();
Instant issuedAt = ((OidcIdToken) ((DefaultOidcUser) ((OAuth2AuthenticationToken) abstractAuthenticationToken).getPrincipal()).getIdToken()).getIssuedAt();
Instant expiresAt = ((OidcIdToken) ((DefaultOidcUser) ((OAuth2AuthenticationToken) abstractAuthenticationToken).getPrincipal()).getIdToken()).getExpiresAt();
OidcIdToken oidcIdToken = new OidcIdToken(tokenValue,issuedAt,expiresAt,claims);
DefaultOidcUser user = new DefaultOidcUser(authorities,oidcIdToken,"name");
OAuth2AuthenticationToken oAuth2AuthenticationToken = new OAuth2AuthenticationToken(user,authorities,userNameKey);
SecurityContextHolder.getContext().setAuthentication(oAuth2AuthenticationToken);
}