使用 keycloak rest admin API (Oauth2) 修改用户姓氏后 jhipster 重新加载 OIDC 令牌

Posted

技术标签:

【中文标题】使用 keycloak rest admin API (Oauth2) 修改用户姓氏后 jhipster 重新加载 OIDC 令牌【英文标题】:jhipster Reload OIDC token after modifying user last name with keycloak rest admin API (Oauth2) 【发布时间】:2020-12-08 00:37:21 【问题描述】:

我让 Jhipster 使用 Oauth2 + Keycloak 运行。

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

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

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

感谢您的回答!

【问题讨论】:

您好,您找到解决方案了吗?我处于同样的情况,用户通过管理客户端正确更新,但 Spring 应用程序仍然依赖旧的令牌数据。我正在考虑一个 hacky 解决方案:使访问令牌无效,并让客户端应用程序在第一个用户更新之后发送另一个请求。然后,无效的访问令牌将使应用程序客户端刷新访问令牌,并从更新的令牌同步数据。我正在寻找更好的解决方案,这并不能说服我太多。 【参考方案1】:

所以从工作流程的角度来看,我能够通过以下方式解决问题:

    通过 Keycloak 管理客户端更改数据 更改 Spring Security Context 中的数据

我对 Spring Security 有一个错误的假设,即它在每次调用时都会根据存储在上下文中的实际令牌来验证令牌数据。事实证明,通过更改上下文中的数据,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);

【讨论】:

以上是关于使用 keycloak rest admin API (Oauth2) 修改用户姓氏后 jhipster 重新加载 OIDC 令牌的主要内容,如果未能解决你的问题,请参考以下文章

使用 Keycloak 中的自定义 Admin REST API 获取用户的 ID 令牌

Keycloak Admin REST API:查询超过 100 个资源对象

使用 keycloak rest admin API (Oauth2) 修改用户姓氏后 jhipster 重新加载 OIDC 令牌

如何在不使用 rest admin api 的情况下以编程方式(java)更新 keycloak 的用户详细信息?

如何通过执行操作电子邮件通过 keycloak admin rest api 更新密码

如何通过 REST API 将 Keycloak 领域角色添加到组