Secure Applications with OpenID Connect

This guide describes how to integrate a client application with Keycloak using the OpenID Connect (OIDC) protocol. Keycloak acts as the Identity Provider (IdP) and issues tokens that your application validates.

Integration Approach

Keycloak 26.x recommends using standard OIDC/OAuth 2.0 client libraries rather than Keycloak-specific adapters. Most legacy Keycloak adapters (Java, JavaScript, Node.js) have been deprecated in favor of generic OIDC libraries that work with any compliant provider.

Choose a library based on your application platform:

PlatformRecommended Libraries
JavaScript / SPAoidc-client-ts, angular-auth-oidc-client, react-oidc-context
Java / Spring BootSpring Security OAuth2 Client (spring-boot-starter-oauth2-client)
Gocoreos/go-oidc, golang.org/x/oauth2
Pythonauthlib, python-keycloak
Node.jsopenid-client, passport-openidconnect
.NETMicrosoft.AspNetCore.Authentication.OpenIdConnect

Prerequisites

  • A Keycloak instance with a configured Realm.
  • An OIDC client registered in Keycloak (see Manage Clients).

Step 1: Note the OIDC Discovery URL

Every Realm exposes an OIDC discovery endpoint:

https://<keycloak-host>/realms/<realm>/.well-known/openid-configuration

This endpoint returns all the URLs your application needs (authorization, token, userinfo, JWKS, logout).

Step 2: Configure Your Application

Provide the following to your OIDC library:

ParameterValue
Issuer / Authorityhttps://<keycloak-host>/realms/<realm>
Client IDThe client ID registered in Keycloak
Client SecretThe client secret (for confidential clients only)
Redirect URIA URI registered in the client's Valid redirect URIs
Scopesopenid (required), plus profile, email, roles as needed

Step 3: Implement the Authorization Code Flow

The Authorization Code Flow (with PKCE for public clients) is the recommended flow for interactive applications.

Flow Overview

  1. Your application redirects the user to the Keycloak authorization endpoint.
  2. The user authenticates at Keycloak.
  3. Keycloak redirects back to your application with an authorization code.
  4. Your application exchanges the code for tokens at the token endpoint.
  5. Your application validates the ID token and uses the access token to call APIs.

Authorization Request

GET https://<keycloak-host>/realms/<realm>/protocol/openid-connect/auth?
  response_type=code&
  client_id=my-app&
  redirect_uri=https://my-app.example.com/callback&
  scope=openid profile email&
  state=<random-state>&
  code_challenge=<PKCE-challenge>&
  code_challenge_method=S256

Token Exchange

curl -s -X POST \
  "https://<keycloak-host>/realms/<realm>/protocol/openid-connect/token" \
  -d "grant_type=authorization_code" \
  -d "code=<authorization-code>" \
  -d "redirect_uri=https://my-app.example.com/callback" \
  -d "client_id=my-app" \
  -d "client_secret=<secret>" \
  -d "code_verifier=<PKCE-verifier>"

Token Response

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 300,
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "id_token": "eyJhbGciOiJSUzI1NiIs...",
  "scope": "openid profile email"
}

Securing a REST API (Resource Server)

For backend APIs that receive bearer tokens from other applications:

  1. Register a confidential client in Keycloak with all standard authentication flows disabled (uncheck Standard flow, Direct access grants, etc.). This is the recommended approach for resource servers in Keycloak 17+, as the deprecated bearer-only client type is no longer exposed in the Admin Console UI.

  2. Configure your API to validate access tokens using the Keycloak JWKS endpoint:

    https://<keycloak-host>/realms/<realm>/protocol/openid-connect/certs
  3. On each request, extract the Authorization: Bearer <token> header.

  4. Validate the token signature using the JWKS keys.

  5. Check the iss (issuer), exp (expiration), and aud (audience) claims.

  6. Use token claims (roles, groups) for authorization decisions.

Logout

RP-Initiated Logout

Redirect the user to the Keycloak logout endpoint to terminate the SSO session:

GET https://<keycloak-host>/realms/<realm>/protocol/openid-connect/logout?
  id_token_hint=<id-token>&
  post_logout_redirect_uri=https://my-app.example.com/logged-out&
  client_id=my-app

Back-Channel Logout

For applications that need to be notified when a user logs out from another application:

  1. In the client settings, set Backchannel logout URL to your application's logout endpoint (for example, https://my-app.example.com/backchannel-logout).
  2. Enable Backchannel logout session required.
  3. Keycloak sends a logout token (JWT) to your endpoint when the user's session is terminated.

Token Refresh

Use the refresh token to obtain new access tokens without re-authentication:

curl -s -X POST \
  "https://<keycloak-host>/realms/<realm>/protocol/openid-connect/token" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=<refresh-token>" \
  -d "client_id=my-app" \
  -d "client_secret=<secret>"

Other Grant Types

Grant TypeUse Casegrant_type Value
Client CredentialsMachine-to-machine, no user contextclient_credentials
Device AuthorizationInput-constrained devices (IoT, CLI tools, smart TVs)urn:ietf:params:oauth:grant-type:device_code
Token ExchangeExchange one token for another (delegation, impersonation)urn:ietf:params:oauth:grant-type:token-exchange
Deprecated Grant Types

The Resource Owner Password Credentials (ROPC) grant is supported but discouraged. It exposes user credentials to the client application and cannot support MFA. Use the Authorization Code flow instead.