How can one read/import the roles from an external IDP into Keycloak

I have a spring boot application secured with Keycloak 11.0.2, and my Keycloak setup is as follows:

  • A Realm named Central with a role CentralWebUser and a client SpringWeb. The client has
    • Access Type : public and only one flow enabled, namely Standard Flow Enabled
    • Valid Redirect URIs : http://localhost:8000/*
  • A 2ª realm named SpringApp with a role WebUser and a client spring_brokering
    • A user named springuser with the realm role WebUser
    • The client spring_brokering has only the Standard Flow Enabled set to ON, Valid Redirect URIs : http://localhost:8080/*, and Access Type : Confidential

The second realm is an IDP of the first. So to login a user goes to the Central login page and selects the IDP SpringAppIDP.

The IDP configuration is as follows:

  • alias : SpringAppIDP, with everything else being OFF except for the option enabled
  • The Authorization URL, Token URL, and so on are set to the URLs from the SpringApp endpoints (e.g., Authorization URL : http://127.0.0.1:8080/auth/realms/SpringApp/protocol/openid-connect/auth)
  • Client ID and Client secret are the spring_brokering and its secret, respectively.

On the Spring side, I have the following properties worth mentioning:

server.port                         = 8000
keycloak.realm                      = Central
keycloak.auth-server-url            = http://localhost:8080/auth
keycloak.ssl-required               = external
keycloak.resource                   = SpringWeb
keycloak.public-client=true

keycloak.security-constraints[0].authRoles[0]=WebUser
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/services/*

When I access http://127.0.0.1:8080/services I got redirected to the Keycloak Central Realm Login page, then I click the SpringAppIDP and enter the username springuser and its password. The login is successful, but I got an access denied, which means that the user springuser does not have the role WebUser. However, that role was assigned to that user within the second realm (i.e., SpringApp).

Interestingly, if in the first Realm I create an identity provider Mapper External Role to Role (in the IDP SpringAppIDP configuration) mapping the external role of WebUser to the CentralWebUser and change the spring properties to :

keycloak.security-constraints[0].authRoles[0]=CentralWebUser
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/services/*

I am able to login, which means that Keycloak knew that the user had the WebUser role, hence mapping that role to the CentralWebUser role.

I would like to know if it is possible to explicitly import the roles from an external IDP into an internal one? Or if (and how) can I request a token in behalf to the user that would have that users’ roles from both the Central and SpringWeb Realm in the that token, without having to explicitly creating a Role Mapper for each user role.

Hi Dreamcrash,

Were you able to solve this? I have the same problem

  • I want to login with an ext identity provider (which I am able to with Azure AD)
  • On login - I want the roles to be part of the AccessToken - but the roles should come from an external DB or User/RoleProvider in Keycloak.

Any suggestions pls let me know.

thank you,
-Anand

Hi anand, I have found a solution but not the one I wanted I end up using Role Mapper for each of the roles. I have yet to try with token exchange. But if your interested I can add a more in detail explanation and added as an answer to this

Hey thanks for the response.

I ended up impl probably the same way you did UserClientRoleMappingMapper.java

Good for now.

regards,
-Anand

Actually, I had to do two Role Mappers, one from the External DB into the External IDP realm, another from the External lDP to the Internal IDP.

I endup using this approach: