Skip to content
ineedcloudineedcloud — home
All guides
SecurityHobbyist

Connect your first app to Keycloak using OIDC

Once Keycloak is running you want apps to actually use it. This guide covers registering a client, grabbing the credentials, and wiring up OpenID Connect in plain terms.

18 min readLast updated 4 May 2026

TL;DR

Register your app as a client in Keycloak, grab the client ID and secret, and use the OIDC discovery endpoint to wire up authentication. Your app redirects unauthenticated users to Keycloak — they log in once, get a token, and your app reads that token to know who they are.

What you'll need

  • Keycloak running with a realm and at least one user set up
  • An app to connect (this guide uses curl to test the token endpoint, so you don't need a specific language)
  • The realm name and your Keycloak base URL

Step 1 — Create a client

  1. In the Keycloak admin console, make sure you're in your app's realm (not master)
  2. Click Clients in the left sidebar
  3. Click Create client
  4. Set:
    • Client type: OpenID Connect
    • Client ID: something that identifies your app, e.g. my-app
  5. Click Next
  6. Toggle Client authentication to On (this makes it a "confidential" client with a secret)
  7. Leave Standard flow enabled
  8. Click Next, then Save

Step 2 — Configure redirect URIs

After saving, you're on the client settings page.

Under Valid redirect URIs, add the URL your app will redirect to after login, e.g.:

http://localhost:3000/auth/callback

For development, you can also add http://localhost:* as a wildcard. Tighten this to exact URLs before going live.

Click Save.

Step 3 — Get the client secret

  1. Click the Credentials tab on the client page
  2. Copy the Client secret — you'll need this in your app config

Step 4 — Find your OIDC discovery endpoint

Every Keycloak realm exposes a standard discovery document listing all its endpoints:

https://your-keycloak.com/realms/YOUR_REALM_NAME/.well-known/openid-configuration

Open that URL in a browser. You'll see a JSON document with everything your app needs — the authorisation endpoint, token endpoint, JWKS URI (for validating tokens), and more.

The key values for most libraries:

Setting Value
Issuer https://your-keycloak.com/realms/YOUR_REALM_NAME
Authorisation endpoint .../protocol/openid-connect/auth
Token endpoint .../protocol/openid-connect/token
JWKS URI .../protocol/openid-connect/certs

Step 5 — Test with curl

This confirms your client is working before you touch any application code.

curl -X POST \
  "https://your-keycloak.com/realms/YOUR_REALM_NAME/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=my-app" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "username=alice" \
  -d "password=alices-password"

If it works, you'll get a JSON response containing access_token, refresh_token, and id_token. If you get an error, check the realm name, client ID, and client secret.

Step 6 — Wire it up in your app

Most languages have OIDC libraries that accept the issuer URL and client credentials and handle the rest automatically:

Language / framework Library
Node.js openid-client
Python authlib or python-jose
PHP league/oauth2-client
Go coreos/go-oidc
Java/Spring Spring Security OAuth2

Pass the library your issuer URL (https://your-keycloak.com/realms/YOUR_REALM_NAME), client ID, and client secret. It will discover all the endpoints automatically from the .well-known document.

Common pitfalls

"Invalid redirect URI" error. The redirect URI your app sends must exactly match one of the valid redirect URIs registered in Keycloak — including the scheme, port, and path. A trailing slash mismatch will cause this.

Token validation fails. Make sure your app is validating tokens against the Keycloak JWKS URI (listed in the discovery document), not a hardcoded key. Keys rotate.

Using the "master" realm client. Never use the master realm for application authentication. Always create clients inside a dedicated realm.

Client authentication off. If you forgot to toggle "Client authentication" on when creating the client, it's a public client with no secret. Fine for single-page apps; not for server-side apps with a backend.

Where to go next