Skip to content

Endpoints

Keycloak exposes endpoints across 4 groups. The base URL for each group impacts token issuance, redirect link generation, and OIDC discovery.

Frontend group

Publicly accessible. Used for browser-based flows and user interaction.

Path Description
/realms/{realm}/protocol/openid-connect/auth OIDC Authorization / Login
/realms/{realm}/protocol/saml SAML SSO
/realms/{realm}/protocol/openid-connect/auth/device Device Authorization
/realms/{realm}/login-actions/... Consent / Registration actions
/realms/{realm}/account/ Account management (user self-service)
/realms/{realm}/.well-known/openid-configuration OIDC Discovery Document

Backend group

Programmatic client-to-server communication. Handles token operations without user interaction.

Path Description
/realms/{realm}/protocol/openid-connect/token Token Endpoint
/realms/{realm}/protocol/openid-connect/token/introspect Token Introspection
/realms/{realm}/protocol/openid-connect/logout End Session (Logout)
/realms/{realm}/protocol/openid-connect/revoke Token Revocation
/realms/{realm}/protocol/openid-connect/userinfo Userinfo
/realms/{realm}/protocol/openid-connect/certs JWKS URI
/realms/{realm}/clients-registrations/... Client Registration
/realms/{realm}/protocol/saml/descriptor SAML Descriptor (metadata)

Administration group

Not exposed publicly.

Path Description
/admin/ Administration Console (web UI)
/admin/realms/{realm}/... Admin REST API
/resources/ Static assets (CSS, JS for admin console)

Management interface

Dedicated port 9000 (separate from the main server). Health is enabled by default; metrics require opt-in via KC_METRICS_ENABLED or spec.additionalOptions.

Path Purpose
/health/ready Readiness probe
/health/live Liveness probe
/health/started Startup probe
/metrics Prometheus metrics

Port: KC_HTTP_MANAGEMENT_PORT / spec.httpManagement.port (default 9000).

Exposure recommendations

Only expose HTTPS (port 8443 via KC_HTTPS_PORT). Do not enable HTTP.

Path Exposure Notes
/realms/ Public Core OIDC/SAML endpoints
/resources/ Public Static assets for login pages and admin console
/js/ Public Keycloak JS adapter
/admin/ Internal only Admin UI and REST API
/health Internal only Management interface — port 9000
/metrics Internal only Management interface — port 9000

Admin console access

The admin web UI (/admin/) should be exposed on a separate hostname using --hostname-admin / KC_HOSTNAME_ADMIN / spec.hostname.admin. The admin console also needs /resources/ for its static assets (already public).

Never expose /admin/ on the same public hostname as the frontend. Restrict it to a VPN, internal network, or a separate ingress with IP allowlisting.

Internal pod calls via the Kubernetes service

When a pod calls Keycloak using the internal Kubernetes service DNS name (e.g., keycloak-service.keycloak.svc.cluster.local), the Host header contains that name — not the configured KC_HOSTNAME.

With hostname-strict: true (default), Keycloak rejects these requests. Two solutions:

Option 1 - backchannel dynamic resolution (KC_HOSTNAME_BACKCHANNEL_DYNAMIC / spec.hostname.backchannelDynamic)

Keycloak accepts requests from any hostname on the backchannel. Issued tokens still carry the public KC_HOSTNAME in the iss claim, so token validation against the JWKS URI is unaffected.

Option 2 - split-horizon DNS

Configure in-cluster DNS so the public hostname resolves to the internal service ClusterIP. Pods use the public hostname; Host headers match; tokens are fully consistent. More complex to set up but behaviorally identical to external traffic.