How to setup roles in Keycloak

Limited Time Offer!

For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly.
Master DevOps, SRE, DevSecOps Skills!

Enroll Now

A) Create / prepare your Realm

  1. Sign in to Keycloak Admin Console.
  2. Top-left realm selector → Create realm (e.g., acme).

B) Define your roles (admin / manager / user)

You can use Realm Roles (recommended for app-wide roles) or Client Roles (scoped to a single client). We’ll use Realm Roles.

  1. In left nav, RolesAdd role:
    • Create admin, manager, user.
  2. (Optional but tidy) Groups → Add groups admins, managers, users.
    • Inside each group → Role mappingsAssign role → add the matching realm role.
    • Later, just put users in groups; they’ll inherit the role.

Result: your tokens can include these realm roles under realm_access.roles.


C) Create the OIDC Client for Laravel

You have two safe choices. Pick one:

Option 1 — Public client + PKCE (no secret)

  • Good when you don’t want to store a secret or might ever do a browser-based flow.

Option 2 — Confidential client (has a secret)

  • Also fine for server-side Laravel Socialite (secret stays on your server).

Steps (common; I’ll note the one-line difference for each option):

  1. Left nav ClientsCreate client
    • Client type: OpenID Connect
    • Client ID: laravel-app (must match KEYCLOAK_CLIENT_ID in .env)
    • Name: (anything)
    • Always display in UI: your choice
    • Click Next
  2. Capability config:
    • Client authentication:
      • OFF for Public + PKCE (Option 1)
      • ON for Confidential (Option 2)
    • Authorization: OFF (not needed)
    • Click Next
  3. Login settings:
    • Valid redirect URIs: add your Laravel callback(s)
      • http://localhost:8000/auth/callback
      • https://yourapp.example.com/auth/callback
    • Web origins: add exact origins you’ll use (e.g., http://localhost:8000, https://yourapp.example.com). Avoid * in prod.
    • Root URL (optional but nice): your site’s base URL.
    • Save.
  4. If you chose Option 1 (Public + PKCE):
    • Client → Advanced (or Settings, depending on version) → ensure PKCE is Required, Method = S256.
  5. If you chose Option 2 (Confidential):
    • Client → Credentials tab → copy the Client Secret to your Laravel .env (KEYCLOAK_CLIENT_SECRET).

Make sure Standard Flow (Authorization Code) is enabled; it is enabled by default for new OIDC clients. We’re not using Implicit or Direct Access Grants.


D) Ensure roles are sent in tokens

Keycloak includes claims based on Client Scopes.

  1. Client scopes (left nav) → confirm a built-in scope named roles exists (it normally does).
    • Inside it there’s a mapper for realm roles (go to “Mappers” and see “realm roles” / “roles”).
  2. Go to your Client → Client scopes:
    • Under Assigned default client scopes, ensure roles is present.
    • If not, Add client scope → pick roles.
  3. Keep profile and email in default scopes as well (usually already there).

Result: your ID token and Access token will include roles.

  • Realm roles → realm_access.roles
  • If you ever use client roles → resource_access[clientId].roles

Your Laravel callback code (from earlier) merges both; you’re covered either way.


E) Create users and assign roles

  1. UsersAdd user → fill username, email, etc. Save.
  2. Credentials tab → set password (toggle temporary off if you want).
  3. Assign role:
    • Either Role mappingsAssign role → pick admin/manager/user, Add.
    • Or put the user in a Group that already has the role.

Logins via social providers (Google/Apple) configured in Keycloak can also be mapped to these roles—see Section G.


F) Double-check client settings against Laravel .env

In Laravel you set:

KEYCLOAK_BASE_URL=http://localhost:8080      # or https://kc.yourdomain.com
KEYCLOAK_REALM=acme
KEYCLOAK_CLIENT_ID=laravel-app
KEYCLOAK_CLIENT_SECRET=   # only for confidential clients
KEYCLOAK_REDIRECT_URI=http://localhost:8000/auth/callback

In Keycloak client:

  • Client ID = laravel-app
  • Redirect URI includes /auth/callback
  • Web origins include your app’s origins
  • If Public client: PKCE required (S256)
  • If Confidential: Client secret matches .env

G) (Optional) Add Google/Apple login to Keycloak (federated IdP)

If you want users to log in with Google/Apple into Keycloak (and still get your Laravel roles):

  1. Identity ProvidersAdd provider → choose Google (or Apple).
  2. Enter Google/Apple Client ID/Secret (from their developer consoles).
  3. Save. Try login from the Keycloak login page → you’ll see a Google/Apple button.
  4. Map to roles:
    • Use User Attribute → Role approach or Group Mapper:
      • Create a Group (e.g., admins) with role admin attached.
      • In Identity Providers → Mappers, add a mapper that puts users into that group based on an IdP attribute (e.g., email domain).
      • Alternatively, run a small post-login admin action to assign roles manually.

This keeps all SSO sources behind Keycloak; Laravel just sees a standard OIDC login.


H) (Optional) Single Logout (SLO)

If you want to log users out of Keycloak too (not just Laravel session):

  • Use Keycloak’s end-session endpoint: {KEYCLOAK_BASE_URL}/realms/{REALM}/protocol/openid-connect/logout ?post_logout_redirect_uri={APP_URL_ENCODED} &id_token_hint={ID_TOKEN}
  • You already capture id_token in the callback; you can stash it in session and call this on logout.
  • If you skip SLO, your app will log out locally, but the Keycloak session remains until it expires.

I) Quick test flow

  1. Start Keycloak (dev example): docker run -p 8080:8080 \ -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:25.0.6 start-dev
  2. Create realm, roles, client, user (as above).
  3. Run Laravel: php artisan serve
  4. Visit http://localhost:8000/login → you should be redirected to Keycloak.
  5. Log in with the test user (e.g., role manager) → you should land on /dashboard and only routes allowed by role:manager should work.

J) Troubleshooting

  • Redirect URI mismatch → Ensure the exact URI (including scheme, host, port, path) is in “Valid redirect URIs.”
  • 403 on protected routes → Token didn’t include roles:
    • Confirm roles client scope is assigned to the client.
    • Confirm the user actually has admin/manager/user (Role mappings or via Group).
    • Confirm you request the roles scope in Laravel (->scopes(['openid','profile','email','roles'])).
  • CORS errors → Add your site origin(s) under Web origins.
  • Time/clock skew → If tokens seem “not yet valid,” ensure Keycloak and server time are in sync (NTP).
  • Confidential client → If code exchange fails, re-check the Client Secret in your .env.

That’s it

Once these steps are done, your Laravel app’s Socialite flow will receive an ID token containing realm_access.roles (and client roles if you ever use them), and your middleware will gate /admin, /manager, /user accordingly.

If you want, I can also give you a minimal Keycloak realm export (JSON) with the roles, a demo client pre-configured for http://localhost:8000/auth/callback, and a sample user—ready to import.

Senior Software Development Engineer at Cotocus

Related Posts

Complete Tutorial: Fixing Keycloak UDP Socket Exhaustion, DNS Failure, GitHub Resolution Error, and Laravel Guzzle ConnectException on a Single Server

Limited Time Offer! For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly. Master DevOps, SRE, DevSecOps Skills! Enroll Now This…

Read More

Keycloak Multi-Client Architecture with Project-Based Email Validation (Student, Trainer, Company, Consulting)

Limited Time Offer! For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly. Master DevOps, SRE, DevSecOps Skills! Enroll Now When…

Read More

Complete Step-by-Step Guide to Running and Managing Keycloak 26.3.3 on Linux (Production Ready)

Limited Time Offer! For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly. Master DevOps, SRE, DevSecOps Skills! Enroll Now 1….

Read More

Complete Tutorial: Running Keycloak 26.x on Ubuntu with LAMPP (MariaDB) in Production

Limited Time Offer! For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly. Master DevOps, SRE, DevSecOps Skills! Enroll Now 1….

Read More

Complete Guide: Migrating Legacy Wizbrand Users to Keycloak & Customizing Email Templates

Limited Time Offer! For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly. Master DevOps, SRE, DevSecOps Skills! Enroll Now When…

Read More
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments