This document describes what a Realm is in Keycloak, its architecture, configuration options, and how it serves as the foundation for multi-tenancy.
What is a Realm?
A Realm in Keycloak is a complete, isolated authentication and authorization domain. It is the top-level organizational unit that contains:
- Users & Groups – The user population with their credentials and group memberships
- Clients – Applications that authenticate users through Keycloak
- Roles & Permissions – Authorization model for access control
- Authentication Flows – How users prove their identity (login forms, MFA, social login)
- Identity Providers – Federation with external identity systems (LDAP, social providers)
- Security Policies – Password requirements, session timeouts, brute force protection
- Themes & Localization – UI customization and language support
Key Principle: Realms are completely isolated from each other. Users in one realm cannot access another realm’s resources. This enables true multi-tenancy where a single Keycloak instance can serve multiple independent organizations.
Realm Architecture
Core Interfaces
| Interface | Purpose | Source |
|---|---|---|
RealmModel |
Main realm interface (~300 methods) | server-spi |
RealmProvider |
CRUD operations for realms | server-spi |
RealmEntity |
JPA database entity | model/jpa |
RealmAdapter |
Bridges RealmModel to RealmEntity | model/jpa |
RealmModel Interface
The RealmModel interface extends RoleContainerModel and defines approximately 300+ methods across multiple categories:
Basic Identity Properties
From RealmModel.java:73-90:
| Method | Description |
|---|---|
getId() |
Unique identifier (UUID format) |
getName() |
Unique realm name (e.g., “master”, “production”) |
getDisplayName() |
Human-readable display name |
getDisplayNameHtml() |
Display name with HTML (for theming) |
isEnabled() |
Whether the realm is active |
The Master Realm
The master realm is a special administrative realm created automatically when Keycloak starts for the first time.
Master Realm Characteristics:
- Contains super administrators who can manage all realms
- For each non-master realm, a client is created in master (e.g.,
production-realm) - Admin users in master can be granted permissions to manage specific realms
- Best practice: Don’t use master realm for application users
Realm Entity Relationships
Realm Configuration Categories
Authentication & Registration
From RealmModel.java:96-127:
| Setting | Method | Default | Description |
|---|---|---|---|
| User Registration | isRegistrationAllowed() |
false | Allow user self-registration |
| Email as Username | isRegistrationEmailAsUsername() |
false | Use email as username during registration |
| Remember Me | isRememberMe() |
false | Enable remember-me checkbox on login |
| Edit Username | isEditUsernameAllowed() |
false | Allow users to edit their username |
| Login with Email | isLoginWithEmailAllowed() |
true | Login with email instead of username |
| Duplicate Emails | isDuplicateEmailsAllowed() |
false | Allow multiple users with same email |
| Verify Email | isVerifyEmail() |
false | Require email verification |
| Reset Password | isResetPasswordAllowed() |
false | Enable password reset functionality |
SSL/TLS Requirements
Session Configuration
From RealmModel.java:214-248:
SSO Session Settings
| Setting | Method | Default | Description |
|---|---|---|---|
| SSO Idle Timeout | getSsoSessionIdleTimeout() |
1800s (30 min) | Idle timeout for user sessions |
| SSO Max Lifespan | getSsoSessionMaxLifespan() |
36000s (10 hours) | Maximum session duration |
| SSO Idle (Remember Me) | getSsoSessionIdleTimeoutRememberMe() |
0 (use regular) | Idle timeout with remember-me |
| SSO Max (Remember Me) | getSsoSessionMaxLifespanRememberMe() |
0 (use regular) | Max lifespan with remember-me |
Offline Session Settings
| Setting | Method | Default | Description |
|---|---|---|---|
| Offline Idle Timeout | getOfflineSessionIdleTimeout() |
2592000s (30 days) | Offline session idle timeout |
| Offline Max Enabled | isOfflineSessionMaxLifespanEnabled() |
false | Enable max lifespan limit |
| Offline Max Lifespan | getOfflineSessionMaxLifespan() |
5184000s (60 days) | Maximum offline session duration |
Client Session Settings
| Setting | Method | Default | Description |
|---|---|---|---|
| Client Idle Timeout | getClientSessionIdleTimeout() |
0 (use SSO) | Client-specific idle timeout |
| Client Max Lifespan | getClientSessionMaxLifespan() |
0 (use SSO) | Client-specific max lifespan |
| Client Offline Idle | getClientOfflineSessionIdleTimeout() |
0 (use offline) | Client offline idle timeout |
| Client Offline Max | getClientOfflineSessionMaxLifespan() |
0 (use offline) | Client offline max lifespan |
Token Configuration
From RealmModel.java:229-288:
| Setting | Method | Default | Description |
|---|---|---|---|
| Access Token Lifespan | getAccessTokenLifespan() |
300s (5 min) | Access token expiration |
| Access Token (Implicit) | getAccessTokenLifespanForImplicitFlow() |
900s (15 min) | For implicit flow |
| Access Code Lifespan | getAccessCodeLifespan() |
60s (1 min) | Authorization code validity |
| User Action Lifespan | getAccessCodeLifespanUserAction() |
300s (5 min) | Action token validity |
| Login Lifespan | getAccessCodeLifespanLogin() |
1800s (30 min) | Login session validity |
| Revoke Refresh Token | isRevokeRefreshToken() |
false | Revoke on logout |
| Refresh Token Max Reuse | getRefreshTokenMaxReuse() |
0 | Max reuse count |
| Default Signature Alg | getDefaultSignatureAlgorithm() |
RS256 | Token signing algorithm |
Brute Force Protection
From RealmModel.java:165-186:
| Setting | Method | Default | Description |
|---|---|---|---|
| Enabled | isBruteForceProtected() |
false | Enable brute force detection |
| Permanent Lockout | isPermanentLockout() |
false | Lock accounts permanently |
| Max Temporary Lockouts | getMaxTemporaryLockouts() |
0 | Max temp lockouts before permanent |
| Strategy | getBruteForceStrategy() |
MULTIPLE | MULTIPLE (per user+IP) or FIXED_HOUR |
| Max Failure Wait | getMaxFailureWaitSeconds() |
900s (15 min) | Maximum wait time |
| Wait Increment | getWaitIncrementSeconds() |
60s | Increment per failure |
| Min Quick Login Wait | getMinimumQuickLoginWaitSeconds() |
60s | Minimum wait for rapid attempts |
| Quick Login Check | getQuickLoginCheckMilliSeconds() |
1000ms | Rapid attempt detection window |
| Max Delta Time | getMaxDeltaTimeSeconds() |
43200s (12 hours) | Reset window |
| Failure Factor | getFailureFactor() |
30 | Failure threshold |
Authentication Flows
From RealmModel.java:393-425:
| Flow Type | Method | Purpose |
|---|---|---|
| Browser Flow | getBrowserFlow() |
Standard browser login |
| Registration Flow | getRegistrationFlow() |
User self-registration |
| Direct Grant Flow | getDirectGrantFlow() |
Resource Owner Password Credentials |
| Reset Credentials Flow | getResetCredentialsFlow() |
Password reset |
| Client Authentication Flow | getClientAuthenticationFlow() |
Client authentication |
| Docker Authentication Flow | getDockerAuthenticationFlow() |
Docker registry auth |
| First Broker Login Flow | getFirstBrokerLoginFlow() |
First social/IdP login |
Credential Policies
From RealmModel.java:289-327:
| Policy | Method | Description |
|---|---|---|
| Password Policy | getPasswordPolicy() |
Password requirements (length, complexity, history) |
| OTP Policy | getOTPPolicy() |
One-Time Password settings (TOTP/HOTP) |
| WebAuthn Policy | getWebAuthnPolicy() |
WebAuthn/FIDO2 settings for 2FA |
| WebAuthn Passwordless | getWebAuthnPolicyPasswordless() |
WebAuthn for passwordless login |
Password Policy Example:
length(8) and digits(1) and upperCase(1) and specialChars(1) and notUsername
Themes & Branding
From RealmModel.java:620-634:
| Setting | Method | Description |
|---|---|---|
| Login Theme | getLoginTheme() |
Login page appearance |
| Account Theme | getAccountTheme() |
User account management UI |
| Admin Theme | getAdminTheme() |
Admin console appearance |
| Email Theme | getEmailTheme() |
Email template styling |
Localization
From RealmModel.java:708-829:
| Setting | Method | Description |
|---|---|---|
| i18n Enabled | isInternationalizationEnabled() |
Enable language support |
| Supported Locales | getSupportedLocalesStream() |
Available languages |
| Default Locale | getDefaultLocale() |
Default language code |
| Localization Texts | getRealmLocalizationTexts() |
Custom translations |
Event Logging
From RealmModel.java:646-680:
| Setting | Method | Default | Description |
|---|---|---|---|
| Events Enabled | isEventsEnabled() |
false | Enable event logging |
| Events Expiration | getEventsExpiration() |
0 | Event retention (ms) |
| Event Listeners | getEventsListenersStream() |
jboss-logging | Event handlers |
| Enabled Event Types | getEnabledEventTypesStream() |
all | Types to log |
| Admin Events | isAdminEventsEnabled() |
false | Log admin operations |
| Admin Event Details | isAdminEventsDetailsEnabled() |
false | Include request/response |
Database Schema
Main REALM Table
From RealmEntity.java:
CREATE TABLE REALM (
ID VARCHAR(36) PRIMARY KEY,
NAME VARCHAR(255) UNIQUE NOT NULL,
ENABLED BOOLEAN DEFAULT FALSE,
SSL_REQUIRED VARCHAR(255),
-- Registration & Login
REGISTRATION_ALLOWED BOOLEAN DEFAULT FALSE,
REG_EMAIL_AS_USERNAME BOOLEAN DEFAULT FALSE,
VERIFY_EMAIL BOOLEAN DEFAULT FALSE,
RESET_PASSWORD_ALLOWED BOOLEAN DEFAULT FALSE,
LOGIN_WITH_EMAIL_ALLOWED BOOLEAN DEFAULT TRUE,
DUPLICATE_EMAILS_ALLOWED BOOLEAN DEFAULT FALSE,
REMEMBER_ME BOOLEAN DEFAULT FALSE,
EDIT_USERNAME_ALLOWED BOOLEAN DEFAULT FALSE,
-- Session Timeouts
SSO_IDLE_TIMEOUT INT DEFAULT 1800,
SSO_MAX_LIFESPAN INT DEFAULT 36000,
SSO_IDLE_TIMEOUT_REMEMBER_ME INT DEFAULT 0,
SSO_MAX_LIFESPAN_REMEMBER_ME INT DEFAULT 0,
OFFLINE_SESSION_IDLE_TIMEOUT INT DEFAULT 2592000,
-- Token Lifespans
ACCESS_TOKEN_LIFESPAN INT DEFAULT 300,
ACCESS_TOKEN_LIFE_IMPLICIT INT DEFAULT 900,
ACCESS_CODE_LIFESPAN INT DEFAULT 60,
USER_ACTION_LIFESPAN INT DEFAULT 300,
LOGIN_LIFESPAN INT DEFAULT 1800,
-- Token Settings
NOT_BEFORE INT DEFAULT 0,
REVOKE_REFRESH_TOKEN BOOLEAN DEFAULT FALSE,
REFRESH_TOKEN_MAX_REUSE INT DEFAULT 0,
-- Themes
LOGIN_THEME VARCHAR(255),
ACCOUNT_THEME VARCHAR(255),
ADMIN_THEME VARCHAR(255),
EMAIL_THEME VARCHAR(255),
-- Events
EVENTS_ENABLED BOOLEAN DEFAULT FALSE,
EVENTS_EXPIRATION BIGINT DEFAULT 0,
ADMIN_EVENTS_ENABLED BOOLEAN DEFAULT FALSE,
ADMIN_EVENTS_DETAILS_ENABLED BOOLEAN DEFAULT FALSE,
-- Policies
PASSWORD_POLICY VARCHAR(2550),
OTP_POLICY_TYPE VARCHAR(255) DEFAULT 'totp',
OTP_POLICY_ALG VARCHAR(255) DEFAULT 'HmacSHA1',
OTP_POLICY_DIGITS INT DEFAULT 6,
OTP_POLICY_PERIOD INT DEFAULT 30,
OTP_POLICY_WINDOW INT DEFAULT 1,
OTP_POLICY_COUNTER INT DEFAULT 0,
-- Authentication Flows (Foreign Keys)
BROWSER_FLOW VARCHAR(36),
REGISTRATION_FLOW VARCHAR(36),
DIRECT_GRANT_FLOW VARCHAR(36),
RESET_CREDENTIALS_FLOW VARCHAR(36),
CLIENT_AUTH_FLOW VARCHAR(36),
DOCKER_AUTH_FLOW VARCHAR(36),
-- Administrative
MASTER_ADMIN_CLIENT VARCHAR(36),
DEFAULT_ROLE VARCHAR(36),
-- Features
INTERNATIONALIZATION_ENABLED BOOLEAN DEFAULT FALSE,
DEFAULT_LOCALE VARCHAR(255),
ALLOW_USER_MANAGED_ACCESS BOOLEAN DEFAULT FALSE
);
Related Tables
-- Realm Custom Attributes
CREATE TABLE REALM_ATTRIBUTE (
REALM_ID VARCHAR(36) NOT NULL,
NAME VARCHAR(255) NOT NULL,
VALUE TEXT,
PRIMARY KEY (REALM_ID, NAME),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
-- SMTP Configuration
CREATE TABLE REALM_SMTP_CONFIG (
REALM_ID VARCHAR(36) NOT NULL,
NAME VARCHAR(255) NOT NULL,
VALUE VARCHAR(1024),
PRIMARY KEY (REALM_ID, NAME),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
-- Default Groups (assigned to new users)
CREATE TABLE REALM_DEFAULT_GROUPS (
REALM_ID VARCHAR(36) NOT NULL,
GROUP_ID VARCHAR(36) NOT NULL,
PRIMARY KEY (REALM_ID, GROUP_ID),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
-- Supported Locales
CREATE TABLE REALM_SUPPORTED_LOCALES (
REALM_ID VARCHAR(36) NOT NULL,
VALUE VARCHAR(255) NOT NULL,
PRIMARY KEY (REALM_ID, VALUE),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
-- Event Listeners
CREATE TABLE REALM_EVENTS_LISTENERS (
REALM_ID VARCHAR(36) NOT NULL,
VALUE VARCHAR(255) NOT NULL,
PRIMARY KEY (REALM_ID, VALUE),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
-- Enabled Event Types
CREATE TABLE REALM_ENABLED_EVENT_TYPES (
REALM_ID VARCHAR(36) NOT NULL,
VALUE VARCHAR(255) NOT NULL,
PRIMARY KEY (REALM_ID, VALUE),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
-- Localization Texts
CREATE TABLE REALM_LOCALIZATION_TEXTS (
REALM_ID VARCHAR(36) NOT NULL,
LOCALE VARCHAR(255) NOT NULL,
KEY VARCHAR(255) NOT NULL,
VALUE TEXT,
PRIMARY KEY (REALM_ID, LOCALE, KEY),
FOREIGN KEY (REALM_ID) REFERENCES REALM(ID) ON DELETE CASCADE
);
Realm Attributes
Realm attributes provide extensible key-value storage for settings not in the main table.
From RealmAttributes.java:
| Attribute Key | Purpose |
|---|---|
displayName |
Human-readable realm name |
displayNameHtml |
Display name with HTML |
actionTokenGeneratedByAdminLifespan |
Admin action token lifespan |
actionTokenGeneratedByUserLifespan |
User action token lifespan |
offlineSessionMaxLifespanEnabled |
Enable offline session max |
offlineSessionMaxLifespan |
Offline session max value |
clientSessionIdleTimeout |
Client session idle timeout |
clientSessionMaxLifespan |
Client session max lifespan |
webAuthnPolicyRpEntityName |
WebAuthn relying party name |
webAuthnPolicySignatureAlgorithms |
WebAuthn signature algorithms |
firstBrokerLoginFlowId |
First broker login flow |
organizationsEnabled |
Enable organizations feature |
adminPermissionsEnabled |
Fine-grained admin permissions |
verifiableCredentialsEnabled |
OID4VC support |
Realm Creation & Initialization
When a realm is created via RealmManager.java, Keycloak automatically sets up:
Default Settings
// From RealmManager.setupRealmDefaults() realm.setBrowserSecurityHeaders(BrowserSecurityHeaders.realmDefaultHeaders); realm.setBruteForceProtected(false); realm.setPermanentLockout(false); realm.setMaxFailureWaitSeconds(900); // 15 minutes realm.setMinimumQuickLoginWaitSeconds(60); // 1 minute realm.setWaitIncrementSeconds(60); realm.setQuickLoginCheckMilliSeconds(1000); realm.setMaxDeltaTimeSeconds(43200); // 12 hours realm.setFailureFactor(30); realm.setSslRequired(SslRequired.EXTERNAL); realm.setOTPPolicy(OTPPolicy.DEFAULT_POLICY); realm.setLoginWithEmailAllowed(true); realm.setEventsListeners(Collections.singleton("jboss-logging"));
Default Clients
| Client ID | Purpose | Type |
|---|---|---|
security-admin-console |
Admin Console SPA | Public |
admin-cli |
CLI Administration | Public, Direct Grant |
account |
User Account Management | Public |
account-console |
Account Console SPA | Public |
broker |
Identity Provider Broker | Bearer-only |
realm-management |
Realm Administration | Bearer-only |
Default Authentication Flows
Created by DefaultAuthenticationFlows.addFlows():
- browser – Standard browser login
- registration – User self-registration
- direct grant – Resource Owner Password Credentials
- reset credentials – Password reset
- clients – Client authentication
- first broker login – First social/IdP login
- docker auth – Docker registry authentication
Default Required Actions
Created by DefaultRequiredActions.addActions():
VERIFY_EMAIL– Email verificationUPDATE_PASSWORD– Password updateCONFIGURE_TOTP– Configure OTPUPDATE_PROFILE– Update profileTERMS_AND_CONDITIONS– Accept terms
Default Client Scopes
Created by DefaultClientScopes.createDefaultClientScopes():
| Scope | Type | Claims |
|---|---|---|
openid |
Default | sub |
profile |
Default | name, family_name, given_name, etc. |
email |
Default | email, email_verified |
address |
Optional | address |
phone |
Optional | phone_number, phone_number_verified |
offline_access |
Optional | Enables offline tokens |
roles |
Default | realm_access, resource_access |
web-origins |
Default | allowed-origins |
microprofile-jwt |
Optional | upn, groups |
acr |
Default | acr |
Default Roles
default-roles-{realmname}– Composite role for all default rolesoffline_access– Permission to obtain offline tokens
Realm Provider Operations
From RealmProvider.java:
public interface RealmProvider extends Provider { // Create RealmModel createRealm(String name); RealmModel createRealm(String id, String name); // Read RealmModel getRealm(String id); RealmModel getRealmByName(String name); Stream&lt;realmmodel&gt; getRealmsStream(); Stream&lt;realmmodel&gt; getRealmsStream(String search); Stream&lt;realmmodel&gt; getRealmsWithProviderTypeStream(Class&lt;? &gt; type); // Delete boolean removeRealm(String id); // Client Initial Access ClientInitialAccessModel createClientInitialAccessModel(...); ClientInitialAccessModel getClientInitialAccessModel(...); void removeClientInitialAccessModel(...); Stream&lt;clientinitialaccessmodel&gt; listClientInitialAccessStream(...); // Localization void saveLocalizationText(RealmModel realm, String locale, String key, String text); void saveLocalizationTexts(RealmModel realm, String locale, Map&lt;string, string=&quot;&quot;&gt; texts); boolean deleteLocalizationTextsByLocale(RealmModel realm, String locale); }</string,>
Realm Events
From RealmModel.java:39-71:
| Event Interface | When Fired |
|---|---|
RealmCreationEvent |
After realm creation |
RealmPostCreateEvent |
After realm initialization complete |
RealmRemovedEvent |
When realm is deleted |
IdentityProviderUpdatedEvent |
IdP configuration changed |
IdentityProviderRemovedEvent |
IdP removed |
RealmAttributeUpdateEvent |
Custom attribute changed |
Special Features
User-Managed Access (UMA)
realm.isUserManagedAccessAllowed() // Enable UMA permissions realm.setUserManagedAccessAllowed(boolean)
Organizations
realm.isOrganizationsEnabled() // Enable organizations feature realm.setOrganizationsEnabled(boolean)
Verifiable Credentials (OID4VC)
realm.isVerifiableCredentialsEnabled() // Enable OID4VC support realm.setVerifiableCredentialsEnabled(boolean)
Fine-Grained Admin Permissions
realm.isAdminPermissionsEnabled() // Enable fine-grained admin permissions realm.setAdminPermissionsEnabled(boolean) realm.getAdminPermissionsClient() // Get the admin permissions client
Key Constants
From Constants.java:
// Default Clients ADMIN_CONSOLE_CLIENT_ID = &quot;security-admin-console&quot; ADMIN_CLI_CLIENT_ID = &quot;admin-cli&quot; ACCOUNT_MANAGEMENT_CLIENT_ID = &quot;account&quot; ACCOUNT_CONSOLE_CLIENT_ID = &quot;account-console&quot; BROKER_SERVICE_CLIENT_ID = &quot;broker&quot; REALM_MANAGEMENT_CLIENT_ID = &quot;realm-management&quot; // Default Roles OFFLINE_ACCESS_ROLE = &quot;offline_access&quot; DEFAULT_ROLES_ROLE_PREFIX = &quot;default-roles&quot; // Token Lifespans (seconds) DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT = 900 // 15 min DEFAULT_OFFLINE_SESSION_IDLE_TIMEOUT = 2592000 // 30 days DEFAULT_OFFLINE_SESSION_MAX_LIFESPAN = 5184000 // 60 days DEFAULT_SESSION_IDLE_TIMEOUT = 1800 // 30 min DEFAULT_SESSION_MAX_LIFESPAN = 36000 // 10 hours // Signature Algorithms DEFAULT_SIGNATURE_ALGORITHM = &quot;RS256&quot; INTERNAL_SIGNATURE_ALGORITHM = &quot;HS512&quot;
Related Source Files
| Component | File |
|---|---|
| Realm Model Interface | RealmModel.java |
| Realm Provider Interface | RealmProvider.java |
| Realm JPA Entity | RealmEntity.java |
| Realm Adapter | RealmAdapter.java |
| JPA Realm Provider | JpaRealmProvider.java |
| Realm Manager | RealmManager.java |
| Realm Attributes | RealmAttributes.java |
| Constants | Constants.java |
| Default Auth Flows | DefaultAuthenticationFlows.java |
| Default Required Actions | DefaultRequiredActions.java |
| Default Client Scopes | DefaultClientScopes.java |







