2
votes

I have simple spring boot app which use keycloak SSO with custom user storage provider. Authentication is work fine without user roles. But i need to know how to map existing user roles with custom user storage provider. Does anyone know how to map existing user roles with keycloak user storage provider?

2

2 Answers

4
votes

Finally found a way to map roles.

Add roles to realm and override the AbstractUserAdapterFederatedStorage.getRoleMappingsgetRoleMappings() method.

public Set<RoleModel> getRoleMappings() {
    Set<RoleModel> roles = new HashSet();
    Iterator rolesItr = userEntity.getRoles().iterator();

    while(rolesItr.hasNext()) {
        roles.add(realm.getRole(((Role)rolesItr.next()).getName()));
    }
    return roles;
}
2
votes

If you are using a user storage SPI you'll most likely need to implement the UserLookupProvider interface (org.keycloak.storage.user.UserLookupProvider).

For instance one of the method in that interface is UserModel getUserByUsername(String username, RealmModel realm)

As you can see, the methods in that interface return a UserModel object.

UserModel implements the RoleMapperModel interface. You just have to call the UserModel::grantRole method and pass the roles you want.

Example:

Assuming you have a class MyUserDao {...} that retrieves users from your database as a class MyUserModel {...} instance.

    public UserModel getUserByUsername(String username, RealmModel realm) {
        Optional<MyUserModel> myUserOpt = myUserDao.getUserByUsername(username);
        if (!myUserOpt.isPresent()) 
           throw new AccessDeniedException();
    
        MyUserModel myUser = myUserOpt .get();
    
        UserModel keycloakUser = mapToKeycloakUserModel(myUser);
    
        for (String roleName: myUser.getRoles())
           userModel.grantRole(KeycloakModelUtils.getRoleFromString(realm, roleName));
        
        return keycloakUser;
    }

    private UserModel mapToKeycloakUserModel(MyUserModel myUser) {...}

Note you have to load roles with org.keycloak.models.utils.KeycloakModelUtils::getRoleFromString otherwise UserModel::grantRole will try to re-create them and you'll end up with an exception.