Keycloak Security Hardening
Skycloak runs, patches and backs up your Keycloak for you, but the settings that decide how hard your realms are to attack belong to you. This guide walks through the realm settings that matter most, gives recommended values for each, and ends with a checklist you can use to audit a realm on your own.
Overview
Section titled “Overview”This guide covers:
- Security headers: the HTTP headers Keycloak sends with its login and account pages
- Password policy: length, complexity, history and hashing for realm users
- Brute force detection: locking accounts after repeated failed logins
- MFA enforcement: requiring a second factor for your dashboard team and for your realm users
- Security audit checklist: yes/no checks to run on every realm
Each section applies to one realm. Repeat the steps for every realm your applications sign users in to.
Where the settings live
Section titled “Where the settings live”Most steps happen in the Keycloak Admin Console. To open it:
- Select your cluster in the Skycloak dashboard
- On the Overview page, click Open admin console. When the Admin Console SSO card on that page is on, you are signed in with your Skycloak account
- Pick your realm from the realm selector in the top left of the Admin Console
The Skycloak dashboard also summarises a realm’s security settings. Open your cluster, click a realm in the realms grid, and look at the Security posture card. It shows email verification, self-registration, brute-force protection, password policy, session and token lifetimes, passkeys and MFA enforcement, with an amber dot on each row that needs attention. Its action buttons open the matching recipe or the Admin Console.
Security Headers
Section titled “Security Headers”Keycloak adds a set of browser security headers to every page it serves for a realm: the login page, the account console and the error pages. They tell the browser whether the page may be framed, which content it may load, and whether it must only be reached over HTTPS.
Where to set them
Section titled “Where to set them”- In the Admin Console, select your realm
- Go to Realm settings > Security defenses
- Open the Headers tab
- Edit the values and click Save
Changes apply to the next page Keycloak serves. No restart is needed.
The headers and recommended values
Section titled “The headers and recommended values”| Header | Keycloak default | Recommendation |
|---|---|---|
| X-Frame-Options | SAMEORIGIN |
Keep SAMEORIGIN. Only another Keycloak page may frame the login page, which blocks clickjacking. |
| Content-Security-Policy | frame-src 'self'; frame-ancestors 'self'; object-src 'none'; |
Keep the default. Add origins to frame-ancestors only if your application frames Keycloak pages (see below). |
| Content-Security-Policy-Report-Only | empty | Leave empty, or use it to test a stricter policy before you enforce it. |
| X-Content-Type-Options | nosniff |
Keep nosniff. It stops browsers from guessing a file’s type. |
| X-Robots-Tag | none |
Keep none. Search engines should not index your login pages. |
| HTTP Strict Transport Security (HSTS) | max-age=31536000; includeSubDomains |
Keep the default. Browsers then refuse to reach your sign-in host over plain HTTP for a year. |
| Referrer Policy | no-referrer |
Keep no-referrer. Login URLs carry state you do not want to leak to other sites. |
Older Keycloak versions also show X-XSS-Protection. Modern browsers ignore it, so its value no longer matters.
The defaults are already a strong baseline. The most common reason to change them is not to tighten them but to loosen them by mistake while debugging an iframe problem, so check them whenever a realm has been edited by hand.
When your application frames Keycloak
Section titled “When your application frames Keycloak”Some setups load Keycloak pages inside an iframe, for example the silent check-sso flow in keycloak-js, or a login page embedded in your own application. With the default headers the browser blocks the frame, because your application is on a different origin from your sign-in host.
To allow it for one origin without opening it to every site:
-
In Content-Security-Policy, add your application’s origin to
frame-ancestors, for example:frame-src 'self'; frame-ancestors 'self' https://app.example.com; object-src 'none'; -
Clear X-Frame-Options. It cannot list a specific origin, and browsers that support
frame-ancestorsuse the CSP value instead -
Click Save
Never use frame-ancestors * or remove the CSP entirely. That lets any site frame your login page.
HSTS and custom domains
Section titled “HSTS and custom domains”If your realm is served from a custom domain, the HSTS header applies to that hostname and, with includeSubDomains, to hostnames below it. Only add preload if you control the whole parent domain, serve every subdomain over HTTPS, and intend to submit it to the browser preload list, because preloading is hard to undo.
Password Policy
Section titled “Password Policy”Keycloak sets no password policy on a new realm, so any password a user types is accepted. If your users sign in with passwords, set a policy.
Recommended policy
Section titled “Recommended policy”This policy follows current guidance (NIST SP 800-63B): favour length, block obvious choices, and do not force regular rotation.
| Policy | Value | Why |
|---|---|---|
| Minimum length | 12 |
Length is the strongest single factor against guessing. |
| Not username | on | Blocks the username as the password. |
| Not email | on | Blocks the email address as the password. |
| Not recently used | 5 |
A user cannot cycle back to one of their last five passwords. |
| Hashing algorithm | leave at the default | Keycloak picks a strong algorithm for the version your cluster runs. |
| Hashing iterations | leave at the default | Lowering it makes stolen hashes cheaper to crack. |
The resulting policy string, as Keycloak stores it, is:
length(12) and notUsername and notEmail and passwordHistory(5)
If a compliance framework you follow requires character classes, also add Uppercase characters, Lowercase characters, Digits and Special characters, each set to 1. Leave Expire password off unless a framework requires it: forced rotation tends to produce weaker, predictable passwords.
Apply it
Section titled “Apply it”- In the Admin Console, select your realm
- Go to Authentication and open the Policies tab
- Open the Password policy sub-tab
- Click Add policy and add Minimum length, then set it to
12 - Add Not username, Not email and Not recently used, and set Not recently used to
5 - Click Save
Back in the Skycloak dashboard, the realm’s Security posture card now lists the policy on the Password policy row.
Existing users
Section titled “Existing users”A new policy is checked when a password is set or changed. Existing passwords keep working until then. To make everyone pick a compliant password now, add the Update Password required action to users from Users > select a user > Required user actions. Each user is asked for a new password at their next login.
If you change the hashing algorithm or iterations, Keycloak re-hashes each password the next time that user signs in. Nobody is locked out.
Brute Force Detection
Section titled “Brute Force Detection”Brute force detection stops password guessing by locking an account after repeated failed logins. Keycloak turns it off on a new realm.
The settings
Section titled “The settings”| Setting | What it controls |
|---|---|
| Brute Force Mode | Off, temporary lockout, permanent lockout, or permanent lockout after a number of temporary ones |
| Max login failures | Failed attempts before the account is locked |
| Wait increment | How long the first lockout lasts. Each further lockout adds this amount again |
| Max wait | The longest a temporary lockout can last |
| Failure reset time | How long after the last failure the failure count goes back to zero |
| Quick login check milliseconds | Two failed attempts closer together than this count as an automated attack |
| Minimum quick login wait | How long the account is locked after a quick-login failure |
| Maximum temporary lockouts | In the permanent-after-temporary mode, how many temporary lockouts happen before the permanent one |
Recommended values
Section titled “Recommended values”| Setting | Value |
|---|---|
| Brute Force Mode | Lockout temporarily |
| Max login failures | 5 |
| Wait increment | 1 minute |
| Max wait | 15 minutes |
| Failure reset time | 12 hours |
| Quick login check milliseconds | 1000 |
| Minimum quick login wait | 1 minute |
With these values a password guesser gets five tries, then waits at least a minute, with the wait growing up to 15 minutes. That makes online guessing impractical while a real user who mistypes their password is only slowed down.
Apply it
Section titled “Apply it”- In the Admin Console, select your realm
- Go to Realm settings > Security defenses
- Open the Brute force detection tab
- Set Brute Force Mode to Lockout temporarily
- Enter the recommended values above
- Click Save
The realm’s Security posture card in the Skycloak dashboard now shows Brute-force protection as on, with the failure count and lockout time.
Unlocking a user
Section titled “Unlocking a user”Depending on your Keycloak version and realm settings, a locked user may see the same “Invalid username or password” message as any failed login, or a message saying the account is temporarily disabled. To unlock someone before the wait ends, go to Users and select the user. While the user is locked, the user details page shows a Temporarily locked switch that is on. Turn it off to unlock the user. After a permanent lockout, check the same page and turn Enabled back on if the user shows as disabled.
Brute force detection also feeds the free Adaptive Risk extension’s recent_failures signal. See Risk-Based MFA.
MFA Enforcement
Section titled “MFA Enforcement”There are two places to require a second factor, and a hardened setup uses both.
Your Skycloak workspace
Section titled “Your Skycloak workspace”Workspace MFA enforcement protects the people who manage your clusters. When it is on, every member of your workspace has to set up an authenticator app or a security key before they can use the dashboard. Because Admin Console SSO signs people in with their Skycloak account, the same second factor also protects access to your Keycloak Admin Console.
- In the Skycloak dashboard, go to Settings > Security
- On the Multi-Factor Authentication card, click Require MFA
- In the confirmation dialog, click Enforce MFA
The card then shows Required. Members who have not set up MFA get an email and are asked to set it up at their next login.
Whether workspace MFA enforcement is included depends on your plan. If your plan does not include it, the Multi-Factor Authentication card shows a lock tag instead of the Require MFA button, with a link to view pricing. See MFA Enforcement for the member experience.
Your realm users
Section titled “Your realm users”Realm MFA protects the users who sign in to your applications. The quickest way to turn it on is the Multi-factor authentication (MFA) recipe:
- In the Skycloak dashboard, go to Recipes and choose Multi-factor authentication (MFA), or click the action on the MFA enforcement row of a realm’s Security posture card
- Pick the second factors to offer: Authenticator app (TOTP), Security key (WebAuthn second factor), or both
- Turn on Enforce for all users to prompt every user, including existing ones, to set up a second factor at their next login
- Click Enable & enforce
If you leave Enforce for all users off, MFA is available but optional: users can add a second factor from the Account Console. For most realms, enforce MFA at least for administrators and for any user who can reach sensitive data.
The Multi-Factor Authentication Setup guide covers the rest: OTP and WebAuthn policies, risk-based MFA that only asks when a login looks unusual, enforcing MFA for specific groups or roles, and recovery.
Security Audit Checklist
Section titled “Security Audit Checklist”Run this checklist on each realm after initial setup and again whenever someone has changed realm settings by hand. Every item should be answered Yes. For each No, the section above tells you how to fix it.
Workspace
Section titled “Workspace”| Check | Where to look |
|---|---|
| Is MFA enforcement on for your workspace? | Skycloak dashboard > Settings > Security > Multi-Factor Authentication shows Required |
| Does every workspace member still need access, with the lowest role that works? | Skycloak dashboard > Team |
| Is Admin Console SSO used for Admin Console access, rather than shared admin passwords? | Skycloak dashboard > your cluster > Overview > Admin Console SSO card |
Security headers
Section titled “Security headers”| Check | Where to look |
|---|---|
Is X-Frame-Options SAMEORIGIN, or empty only because CSP frame-ancestors lists specific origins? |
Admin Console > Realm settings > Security defenses > Headers |
Does Content-Security-Policy contain frame-ancestors without a * and object-src 'none'? |
Admin Console > Realm settings > Security defenses > Headers |
Is X-Content-Type-Options nosniff? |
Admin Console > Realm settings > Security defenses > Headers |
Is HTTP Strict Transport Security (HSTS) set with a max-age of at least 31536000? |
Admin Console > Realm settings > Security defenses > Headers |
Is Referrer Policy no-referrer? |
Admin Console > Realm settings > Security defenses > Headers |
Passwords
Section titled “Passwords”| Check | Where to look |
|---|---|
| Does the realm have a password policy? | Skycloak dashboard > realm page > Security posture > Password policy |
Is Minimum length at least 12? |
Admin Console > Authentication > Policies > Password policy |
| Are Not username and Not email set? | Admin Console > Authentication > Policies > Password policy |
Is Not recently used set to 5 or more? |
Admin Console > Authentication > Policies > Password policy |
| Are Hashing algorithm and Hashing iterations absent from the policy list, so Keycloak uses its own defaults? | Admin Console > Authentication > Policies > Password policy |
Brute force detection
Section titled “Brute force detection”| Check | Where to look |
|---|---|
| Is brute-force protection on? | Skycloak dashboard > realm page > Security posture > Brute-force protection |
| Is Brute Force Mode set to Lockout temporarily (or a permanent mode you chose on purpose)? | Admin Console > Realm settings > Security defenses > Brute force detection |
Is Max login failures 10 or fewer? |
Admin Console > Realm settings > Security defenses > Brute force detection |
Is Max wait 15 minutes or longer? A longer wait slows guessing more, so a higher value is stricter. |
Admin Console > Realm settings > Security defenses > Brute force detection |
MFA and sign-in
Section titled “MFA and sign-in”| Check | Where to look |
|---|---|
| Is MFA enforced for the realm, or at least for administrators and privileged users? | Skycloak dashboard > realm page > Security posture > MFA enforcement |
| Is email verification required on sign-up? | Skycloak dashboard > realm page > Security posture > Email verification |
| Is self-registration off, unless your application needs open sign-up? | Skycloak dashboard > realm page > Security posture > Self-registration |
| Do session idle and token lifetimes match your policy? | Skycloak dashboard > realm page > Security posture > Session & tokens, and the Session Timeouts guide |
Monitoring
Section titled “Monitoring”| Check | Where to look |
|---|---|
| Are login events saved, so failed logins and lockouts can be reviewed? | Admin Console > Realm settings > Events > User events settings > Save events |
| Are admin events saved, so configuration changes can be traced? | Admin Console > Realm settings > Events > Admin events settings > Save events |
| Are security events sent to your SIEM or alerting? | Skycloak dashboard > Events and webhooks, and the SIEM Integration guide |