I have a requirement to use a different source to load the user details, authentication and user’s role assignment while generating OpenID tokens with grant_type ‘password’ from KeyCloak.
I have been able to successfully configure an implementation of UserStorageProvider and generate an OpenID tokens. In this case I have implemented the user storage only. My token contains any roles from realm and the client. I want to load additional roles from the third party provider (a user repository) which was used to construct the custom UserStorageProvider. For this I have created a CustomRole class which implements RoleModel interface.
@Override
public UserModel getUserById(String id, RealmModel realm) {
// the logic to fetch the user model
roleName = fetched from the third party source based on the user id
userModel.getClientRoleMappings(session.getContext().getClient()).add(new CustomRole(roleName, roleName, true,session.getContext().getClient()));
}
@Override
public UserModel getUserByUsername(String username, RealmModel realm) {
// the logic to fetch the user model
roleName = fetched from the third party source based on the user id
userModel.getClientRoleMappings(session.getContext().getClient()).add(new CustomRole(roleName, roleName, true,session.getContext().getClient()));
}
@Override
public UserModel getUserByEmail(String email, RealmModel realm) {
// the logic to fetch the user model
roleName = fetched from the third party source based on the user id
userModel.getClientRoleMappings(session.getContext().getClient()).add(new CustomRole(roleName, roleName, true,session.getContext().getClient()));
}
While the above approach does not give any error, I do not see the newly injected roles in the JWT token.
I have configured the protocol mappers correctly so that the same could be achieved when the default configuration via the console is done. That is if I create the user from console and map to client roles from the console it would give me the roles in the token. But the issue is, when I load the user from the custom user storage, I can’t artificially inject those role mappings to the user token.
“protocolMappers”: [
{
“id”: “4b109648-d8e2-4802-a158-69fbf5a17fc6”,
“name”: “realm roles”,
“protocol”: “openid-connect”,
“protocolMapper”: “oidc-usermodel-realm-role-mapper”,
“consentRequired”: false,
“config”: {
“user.attribute”: “foo”,
“access.token.claim”: “true”,
“claim.name”: “realm_access.roles”,
“jsonType.label”: “String”,
“multivalued”: “true”
}
},
{
“id”: “1883daa7-2552-42a5-b156-36d7625bab13”,
“name”: “client roles”,
“protocol”: “openid-connect”,
“protocolMapper”: “oidc-usermodel-client-role-mapper”,
“consentRequired”: false,
“config”: {
“user.attribute”: “foo”,
“access.token.claim”: “true”,
“claim.name”: “resource_access.${client_id}.roles”,
“jsonType.label”: “String”,
“multivalued”: “true”
}
},
{
“id”: “99a36320-7813-4137-a640-83992742b1a8”,
“name”: “groups”,
“protocol”: “openid-connect”,
“protocolMapper”: “oidc-usermodel-realm-role-mapper”,
“consentRequired”: false,
“config”: {
“multivalued”: “true”,
“user.attribute”: “foo”,
“id.token.claim”: “true”,
“access.token.claim”: “true”,
“claim.name”: “groups”,
“jsonType.label”: “String”
}
}
]
Does anyone know how you can look up the same third party source to determine the roles that are being assigned to that user and inject it to the user during the UserModel fetch in custom user storage provider?
I used this article as the basis for my work.
But I am not using a database.
If you can tell me how you can customize a method like in this method in the above article, I would appreciate very much.
private UserModel mapUser(RealmModel realm, ResultSet rs) throws SQLException {
CustomUser user = new CustomUser.Builder(ksession, realm, model, rs.getString(“username”))
.email(rs.getString(“email”))
.firstName(rs.getString(“firstName”))
.lastName(rs.getString(“lastName”))
.birthDate(rs.getDate(“birthDate”))
.build();
// right here I want to inject some custom roles that are not in the key cloak database
return user;
}