Client credentials (M2M)
Authenticate a backend service as itself — no user, no redirect. Exchange the client's own credentials for an access token to call APIs machine-to-machine.
Overview
The client credentials grant is for machine-to-machine access — a backend service, cron job, or CLI authenticating as itself, with no user involved. There is no login, no redirect, and no ID token; the service exchanges its own credentials directly for an access token.
- Use it for service-to-service API calls, scheduled jobs, or internal tooling.
- Do not use it for signing users in — that's the authorization-code flow.
Register a service client
Create a confidential client with the client_credentials grant enabled and copy its client_id + client_secret. A service client has no redirect URI — it never runs a browser flow.
- Client type: confidential / service.
- Grant type:
client_credentials. - Allowed scopes: the machine scopes your API expects (e.g.
reports.read).
Request a token
POST your credentials to the token endpoint. There is no code, redirect_uri, or PKCE.
curl -X POST https://dev-api.niaauth.com/oauth/token \
-d grant_type=client_credentials \
-d client_id=your-service-client-id \
-d client_secret=your-service-client-secret \
-d scope=reports.readid_token and no refresh_token are issued — when the token expires, just request another.Use the token
Send the access token as a Bearer token to your API. The resource server verifies it (RS256, against the JWKS) exactly like a user token — but the subject is the service, not a user.
curl https://api.example.com/reports \
-H "Authorization: Bearer ACCESS_TOKEN"In the token, sub identifies the service (not a user) and there is no user profile — authorize on client_id / scope instead.
Best practices
- Cache the token until shortly before
expires_in— don't fetch a new one per request. - Keep the
client_secretin a secret manager / environment variable, never in client-side code. - Give each service its own client and the narrowest scopes it needs.
- Rotate the secret periodically, and immediately if it leaks.