How to: Restrict access to a Keycloak client to self-registered user accounts

Use Case: Restrict Access to a Client in Keycloak for Self-Registered Users

In Keycloak, a common method to restrict access to specific clients is through roles, groups, or group membership attributes (see our documentation for default configurations). This article provides an example of how to configure authorization based on a role assigned to all accounts in a specific backend of the user federation. The goal is to ensure that only self-registered users from the Univention self-service app can access a particular client.

Background

The Univention Self-Service module does not create separate groups or assign memberships to self-registered accounts. By default, these accounts are created in their own container, directly under the root of the LDAP directory (here: "cn=self registered users,dc=test,dc=intranet").

While there are various ways to implement restricted access in Keycloak and/or UCS, this guide presents a solution that requires no additional programming. It involves separating normal user accounts and self-registered accounts into two distinct user federations in Keycloak. The federation containing self-registered users will use the so-called “hardcoded role mapper” to automatically assign a specific role to all accounts in this federation.

Step-by-Step Configuration

Create a Realm Role for Self-Registered Users

  1. In the left navigation menu, go to Realm Roles and click Create role.
  2. Give the role a meaningful name, such as guest.
  3. Optionally, add a description.
  4. Save the role.

Add a separate provider to the user federation

Please note that you can not just apply this change without checking if it fits the structure of your LDAP directory. To avoid duplicate accounts in Keycloak, ensure that the search bases for regular users and self-registered users do not overlap or work with priorities. The following is an approach based on the simple default structure:

Modify the default user federation (called “ldap-provider”)

In the Settings tab, under LDAP Searching and Updating, adjust the Users DN to the more specific cn=users,dc=test,dc=intranet (instead of dc=test,dc=intranet).

Create a new provider

  1. Go to User Federation in the left navigation and click Add provider.
  2. Settings Tab:
    • UI Display Name: selfservice
    • Vendor: Other
    • Connection and Authentication Settings: Use the same connection settings and bind credentials as in the default “ldap-provider”. The bind password is stored in /etc/idp-ldap-user.secret.
  3. LDAP Searching and Updating:
    • Edit Mode: READ_ONLY
    • Users DN: cn=self-registered-users,dc=test,dc=intranet (adapt to your LDAP setup)
    • Username LDAP Attribute: uid
    • RDN LDAP Attribute: uid
    • UUID LDAP Attribute: entryUUID
    • User Object Classes: person, organizationalPerson, univentionPasswordSelfService
    • User LDAP Filter: (uid=*)
    • Search Scope: One Level
    • Pagination: On
    • Kerberos Integration: Allow Kerberos Authentication = Off
  4. Save the settings and proceed to the Mappers tab.

Add Mappers for LDAP Attributes to the new provider

Add mappers for the LDAP attributes you need. Typically, you will need at least the following attributes:

  • uid
  • displayName
  • entryUUID

For each attribute:

  1. Click Add mapper.
  2. Enter the name of the attribute.
  3. Select Mapper type: user-attribute-ldap-mapper.
  4. Fill out the form as per the configuration in your ldap-provider.

Assign a Hardcoded Role to Self-Registered Users

  1. Click Add Mapper.

  2. Name: guests-mapper

  3. Mapper Type: hardcoded-ldap-role-mapper

  4. Select Role: Click Select role.

  5. In the filter, choose Filter by realm roles, then select the guest role and click Assign.keycloak-assign-realm-role

  6. Save the mapper.

Adjust User Federation Priorities

The following can help you avoid duplicates if the directory with your regular users has a more complicated structure. To ensure that the self-registered users’ federation is used first, go to Manage priorities in the User Providers overview and move the self-registered users provider to the top. This will prevent the regular LDAP provider from being queried if the username exists in the self-registered users federation.
keycloak-manage-prios

keycloak-prio-selfservice

Create a Custom Authentication Flow

  1. Run the following command to create a custom authentication flow:

    univention-keycloak legacy-authentication-flow create
    
  2. Assign this authentication flow to the client you wish to restrict access to:

    univention-keycloak client-auth-flow --clientid "REPLACE_WITH_YOUR_CLIENT_ID" --auth-flow "browser flow with legacy app authorization"
    

Configure the “Univention App Authenticator”

The Univention App Authenticator is a built-in authenticator that checks if the logged-in user is authorized to access the client application. It requires a role to be configured on the Keycloak client, specifically looking for the client role univentionClientAccess.

  1. Go to the client configuration in Keycloak.
  2. Open the Roles tab and click Create role.
  3. Name the role univentionClientAccess and save it.

Now link the client-specific role with the authorized accounts:

  1. Go to Realm Roles, select your guest role, and open the Actions menu in the upper right corner.
  2. Select Add associated roles.
  3. In the filter, choose Filter by clients and select the client ID with the univentionClientAccess role.keycloak-connect-client-with-guest-role
  4. Click Assign.

Test the Configuration

Open a new browser window (ensuring no previous login cookies are present) and test the authentication process.

Edit: Please test this configuration thoroughly after app updates. While the manually added user federation provider will not be modified during updates, minor changes to the default “ldap-provider” may occur.

This approach ensures that only self-registered users are able to access the client, leveraging Keycloak’s role mapping and user federation features without requiring custom coding.

Credits: @jbremer @botner

3 Likes

This topic was automatically closed after 24 hours. New replies are no longer allowed.

Mastodon