Require a Keycloak Role in an Authentication Flow

August 12, 2025

Overview

By default, Keycloak does not ship with any authentication flows that require a user to have a given role. For example, we can gate access to an application by requiring users have an app:login or app:access role. We may then assign this role to a group of users, paving the way for a proper RBAC/GBAC ready access flow.

Implementation

Duplicate Existing Flow

Copy an existing role that has your existing requirements. In my case, this is a modified browser flow with webauthn support and mandatory MFA.

  1. Navigate to Authentication
  2. Duplicate the flow you wish to use as your base flow. duplicate.webp
  3. You should now have a starting point to make our RBAC changes

Adjust Existing Flow

The existing flow needs to be converted to a sub-flow. This will switch the final login logic to:

if ($user->login->is_success and $user->hasRole('my-role'))

Unfortunately there is no way to drag and drop components into a subflow, so they must be changed by hand.

  1. Create a new subflow called login and move it to the top of the flow
  2. Set the flow to Required
  3. Manually recreate all of the existing steps as steps inside the subflow.
    1. Click on the + for the subflow and click add step
    2. Duplicate an existing step
  4. Delete the original step
  5. Repeat these steps for all existing flow steps login-flow

Implement RBAC

Implementing RBAC is fairly straightforward - we add a conditional flow with inverse logic that denies users.

DENY unless (exists $roles->{'my-role'})
  1. Create a new subflow AFTER the login form
  2. Set the new subflow to conditional so it only runs if a condition is met
  3. Add a condition:
    1. Set the type to user role
    2. Once created, switch it from disabled to required
    3. Click the gear to edit and set the following:
      1. Set the Alias to a description of what is triggering (require-app:login)
      2. Select the role you with to check against
      3. Switch Negate output from Off to On
  4. Add a new Deny step
  5. Set the Deny step to Required rbac-flow

Final Flow

The logic for the authentication flow provided should now be:

if (
     ($user->hasCookie or
      $user->alternativeIdentity->is_success or
      ($user->password->is_success and
        ($user->webauthn->is_success or
          $user->otp->is_success
        )
      )
     ) and
     $user->hasRole('my-role')
  )

Binding the Flow

Because this flow requires a user role to succeed, it is not likely that it can be used as a general authentication flow. Instead, we will bind it to a specific client’s browser flow.

  1. Navigate to the client you wish to use the RBAC flow with
  2. Click Advanced
  3. Click Authentication flow overrides
  4. Select your new flow from the dropdown for Browser Flow override

Testing the Flow

user mfa missing role: rbac-fail has role: rbac-success