So from workflow point of view I was able to solve the problem by:
- Changing the data via Keycloak admin client
- 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);
}