Limited Time Offer!
For Less Than the Cost of a Starbucks Coffee, Access All DevOpsSchool Videos on YouTube Unlimitedly.
Master DevOps, SRE, DevSecOps Skills!
A) Create / prepare your Realm
- Sign in to Keycloak Admin Console.
- 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.
- In left nav, Roles โ Add role:
- Create
admin
,manager
,user
.
- Create
- (Optional but tidy) Groups โ Add groups
admins
,managers
,users
.- Inside each group โ Role mappings โ Assign 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):
- Left nav Clients โ Create client
- Client type: OpenID Connect
- Client ID:
laravel-app
(must matchKEYCLOAK_CLIENT_ID
in.env
) - Name: (anything)
- Always display in UI: your choice
- Click Next
- Capability config:
- Client authentication:
- OFF for Public + PKCE (Option 1)
- ON for Confidential (Option 2)
- Authorization: OFF (not needed)
- Click Next
- Client authentication:
- 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.
- Valid redirect URIs: add your Laravel callback(s)
- If you chose Option 1 (Public + PKCE):
- Client โ Advanced (or Settings, depending on version) โ ensure PKCE is Required, Method =
S256
.
- Client โ Advanced (or Settings, depending on version) โ ensure PKCE is Required, Method =
- If you chose Option 2 (Confidential):
- Client โ Credentials tab โ copy the Client Secret to your Laravel
.env
(KEYCLOAK_CLIENT_SECRET
).
- Client โ Credentials tab โ copy the Client Secret to your Laravel
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.
- 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โ).
- Go to your Client โ Client scopes:
- Under Assigned default client scopes, ensure
roles
is present. - If not, Add client scope โ pick
roles
.
- Under Assigned default client scopes, ensure
- Keep
profile
andemail
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
- Users โ Add user โ fill username, email, etc. Save.
- Credentials tab โ set password (toggle temporary off if you want).
- Assign role:
- Either Role mappings โ Assign role โ pick
admin
/manager
/user
, Add. - Or put the user in a Group that already has the role.
- Either Role mappings โ Assign role โ pick
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):
- Identity Providers โ Add provider โ choose Google (or Apple).
- Enter Google/Apple Client ID/Secret (from their developer consoles).
- Save. Try login from the Keycloak login page โ youโll see a Google/Apple button.
- Map to roles:
- Use User Attribute โ Role approach or Group Mapper:
- Create a Group (e.g.,
admins
) with roleadmin
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.
- Create a Group (e.g.,
- Use User Attribute โ Role approach or Group Mapper:
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
- 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
- Create realm, roles, client, user (as above).
- Run Laravel:
php artisan serve
- Visit
http://localhost:8000/login
โ you should be redirected to Keycloak. - Log in with the test user (e.g., role
manager
) โ you should land on/dashboard
and only routes allowed byrole: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'])
).
- Confirm
- 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.
Leave a Reply