0

我让 Jhipster 使用 Oauth2 + Keycloak 运行。

我有一个用例,我需要从 Jhipster React UI 更新用户的姓氏和名字,所以我通过服务帐户使用 Keycloak 管理客户端来更新 Keycloak 中的用户属性。

问题是需要将信息重新提取到 OIDC 令牌才能让用户立即看到更改。(类似的问题:https ://github.com/jhipster/generator-jhipster/issues/7398 )

是否有任何建议如何设置 Spring Security 以便能够使用 Keycloak 的最新信息或任何明确的调用来重新获取/刷新我的令牌?

感谢您的回答!

4

1 回答 1

0

So from workflow point of view I was able to solve the problem by:

  1. Changing the data via Keycloak admin client
  2. Change the data in the Spring Security Context

I had a wrong assumption about spring security that it validates the token data against the actual token stored in the context on every call. It turned out the spring security has no problem by changing the data in the context, so on the next login I can get a valid token what is inline with the actual data.

This is the code I was able to change the context with:

    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);
}
于 2021-06-02T09:06:52.693 回答