Ondrej Sika (sika.io) | [email protected] | Skoleni Keycloak 🚀💻
Freelance DevOps Engineer, Consultant & Lecturer
- Complete DevOps Pipeline
- Open Source / Linux Stack
- Cloud & On-Premise
- Technologies: Git, Gitlab, Gitlab CI, Docker, Kubernetes, Terraform, Prometheus, ELK / EFK, Rancher, Proxmox, DigitalOcean, AWS
Feel free to star this repository or fork it.
If you found bug, create issue or pull request.
Also feel free to propose improvements by creating issues.
For sharing links & "secrets".
- Zoom Chat
- Slack - https://sikapublic.slack.com/
- Microsoft Teams
- https://sika.link/chat (tlk.io)
Keycloak is an open-source identity and access management (IAM) solution developed by Red Hat. It provides authentication and authorization services for applications and services.
- Single Sign-On (SSO): Users can log in once and access multiple applications without re-authenticating.
- Identity Brokering: Supports authentication via third-party identity providers like Google, Microsoft, or LDAP.
- User Federation: Integrates with existing user directories (LDAP, Active Directory).
- Multi-Factor Authentication (MFA): Supports OTP, WebAuthn, and other MFA mechanisms.
- Fine-Grained Authorization: Offers Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC).
- Protocol Support: Works with OpenID Connect (OIDC) and SAML.
- Admin UI, API, and Terraform: Provides an easy-to-use management interface and REST APIs for automation.
- Self-Service Account Management: Users can manage their profiles, passwords, and sessions.
In OIDC & Keycloak, authentication happens via OpenID Connect (OIDC), while authorization is managed via roles, groups, or policies in Keycloak.
- It verifies a user’s identity (e.g., username & password, MFA, or single sign-on).
- Example: Logging into a system with a password.
- It controls access to resources based on permissions and roles.
- Example: A logged-in user can view their profile but not access admin settings.
- Authentication
- Identity verification
- Are you who you claim to be?
- Authorization
- Access control
- What are you allowed to do?
OAuth 2.0 and OpenID Connect (OIDC) are related but serve different purposes
- Purpose: Authorization framework.
- What it does: Allows users to grant third-party applications access to their resources without sharing credentials.
- Example Use Case: A user logs into a service using "Sign in with Google", granting the app access to their Google Drive files.
- Tokens: Issues an access token that applications use to access APIs on behalf of the user.
- No Identity Information: OAuth alone does not provide user authentication or identity details.
- Purpose: Authentication layer on top of OAuth 2.0.
- What it does: Verifies user identity and provides user profile information.
- Example Use Case: A user logs into an application using “Sign in with Google,” and the application gets their email and profile info.
- Tokens: Issues an ID token (JWT) containing user identity details (like name, email, etc.), along with an access token.
- Identity Information: Designed to authenticate users, making it useful for Single Sign-On (SSO).
- OAuth 2.0 is for authorization (who can access what).
- OIDC is for authentication (who the user is).
If you're building a system that requires logging in users securely, you should use OIDC. If you only need to access APIs on behalf of users, OAuth 2.0 is sufficient.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact, URL safe, and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
It is commonly used for authentication and authorization in web applications.
A JWT consists of three parts, separated by dots (.)
- Header – Contains metadata, such as the token type (JWT) and signing algorithm (e.g., HS256, RS256).
- Payload – Contains claims (statements about the user or token), such as user ID, roles, or expiration time.
- Signature – Ensures the integrity of the token using a secret key or public/private key pair.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- A user logs in and receives a JWT from the server.
- The client stores the token (e.g., in localStorage or an HTTP-only cookie).
- With each request, the client includes the JWT in the Authorization header (
Bearer <token>). - The server verifies the JWT’s signature and extracts the payload to determine if the request is authorized.
- Stateless (no need for server-side sessions)
- Compact and efficient (can be sent in headers or URLs)
- Supports various cryptographic algorithms
- Cannot be revoked easily (unless using short expiration and refresh tokens)
- Large payloads increase token size
- Sensitive data should not be stored in the payload, as it can be decoded without the secret key
You can use: https://jwt.io
or use slu jwt parse command
slu jwt parse eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c | jq
Output:
[
{
"alg": "HS256",
"typ": "JWT"
},
{
"iat": 1516239022,
"name": "John Doe",
"sub": "1234567890"
},
"SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
]OAuth 2.0 defines several types of tokens used for different purposes in the authentication and authorization process.
- Grants access to protected resources on behalf of the user.
- Sent in API requests (e.g., Authorization: Bearer ).
- Typically short-lived for security reasons.
- Format varies (JWT, opaque string, etc.), depending on the authorization server.
- Used to obtain a new access token without requiring user interaction.
- Long-lived but can be revoked by the authorization server.
- Not always issued (depends on grant type and server configuration).
- Should be stored securely, as it can be used to generate new access tokens.
OAuth2 does not define ID tokens (those are part of OIDC). It primarily focuses on authorization, not authentication.
In OpenID Connect (OIDC), which is an identity layer built on top of OAuth2, additional tokens are used:
- A JWT (JSON Web Token) that contains identity information about the authenticated user.
- Issued by the OpenID Provider after successful authentication.
- Includes claims such as sub (subject/user ID), email, name, iat (issued at), and exp (expiration).
- Used by the client to verify the user's identity.
In summary
- OAuth2 focuses on authorization (who can access what).
- OIDC adds authentication (who the user is) with ID tokens.
This is a Keycloak Access Token (JWT) containing authentication and authorization details for a user.
- acr: Authentication Context Class Reference (e.g., "1" indicating the authentication level).
- aud: Audience – Specifies the intended recipient of the token (e.g., "account").
- azp: Authorized Party – The client that requested the token (example_client_id).
- exp: Expiration timestamp (Unix time) when the token will expire.
- iat: Issued At – When the token was created.
- iss: Issuer – The Keycloak server that issued the token.
- jti: Unique identifier for the token.
- sid: Session ID – Identifies the user's session.
- sub: Subject – The unique user ID in the Keycloak realm.
- typ: Type of token (e.g., "Bearer").
- scope: The scopes requested during authentication ("openid email profile"), which define what user data is included in the token.
{
"acr": "1",
"aud": "account",
"azp": "example_client_id",
"email": "[email protected]",
"email_verified": true,
"exp": 1740549195,
"family_name": "example",
"given_name": "example",
"iat": 1740548895,
"iss": "https://sso.sikalabs.com/realms/training2",
"jti": "dc0b0a4a-45cf-49e7-bdbf-f3fb1b90f862",
"name": "example example",
"preferred_username": "example_username",
"realm_access": {
"roles": [
"offline_access",
"uma_authorization",
"default-roles-training2"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid email profile",
"sid": "24287475-0fbf-408c-b8cd-355fa245ee3c",
"sub": "e1f6369a-16cf-4573-8a1e-bb19ee416121",
"typ": "Bearer"
}eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4NUdxdnFMT01SdmtNeG4xMmdnaTJFYm1jLVRwZExCQU9tNy1yZko1NkpZIn0.eyJleHAiOjE3NDA1NDkxOTUsImlhdCI6MTc0MDU0ODg5NSwianRpIjoiZGMwYjBhNGEtNDVjZi00OWU3LWJkYmYtZjNmYjFiOTBmODYyIiwiaXNzIjoiaHR0cHM6Ly9zc28uc2lrYWxhYnMuY29tL3JlYWxtcy90cmFpbmluZzIiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiZTFmNjM2OWEtMTZjZi00NTczLThhMWUtYmIxOWVlNDE2MTIxIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiZXhhbXBsZV9jbGllbnRfaWQiLCJzaWQiOiIyNDI4NzQ3NS0wZmJmLTQwOGMtYjhjZC0zNTVmYTI0NWVlM2MiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLXRyYWluaW5nMiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmFtZSI6ImV4YW1wbGUgZXhhbXBsZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImV4YW1wbGVfdXNlcm5hbWUiLCJnaXZlbl9uYW1lIjoiZXhhbXBsZSIsImZhbWlseV9uYW1lIjoiZXhhbXBsZSIsImVtYWlsIjoiZXhhbXBsZUBzaWthZGVtby5jb20ifQ.FUZasx0PAl3jFEAhjhPnM1CUAQPJbkrgilQ8ZL2VPXf-F8Uq7A0_ZMCmUUW70AMyERp76vLRbzK--nwRmgWXlxJvsK9HkOy1A_zRX_Wuq-nQSz2lU2E0VzXJsbFRVx6jcGO-4MJwO1gWpxThesOSueJRCeRcznm_ZrS-DmHscCh1TH3c85KCiHxGweETdC-VG8dDJ74wDu-rqXgIqGwXpUgjIRjrwx3TtJe6YIFx7wSis0QypiQk5fV0g59jX49REp-inDC3JMHUElSrYNsvHEKeIua3vHVfD4k9m0-5SY38BDJIpQ0bWmC3U79YB3tDxnxJKIlmzZNJRlsFN-wtOg
The ID Token in Keycloak is a JWT (JSON Web Token) that provides identity-related claims about the authenticated user. It is primarily used by OpenID Connect (OIDC) clients to obtain user profile information.
Purpose of the ID Token
The ID Token is primarily meant for authentication and providing user identity information to the client application. It is not used for authorization purposes (unlike the Access Token). The client application can decode this token to retrieve user details after successful authentication.
- at_hash: A hash of the Access Token (used for validating access token integrity).
- aud: Audience – Specifies the client ID (example_client_id) for which the token is issued.
- azp: Authorized Party – The client that requested the token.
- exp: Expiration timestamp (Unix time) when the token will expire.
- iat: Issued At – The timestamp when the token was created.
- iss: Issuer – The URL of the Keycloak realm that issued the token.
- jti: Unique identifier for this token.
- sid: Session ID – Identifies the user session.
- sub: Subject – The unique user ID in the Keycloak realm.
- typ: Token type ("ID", indicating this is an ID token).
{
"acr": "1",
"at_hash": "gib9PoLgzImfIMdhuO0UwA",
"aud": "example_client_id",
"azp": "example_client_id",
"email": "[email protected]",
"email_verified": true,
"exp": 1740550026,
"family_name": "example",
"given_name": "example",
"iat": 1740549726,
"iss": "https://sso.sikalabs.com/realms/training2",
"jti": "b819638c-6824-45f6-a312-a62609b9d7a5",
"name": "example example",
"preferred_username": "example_username",
"sid": "4310b043-a925-4e8b-a559-92400204721d",
"sub": "e1f6369a-16cf-4573-8a1e-bb19ee416121",
"typ": "ID"
}eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4NUdxdnFMT01SdmtNeG4xMmdnaTJFYm1jLVRwZExCQU9tNy1yZko1NkpZIn0.eyJleHAiOjE3NDA1NTAwMjYsImlhdCI6MTc0MDU0OTcyNiwianRpIjoiYjgxOTYzOGMtNjgyNC00NWY2LWEzMTItYTYyNjA5YjlkN2E1IiwiaXNzIjoiaHR0cHM6Ly9zc28uc2lrYWxhYnMuY29tL3JlYWxtcy90cmFpbmluZzIiLCJhdWQiOiJleGFtcGxlX2NsaWVudF9pZCIsInN1YiI6ImUxZjYzNjlhLTE2Y2YtNDU3My04YTFlLWJiMTllZTQxNjEyMSIsInR5cCI6IklEIiwiYXpwIjoiZXhhbXBsZV9jbGllbnRfaWQiLCJzaWQiOiI0MzEwYjA0My1hOTI1LTRlOGItYTU1OS05MjQwMDIwNDcyMWQiLCJhdF9oYXNoIjoiZ2liOVBvTGd6SW1mSU1kaHVPMFV3QSIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmFtZSI6ImV4YW1wbGUgZXhhbXBsZSIsInByZWZlcnJlZF91c2VybmFtZSI6ImV4YW1wbGVfdXNlcm5hbWUiLCJnaXZlbl9uYW1lIjoiZXhhbXBsZSIsImZhbWlseV9uYW1lIjoiZXhhbXBsZSIsImVtYWlsIjoiZXhhbXBsZUBzaWthZGVtby5jb20ifQ.pCZL60D76cmMNPrOTvguVx2bxOfrn4jekP94CE_r1vgGzkbyogRBpGayp2LXkmO0mn-uC_mRNPmlTVZzl9HHJOtflWa6Xn_BDLR8bNCXnHN6TeOLY2QoVkmZ7_K1WzOPNG3fQjQ3VHuxH0roScj5mIqTuy3LHBHhBCTGfCdYB2zpuOU9sOuyyngH_hxfLmdvdbh9gRt4sOl1LeQVnOjTZVymRuFCUy9jYP99hhD_wjSsml1BglT2TXlvub3Rxc5Y-BHmxS_u96IYl6wz0w5mjv1OZ0gTjEtMGFwOamv3YEUjFZlGef8lFV9P4jSCRE7F0KNWC2gXIqDj38BgumEbow
https://www.keycloak.org/guides
See example in examples/docker_compose
cd examples/docker-composedocker-compose up -dhelm upgrade --install \
keycloak-sikademo-com \
oci://registry-1.docker.io/bitnamicharts/keycloak \
--version 25.2.0 \
--namespace keycloak-sikademo-com \
--create-namespace \
--values examples/helm_values/keycloak_sikademo_com.yaml
Keycloak will be available on https://keycloak.sikademo.com. Admin user is admin and password is admin.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: keycloak-sikademo-com
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
destination:
namespace: keycloak-sikademo-com
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
source:
repoURL: registry-1.docker.io/bitnamicharts
targetRevision: 24.4.10
chart: keycloak
helm:
valuesObject:
# https://github.com/bitnami/charts/blob/main/bitnami/keycloak/values.yaml
# https://artifacthub.io/packages/helm/bitnami/keycloak?modal=values
replicaCount: 1
global:
security:
allowInsecureImages: true
image:
registry: ghcr.io
repository: sikalabs/bitnami-keycloak-sikalabs-theme
tag: 26.1.2-debian-12-r0
auth:
createAdminUser: true
adminUser: admin
adminPassword: admin
managementUser: management
managementPassword: management
proxyAddressForwarding: true
service:
type: ClusterIP
ingress:
enabled: true
hostname: keycloak.sikademo.com
tls: true
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-body-size: 250m
nginx.ingress.kubernetes.io/proxy-buffer-size: "64k"
cert-manager.io/cluster-issuer: letsencrypt
postgresql:
auth:
postgresPassword: pg
password: pgKeycloak will be available on https://keycloak.sikademo.com. Admin user is admin and password is admin.
Go to https://keycloak.sikademo.com/admin/master/console/#/master/info
terraform {
required_providers {
keycloak = {
source = "keycloak/keycloak"
}
}
}
provider "keycloak" {
client_id = "admin-cli"
url = "http://localhost:8080"
username = "admin"
password = "admin"
}terraform initRealm is a container for users, credentials, roles, groups and other entities. Each user belongs to and logs into a specific realm. Realms are isolated from one another and can only manage and authenticate the users that they control.
Go to https://keycloak.sikademo.com and login as admin with password admin. Click on Add realm button and fill the form.
resource "keycloak_realm" "example" {
realm = "example"
enabled = true
display_name = "Example SSO"
}terraform applyExtra configuration
Add email configuration (maildev in kubernetes)
resource "keycloak_realm" "example" {
realm = "example"
enabled = true
display_name = "Example SSO"
display_name_html = "<h1>Example SSO</h1>"
reset_password_allowed = true
smtp_server {
host = "maildev-smtp.maildev"
port = "25"
from = "[email protected]"
auth {
username = "xxx"
password = "xxx"
}
}
}Add email configuration (mailhog in docker compose)
resource "keycloak_realm" "example" {
realm = "example"
enabled = true
display_name = "Example SSO"
display_name_html = "<h1>Example SSO</h1>"
reset_password_allowed = true
smtp_server {
host = "mailhog"
port = "1025"
from = "[email protected]"
auth {
username = "xxx"
password = "xxx"
}
}
}You can add user here https://keycloak.sikademo.com/admin/example/console/#/example/users
resource "keycloak_user" "ondrej" {
realm_id = keycloak_realm.example.id
username = "ondrej"
enabled = true
email = "[email protected]"
email_verified = true
first_name = "Ondrej"
last_name = "Sika"
initial_password {
value = "a"
temporary = true
}
}- User registration
- Forgot password
- Remember me
- Email as username
- Login with email
- Duplicate emails
- Verify email
- Edit username
Roles and groups have a similar purpose, which is to give users access and permissions to use applications. Groups are a collection of users to which you apply roles and attributes. Roles define specific applications permissions and access control.
A role typically applies to one type of user. For example, an organization may include admin, user, manager, and employee roles. An application can assign access and permissions to a role and then assign multiple users to that role so the users have the same access and permissions. For example, the Admin Console has roles that give permission to users to access different parts of the Admin Console.
https://keycloak.sikademo.com/admin/master/console/#/example/roles
resource "keycloak_role" "editor" {
realm_id = keycloak_realm.example.id
name = "editor"
}
resource "keycloak_role" "viewer" {
realm_id = keycloak_realm.example.id
name = "viewer"
}Groups are a collection of users to which you apply roles and attributes. Roles define specific applications permissions and access control.
https://keycloak.sikademo.com/admin/master/console/#/example/groups
resource "keycloak_group" "team-a" {
realm_id = keycloak_realm.example.id
name = "team-a"
}
resource "keycloak_group" "team-b" {
realm_id = keycloak_realm.example.id
name = "team-b"
}https://keycloak.sikademo.com/admin/master/console/#/example/users
resource "keycloak_user_groups" "ondrej" {
realm_id = keycloak_realm.example.id
user_id = keycloak_user.ondrej.id
group_ids = [
keycloak_group.team-b.id,
]
}resource "keycloak_user_roles" "ondrej" {
realm_id = keycloak_realm.example.id
user_id = keycloak_user.ondrej.id
role_ids = [
keycloak_role.editor.id,
]
}
resource "keycloak_group_roles" "team-a" {
realm_id = keycloak_realm.example.id
group_id = keycloak_group.team-a.id
role_ids = [
keycloak_role.editor.id,
]
}
resource "keycloak_group_roles" "team-b" {
realm_id = keycloak_realm.example.id
group_id = keycloak_group.team-b.id
role_ids = [
keycloak_role.viewer.id,
]
}
Clients are applications that can request authentication from Keycloak. Clients can be applications that are developed by your organization or third-party applications. When you create a client, you can specify the type of client. For example, you can specify that the client is a confidential application that requires a secret to authenticate, or you can specify that the client is a public application that does not require a secret to authenticate.
https://keycloak.sikademo.com/admin/master/console/#/example/clients
curl -X POST "https://keycloak.sikademo.com/realms/test/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=default" \
-d "client_secret=default" \
-d "grant_type=password" \
-d "username=user" \
-d "password=a"curl -X POST "https://keycloak.sikademo.com/realms/test/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=default" \
-d "client_secret=default" \
-d "grant_type=password" \
-d "username=user" \
-d "password=a" \
-d "scope=openid"resource "keycloak_openid_client" "example" {
realm_id = keycloak_realm.example.id
client_id = "example"
client_secret = "example"
enabled = true
standard_flow_enabled = true
direct_access_grants_enabled = true
access_type = "PUBLIC" # or "CONFIDENTIAL"
valid_redirect_uris = ["*"]
valid_post_logout_redirect_uris = ["*"]
web_origins = ["*"]
}resource "keycloak_openid_client_scope" "example_groups" {
realm_id = keycloak_realm.example.id
name = "groups"
include_in_token_scope = true
}data "keycloak_openid_client_scope" "example_roles" {
realm_id = keycloak_realm.example.id
name = "roles"
}resource "keycloak_openid_group_membership_protocol_mapper" "example_groups" {
realm_id = keycloak_realm.example.id
client_scope_id = keycloak_openid_client_scope.example_groups.id
name = keycloak_openid_client_scope.example_groups.name
claim_name = keycloak_openid_client_scope.example_groups.name
full_path = false
}resource "keycloak_openid_user_realm_role_protocol_mapper" "example_roles" {
realm_id = keycloak_realm.example.id
client_scope_id = data.keycloak_openid_client_scope.example_roles.id
name = data.keycloak_openid_client_scope.example_roles.id
claim_name = data.keycloak_openid_client_scope.example_roles.id
multivalued = true
}resource "keycloak_openid_client_default_scopes" "example" {
realm_id = keycloak_realm.example.id
client_id = keycloak_openid_client.example.id
default_scopes = [
"profile",
"email",
keycloak_openid_client_scope.example_groups.name,
data.keycloak_openid_client_scope.example_roles.name,
]
}Must be requested by the client
resource "keycloak_openid_client_optional_scopes" "example" {
realm_id = keycloak_realm.example.id
client_id = keycloak_openid_client.example.id
optional_scopes = [
keycloak_openid_client_scope.example_groups.name,
]
}Setup NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
echo '. ~/.nvm/nvm.sh' >> ~/.zshrc
echo '. ~/.nvm/nvm.sh' >> ~/.bashrc
. ~/.nvm/nvm.shInstall Node 22
nvm install 22Use Node 22
nvm use 22cd examples/express_api_simple
npm install
cp .env.dist .envvim .envnpm startIn Keycloak, flows are authentication processes that define how users authenticate and interact with Keycloak during login, registration, and other identity-related actions. These flows are highly customizable and consist of multiple execution steps, allowing for complex authentication and authorization scenarios.
- Browser Flow – Handles web-based authentication, such as logging in through a browser.
- Direct Grant Flow – Used for authentication via API (e.g., OAuth 2.0 password grant).
- Registration Flow – Defines how user registration is handled.
- Reset Credentials Flow – Manages the process of resetting user credentials (e.g., forgotten passwords).
- Client Authentication Flow – Used for authenticating clients (applications) to Keycloak.
- First Broker Login Flow – Manages authentication when users log in using an external identity provider (e.g., Google, GitHub, LDAP).
- User-initiated Action Flow – Defines actions users can take after login, like updating passwords.
Each flow consists of authentication executions, which are steps in the flow. These executions can be
- Required – Must be executed for authentication to proceed.
- Alternative – Can be skipped if another option is available.
- Disabled – Not executed.
- Conditional – Executed only if certain conditions are met.
You can modify existing flows or create new ones under Authentication > Flows in the Keycloak Admin Console. This allows you to:
- Add or remove authentication steps.
- Enforce MFA (Multi-Factor Authentication).
- Integrate external identity providers.
resource "keycloak_authentication_flow" "idp_only_browser_flow" {
realm_id = keycloak_realm.example2.id
alias = "idp_only_browser_flow"
}
resource "keycloak_authentication_execution" "idp_only_browser_flow_01" {
realm_id = keycloak_realm.example2.id
parent_flow_alias = keycloak_authentication_flow.idp_only_browser_flow.alias
authenticator = "identity-provider-redirector"
requirement = "REQUIRED"
}
resource "keycloak_authentication_execution_config" "idp_only_browser_flow_01" {
realm_id = keycloak_realm.example2.id
execution_id = keycloak_authentication_execution.idp_only_browser_flow_01.id
alias = "identity-provider-redirector"
config = {
defaultProvider = keycloak_oidc_identity_provider.example2.id
}
}
resource "keycloak_authentication_bindings" "browser_authentication_binding" {
realm_id = keycloak_realm.example2.id
browser_flow = keycloak_authentication_flow.idp_only_browser_flow.alias
}That's it. Do you have any questions? Let's go for a beer!
- email: [email protected]
- web: https://sika.io
- twitter: @ondrejsika
- linkedin: /in/ondrejsika/
- Newsletter, Slack, Facebook & Linkedin Groups: https://join.sika.io
Do you like the course? Write me recommendation on Twitter (with handle @ondrejsika) and LinkedIn (add me /in/ondrejsika and I'll send you request for recommendation). Thanks.
Wanna to go for a beer or do some work together? Just book me :)
- https://github.com/sika-training-examples/2025-02-26_keycloak-ataccama-example (in training example repo)
- https://github.com/sika-training-examples/2025-02-27_keycloak-mapping-example (better example of atrribute mapping and user federation)
- Keycloak Terraform Example - https://github.com/sika-training-examples/2025-02-10_keycloak-terraform-example