Get an access token for a backend service
Sign a backend service in as itself with the client credentials grant, and get an access token for the one API it calls.
A backend service that calls another service has no person to sign in. It signs in as itself with the client_credentials grant (RFC 6749, section 4.4), and receives an access token for the one API it calls.
Use this guide for a service that holds a client secret. For an AI agent, see Give an AI agent an identity. An agent holds its own key, never a shared secret.
Before you begin
You need:
- An AuthFI project and its issuer, the project's URL. This guide uses
https://acme.authfi.io. - Permission to add applications in the AuthFI console.
- The API you want to call, registered as an application in the same project. You need its client ID.
Register the calling service
- In the console, open Integrations > Applications and choose Register.
- Select OIDC / OAuth 2.0, then choose Continue.
- Select the kind Machine-to-machine.
- Enter a Name.
- Check the Review step, then choose Register.
The Done step shows the application's client ID, and its Client secret. The client secret is shown once. Copy both, then tick I have copied the client secret.
export CLIENT_ID=<the calling service's client ID>
export CLIENT_SECRET=<the calling service's client secret>Grant the service access to the API
An access token is issued for one API, named by that API's client ID. The calling service must hold a grant on the API's application before it can request a token for it.
- On the Done step, choose the button that opens the application. You can also open it later from Integrations > Applications.
- On the application's page, choose Allow an API and allow the API you want to call.
The APIs the service can call are listed in the APIs it may call section of its page.
export API_CLIENT_ID=<the API's client ID>Request an access token
Send the service's client ID and client secret to the token endpoint, and name the API in resource. The body is form-encoded.
POST
/oauth/tokencurl https://acme.authfi.io/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials \
-d resource="$API_CLIENT_ID"AuthFI returns an access token:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCIsImtpZCI6Ii4uLiJ9...",
"token_type": "Bearer",
"expires_in": 900
}The response contains an access token only, with no refresh token and no ID token. expires_in is in seconds. When the access token expires, request another.
Validate the access token at the API
The API validates the access token against the project's keys, and checks that aud contains the API's own client ID. For the full list of checks, see Checking a token.
Check that it works
Decode the payload of the access token and read its claims.
python3 -c 'import base64, json, sys; p = sys.argv[1].split(".")[1]; print(json.dumps(json.loads(base64.urlsafe_b64decode(p + "=" * (-len(p) % 4))), indent=2))' "$ACCESS_TOKEN"$ACCESS_TOKEN is the access_token from the previous response. The flow works when sub and client_id are the calling service's client ID, and aud contains the API's client ID.
What the access token contains
The access token has no sid, amr or acr claim, because no person signed in. Every claim is described in Tokens and claims.
Call more than one API
An access token is accepted at one API, the one named in resource. This stops an access token taken from one service from being used at another.
To call two APIs, request two access tokens, one for each resource. The calling service needs a grant on each API's application.
Troubleshooting
The token endpoint answers a failure with an OAuth error in error.
Every error is listed in the endpoint reference.
Next steps
Application types and redirect URIs
How a machine-to-machine application differs from the types that sign people in.
Tokens and claims
Every claim in an access token, and how a service checks one.
Protect an API
Require an access token at an API on Kubernetes, without changing its code.
Give an AI agent an identity
Sign an agent in with its own key instead of a client secret.