Keycloak AttributeToRoleMapper with multiple values - keycloak

My project has a SAML identity provider with multiple roles which we would like to map to a single role in our Keycloak server.
Unfortunately, the isAttributePresent method expects to only have one IdP role mapped and checked in the SAML response.
If you create one mapper for each IdP role mapped to a single role, the login flow will fail after the second login because the mappers are evaluated one by one and if the last one to be evaluated fails, the role is removed.
Mappers:
mapper1 - IdpRole1 -> KC_ROLE
mapper2 - IdpRole2 -> KC_ROLE
Users:
user1 - has IdpRole1, IdpRole2
user2 - has IdpRole1
user3 - has IdpRole2
user1:
first login:
importNewUser is called for mapper1, KC_ROLE is associated
importNewUser is called for mapper2, KC_ROLE is associated
second login:
updateBrokeredUser is called for mapper1, KC_ROLE is associated
updateBrokeredUser is called for mapper2, KC_ROLE is associated
user2:
first login:
importNewUser is called for mapper1, KC_ROLE is associated
importNewUser is called for mapper2, KC_ROLE is associated
second login:
updateBrokeredUser is called for mapper1, KC_ROLE is associated
updateBrokeredUser is called for mapper2, KC_ROLE is removed
user3:
first login:
importNewUser is called for mapper1, KC_ROLE is associated
importNewUser is called for mapper2, KC_ROLE is associated
second login:
updateBrokeredUser is called for mapper1, KC_ROLE is removed
updateBrokeredUser is called for mapper2, KC_ROLE is associated
Therefore, user1 and user 3 will have the role, but user2 will not.
Are there any workarounds to this? Is there any plan for supporting multiple values?

As for a possible workaround, you will have to map the roles one by one and then to configure the application with all the needed roles to be granted on it.
Alternatively, you can opt for creating your own mapper that can have multiple values (but this is an extension/integration topic).
Another possible workaround would be to perform a mapping and consolidate the attributes at the intermediate/external SAML IdP level which used for the identity provider federation so that the Keycloak instance only gets a single attribute to map to the realm role in keycloak.

Related

PostgreSQL representing different types of relations

I have a PostgreSQL database for representing relational data. In my case the tables are as follows:
User: Basic user
Issuer: Upgraded user
Badge: Badge to issue, can only be created by issuer, and can be issued to any type of user
The relation between the tables are as follows:
Issuer - User: one to one, basic info of issuers are held in User table, issuer related info are held in Issuer table
Issuer - Badge: one to many, an issuer can create multiple unique badges
Badge - User: many to many, one user can hold multiple diff. badges and a badge can be issued to multiple diff. users
Should I combine User and Issuer tables into one and add a field to indicate the role of the user, or should I keep them separated? Note that Issuer has multiple fields that are unique to them (such as createdBadges). This way User will have both createdBadges and issuedBadges fields.
Should I create separate table for indicating the relation between Badge and User called Issuances, or should I just have array references to each other?
I want better logical coherency, better management, and higher efficiency.
issuer gets a NOT NULL foreign key to users with a unique constraint on it
badge gets a NOT NULL foreign key to issuer
a junction table user_badge has NOT NULL foreign keys to both users and badge and a primary key that is composed of both foreign keys
Don't call a table user, since that is a reserved word in SQL.

Taking the Name of the ROLE the user is in and populating it to a pick-list on the Opportunity

My customer has created roles with the names of the company's business divisions and sub-divisions. He wants to take the role the creating user is in, along with the next level up Role and populate that into two fields on the opportunity, to then use those two fields. (ROLE and SUB-ROLE) as Dashboard filters. Since the role is in the setup section and is also not a field on the user record, I'm assuming some type of Apex Trigger or Flow would be needed to take the role names of the creating user and then insert them?
They are new to Salesforce.. they have not tried anything yet.

KeyCloak composite role not added to access_token

Could not understand why my composite role not added to access_token. I created a simple role (named Child) and assigned it to a user. Then I created a composite role (named Parent) and linked with Child role. I suppose that composite role will be added to access token, but this didn't happen.
A user to whom is granted a composite role will inherent all roles within the composite role. Notice the word "within".
So if the role "Child" was composed by the role "Parent" (Child -> Parent) and you assign the role "Child" to a user then that user will also get the role "Parent" assign to it. However, if you had just assigned the role "Parent" to the user, then that user would only get the role "Parent".
This is what is happening in your use-case, you have the role "Parent" that is composed by the role "Child" (Parent -> Child) if you assign the role "Child" to the user you will not see the "Parent" there. However, if you assign the role Parent to the user, you will see both the "Parent" and "Child" roles assigned to that user.

Use ldap attribute for role-ldap-mapper role name

I'm trying to sync my roles from my LDAP to keycloak. As i have objects in my Domain that share the name of my needed roles i can't use the cn as "Role Name LDAP Attribute". Instead i want to create groups with a prefix like keycloak-mygroup and omit said prefix in the keycloak roles.
If that isn't possible, i'd like to create these groups with a prefix and use another attribute of the group as a role name. The roles i want to sync, already exist in my keycloak instance.
If i try to use an attribute like description i get an error ("Violation of UNIQUE KEY constraint "UK_J3RWUVD56ONTGSUHOGM184WW2-2". A duplicate key cannot be inserted into the dbo.KEYCLOAK_ROLE object. The duplicate key value is (, default).") and if i use an attribute like distinguishedName (those roles don't exist) everything is created.
How can i use a different attribute than cn for my role names and have it sync?
I was able to solve this problem. The error happens if a group is missing the attribute used for the group name. Every group has to have the used attribute, otherwise the sync will fail for all groups.

Keycloak client mapper to show the relam name as individual attibute in JWT token

By default keycloak (here version 11) provides information about the realm, a token was fetched for, only parsing the iss attribute of the token payload. e.g.
{
"exp": ...,
"iat": ...,
"jti": "...",
"iss": "http://localhost:8088/idp-provider-context/auth/realms/realmname",
"aud": [...
Is there a build in way, like a client mapper, to add the information about the realm name directly as a dedicated attribute to the JWT-token?
One workaround would be to add an attribute "realmname" to each user and setting the realmname as the value. But on the one hand this seems to be a bit messy, as it is redundant information. On the other hand this could speed up the application a bit, as tokens/users without this attribute or the wrong value in it could be already count as invalid without requesting the backend. This would identify users not created in the desired process, defined for the application.
Instead of a user attribute, use a Client Mapper Instead. For that go to:
Select your realm
Go to clients
Select the appropriate client for your use-case
(For the OLD Keycloak UI)
Go to Mappers
Click Create
In Mapper type select Hardcoded claim
Fill up the field Token Claim Name as realm name
Fill up the field Claim value as the name of the realm
Fill up the renaming fields, accordingly.
Click on Save
(For the NEW Keycloak UI)
Go to the tab Client Scopes
Click on the scope -dedicated (e.g., test-dedicated in my example)
Click on Configure a new mapper (or Add Mapper > By configuration if you have already created mappers before for this client)
Select Hardcoded claim
Fill up the field Token Claim Name as realm name
Fill up the field Claim value as the name of the realm
Fill up the renaming fields, accordingly.
Click on Save
The client will be the client that you are using to authenticate against.