LabHub

Blog

Building SSO with Keycloak — From Realm, Client, and Flows to the 2026 New Features

한국어English日本語中文

Introduction — Why You Should Not Build Login Yourself

Say you have 20 internal apps. If you implement sign-up, password reset, 2FA, social login, and session management separately in each one, your attack surface grows twentyfold. The idea behind SSO (Single Sign-On) is simple — stand up one server dedicated to the job of logging people in, and have every app delegate the question "who is this person?" to that server. The user logs in once and can use all 20 apps, and the apps never touch a password at all.

Keycloak is the open-source standard for this identity server (currently a CNCF incubating project, and the upstream of Red Hat build of Keycloak). It speaks both OIDC and SAML, and ships social login brokering, LDAP integration, 2FA, and WebAuthn out of the box. This post makes sense of Keycloak through four core concepts, walks the login flow one step at a time, and then covers deployment pitfalls and the 2026 new features. If the authentication flow itself feels unfamiliar, playing with the Auth Flow Visualizer first will make this post much easier to follow.

Part 1 — Keycloak Through Four Core Concepts

The Keycloak admin console has dozens of menus, but the skeleton is just four.

Concept            Role                                       Analogy
─────────────────  ─────────────────────────────────────────  ──────────────────
Realm              A fully isolated tenant (own users/config)  A single "kingdom"
Client             An application that delegates auth           Who the kingdom issues "passes" to
Role / Group       Permissions and user groupings              "Titles" and "departments"
Identity Provider  An external login source (Google, upstream OIDC/SAML)  "Recognizing another kingdom's passport"

Part 2 — The OIDC Login Flow, One Step at a Time

The most common flow is Authorization Code + PKCE. Let's follow the process of a SPA delegating login to Keycloak.

① The user clicks the app's "Log in"
   → The app redirects the browser to the Keycloak authorize endpoint
     (including client_id, redirect_uri, scope=openid, code_challenge)

② Keycloak shows the login screen → the user authenticates (password + OTP, etc.)
   ※ If a Keycloak session already exists, this screen is skipped = the heart of SSO

③ Keycloak redirects back to redirect_uri + a one-time authorization code

④ The app backend (or SPA) exchanges code + code_verifier at the token endpoint
   → receives access_token (JWT) + id_token + refresh_token

⑤ The app sends the access_token in the API call's Authorization header
   The API only verifies the signature with Keycloak's public key (JWKS) — it does not ask Keycloak on every request

Three things are key here. First, PKCE (code_challenge/code_verifier) neutralizes a stolen authorization code — it is mandatory for public clients. Second, the "skipped if a session exists" in ② is precisely SSO. When a second app delegates login, Keycloak already recognizes the user from the browser cookie and issues a code immediately, with no login screen. Third, in ⑤ the API does not call Keycloak on every request — because the access_token is a signed JWT, it only needs local verification with the public key. This statelessness is why SSO scales.

Don't get the roles of the three token types mixed up either:

id_token       "who logged in" — user info. Consumed by the app (client)
access_token   "what they can do" — permissions. Verified by the API (resource server)
refresh_token  "the right to be reissued" — used to renew when the access_token expires; store it securely

Tuning session and token lifetimes is the key lever in Realm settings. The standard is to make the access_token short (a few minutes) and the refresh_token long (up to the SSO session lifetime); the combination of a short access_token plus local signature verification gives you both "expires soon even if stolen" and "fast verification" at once.

Part 3 — Deployment: The Quarkus Two-Phase Model and Production Pitfalls

Since Keycloak 17, the distribution has been Quarkus-based (the old WildFly/JBoss distribution was removed). The pitfall newcomers hit most often here is the build/start two-phase model.

# ① Build phase (augmentation): "bake in" the DB vendor and enabled features
#    — this phase is slow but not done often
bin/kc.sh build --db=postgres --features=organizations,token-exchange

# ② Start phase: pass only runtime settings (hostname, DB connection, TLS)
bin/kc.sh start --optimized \
  --hostname=https://auth.example.com \
  --db-url=jdbc:postgresql://db/keycloak \
  --db-username=keycloak --db-password="$KC_DB_PASSWORD"

# For local development, a convenience command that combines both phases
bin/kc.sh start-dev

The --optimized flag means "I already built, so don't rebuild on start." In a container image, the standard is to put the build phase in the Dockerfile and bake it into the image, then run only start --optimized at runtime.

Three representative landmines you'll step on in production:

On Kubernetes, the Keycloak Operator wraps all of this declaratively via the Keycloak and KeycloakRealmImport CRDs. If you need a feel for Kubernetes, it helps to first get comfortable with CRD and operator patterns in the Kubernetes Playground.

Part 4 — Keycloak in 2026: The 26.x New Features

As of this writing, the latest is 26.6.3 (internal Quarkus 3.33.2). Of the things that graduated in the 26 series, four with large practical impact:

Token exchange still has boundaries — currently only OIDC/OAuth exchange is supported, and SAML-based client and IdP exchange is future work. So for establishing external trust, the JWT Authorization Grant above is the more standard answer.

Part 5 — When to Use It, and When to Think Again

Where Keycloak shines: when you need data sovereignty on-premises or in hybrid setups, when you need broad protocol (OIDC + SAML) coverage, and when you need to scale massively with no license cost. The fork in the road with managed SaaS (Auth0, Okta, Entra ID) is usually "will you bear the operational burden, or the cost and lock-in?" — Keycloak gives you complete control over your data and customization, at the price of owning the DB, upgrades, and availability yourself.

Points to reconsider: an identity server is a single point of failure. If it dies, all 20 apps become unable to log in at once. So multiple instances + external session storage (Infinispan/DB) + zero-downtime patching are a requirement, not a choice. And if you miss the security basics — token and session lifetimes, redirect URI whitelisting, PKCE enforcement — SSO instead concentrates your attack surface in one place. This sense is best built by running OAuth, OIDC, and JWT by hand in the Auth & Security Lab.

Closing

Keycloak is, in the end, infrastructure that "gathers login into one place." Build the skeleton with the four concepts — Realm (isolation), Client (app), Role/Group (permissions), and IdP (external integration); understand the flow with Authorization Code + PKCE; avoid deployment pitfalls with the build/start two-phase model + hostname v2; and solve multi-tenancy with Organizations — and the logins of 20 apps converge into one well-guarded door. Being open source while honestly following the standards is why this project has been loved for over a decade.

References

Comments

No comments yet.

Sign in to leave a comment