Clients
What is a client?
Section titled “What is a client?”A client is any application that delegates authentication and authorisation to Keycloak. When a user wants to sign in to your app, your app redirects them to Keycloak. Keycloak authenticates the user, then redirects back to your app with a code or a token. This redirect-based dance is the OAuth2 / OIDC Authorization Code flow, and the “client” is the party your app registered itself as.
Examples of clients:
- A React SPA that calls a REST API on behalf of a logged-in user.
- A Spring Boot web application that shows a dashboard after login.
- A mobile app that lets users manage their account.
- A backend microservice that calls another service using a machine-to-machine token.
Every client lives inside exactly one realm. If you have two different applications, register two clients — even if they share users.
Creating a client
Section titled “Creating a client”- In the admin console, make sure you are in the correct realm (check the top-left drop-down).
- Click Clients in the left sidebar.
- Click Create client (top-right of the clients list).
- On the General Settings step:
- Client type — leave as OpenID Connect (the modern standard; use SAML only if required by a legacy system).
- Client ID — enter a short, lowercase, hyphen-separated identifier (e.g.,
my-app-frontend). This is theclient_idyour application sends in token requests. - Name — optional human-readable display name shown in the admin console.
- Description — optional free-text note.
- Click Next.
- On the Capability config step:
- Client authentication — leave Off for a public client (SPA, mobile); turn it On for a confidential client (server-side app). See the Client Types lesson for details.
- Authorization — leave Off unless you need Keycloak’s fine-grained authorisation policies.
- Click Next.
- On the Login settings step — this is where security-critical redirect settings live:
- Root URL — the base URL of your application (e.g.,
http://localhost:3000). Keycloak prepends this to relative URIs. - Valid redirect URIs — the exact URIs Keycloak is allowed to redirect back to after login. Enter at least one (e.g.,
http://localhost:3000/*). Wildcards are permitted but should be as specific as possible in production. - Valid post logout redirect URIs — URIs allowed after logout. Enter
+to reuse the same list as valid redirect URIs, or specify explicitly. - Web origins — origins allowed to make cross-origin requests (CORS). Enter
+to derive from valid redirect URIs, or list explicitly (e.g.,http://localhost:3000). - Click Save.
- Root URL — the base URL of your application (e.g.,
Your client is now registered. You will land on the client’s Settings tab.
The clients list
Section titled “The clients list”The Clients page (left sidebar) shows every client registered in your realm. The list includes:
- Client ID — the identifier your app uses.
- Enabled — whether the client is active.
- Type — OpenID Connect or SAML.
- Description — your optional note.
Click any client ID to open its settings and tabs (Settings, Credentials, Roles, Client scopes, Advanced, etc.).
Key settings after creation
Section titled “Key settings after creation”Valid redirect URIs
Section titled “Valid redirect URIs”After a user authenticates, Keycloak redirects them back to one of the URIs in this list. If the redirect URI in the request does not match any entry, Keycloak rejects the request with an error. This is an important security control: it prevents authorisation-code interception attacks where an attacker tricks Keycloak into redirecting the code to a site they control.
Keep redirect URIs as specific as possible. In development, http://localhost:3000/* is acceptable. In production, list only the exact callback paths:
https://app.example.com/auth/callbackWeb origins
Section titled “Web origins”The Web origins list controls which origins browsers allow to call the Keycloak token endpoint directly (for CORS preflight). If your SPA runs on https://app.example.com and calls https://auth.example.com/realms/my-app/protocol/openid-connect/token, that origin must be listed here.
Setting Web origins to + is a convenient shortcut that tells Keycloak to allow all origins that appear in your Valid redirect URIs list.
A curl to inspect your client’s OIDC discovery document
Section titled “A curl to inspect your client’s OIDC discovery document”Every realm exposes an OpenID Connect discovery document. You can use it to verify your client’s issuer, token endpoint, and JWKS URI:
curl https://localhost:8080/realms/my-app/.well-known/openid-configuration | jq .Replace my-app with your realm name. The jq . part pretty-prints the JSON response.
Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
| Client type: OpenID Connect | The modern standard, compatible with most libraries and SDKs — easier to set up and debug | No extra benefit for a legacy system tied specifically to SAML assertions |
| An exact-match Valid redirect URI | Strongly prevents authorization-code interception, giving you clear control over exactly where Keycloak can send tokens back | Must be updated every time you add an environment or a new path, adding maintenance overhead |
Web origins set to + (derived from redirect URIs) | Configure once, with no need to keep two lists in sync | If the redirect URI list is too broad, Web origins becomes just as broad |
Common mistakes
Section titled “Common mistakes”- Using a wildcard
*in Valid redirect URIs on a production client — this lets Keycloak redirect to any domain matching the pattern, including an attacker’s domain. Specify exact callback paths only in production. - Registering an SPA as a confidential client and embedding the client secret in the frontend bundle — a secret embedded in client-side code is always effectively public, since anyone can open devtools. Use a public client with PKCE instead.
- Not setting Web origins to match the frontend’s real origin — this breaks CORS preflight when calling the token endpoint directly from the browser, or, if set too broadly, opens an unnecessary security gap.
Real-world example
Google Cloud Console — registers a separate OAuth client per environment (dev, staging, production), each with a redirect URI specific to that environment, so an authorization code or token can never leak across environments.
Stripe Connect — uses a confidential client with a client secret kept only on the server side, to register a platform application that connects to a large number of user accounts, with no secret ever reaching the end user’s browser.