Lion Cipher Lab
Run the OAuth 2.0 Client Credentials flow (machine-to-machine) against Keycloak
- Identity & Access Management
- Intermediate
- ~50 min
- Free · no account required
Why it matters
Not every OAuth flow logs a person in. A huge amount of real traffic is one backend talking to another with no human anywhere — a nightly batch job calling an internal API, a payments service calling a ledger, a CI pipeline pushing to a registry. The OAuth 2.0 Client Credentials grant (RFC 6749 §4.4) is the standard, correct way to do that: the service authenticates as ITSELF using its own credentials and gets an access token scoped to what it is allowed to do. Getting this right — and knowing where it does NOT belong — is table stakes for any identity, backend, platform, or cloud role. In…
What you'll learn
- running the OAuth 2.0 Client Credentials grant (RFC 6749 §4.4) end to end from the terminal
- recognising machine-to-machine auth: a backend service acting as ITSELF with no user present, versus a user-login flow
- creating a confidential client in Keycloak and enabling its service account (the client credentials grant)
- reading a client secret and using client_id + client_secret at the /token endpoint
- decoding an access-token JWT and reading the tells of a machine token — sub is the service account, azp is the client, typ is Bearer
- explaining why no refresh_token is issued for client credentials, and why that is correct
- introspecting a token at the /token/introspect endpoint to confirm it is active
- knowing when to use client credentials vs Authorization Code + PKCE vs the device grant, and why a public client must never use client credentials
- the pro hardening path: stronger client auth (mTLS / private_key_jwt), scoped-down permissions, short token lifetimes, and workload identity (SPIFFE)
Steps in this lab
- The flow with no user in it
- Start a real authorization server: Keycloak in Docker
- Create a realm and a CONFIDENTIAL client
- Enable the service account (this IS the client credentials grant)
- Get a token: POST grant_type=client_credentials to /token
- Decode the token and read the machine-identity tells
- Prove the token is real: introspect it
- When to use it, when NOT to, and the pro way