M2M authentication is for servers, jobs, and services that need to call your API without a human user. Authaz issues access tokens through the standard OAuth 2.0 client credentials grant — no Universal Login, no redirects, just a client_id and client_secret exchange.
# Get an access token for a servicecurl -X POST "https://your-app.authaz.io/oauth2/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "scope=invoices:read"
The credential is its own principal as far as Authaz is concerned. Assign it roles, scope it to a tenant, do anything you'd do with a user:
# Give the credential a rolecurl -X POST https://your-app.authaz.io/api/v1/role-assignments \ -H "X-API-Key: $AUTHAZ_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subjectType": "credential", "subjectId": "cred_01h...", "roleId": "role_billing_writer" }'
The access token's permissions claim includes everything the credential can do. Your backend can read it and short-circuit unauthorized calls without round-tripping to Authaz.
For credentials that move through high-risk environments (CI runners, third-party servers), swap the static client_secret for a signed JWT (private_key_jwt). The secret never travels — only a one-shot, short-lived JWT does.
The clientSecret you noted earlier becomes irrelevant — Authaz validates the JWT signature against your uploaded JWKS instead. (JWKS = JSON Web Key Set, the standard format for publishing public keys.)
Static secrets need rotation. Authaz lets you rotate without downtime:
curl -X POST https://your-app.authaz.io/api/v1/applications/{appId}/m2m/credentials/{credId}/rotate \ -H "X-API-Key: $AUTHAZ_API_KEY"
The response contains the new clientSecret. The old one stays valid for a 24-hour grace period — deploy the new secret to your services within that window, then nothing further to do.
curl -X POST https://your-app.authaz.io/api/v1/applications/{appId}/m2m/credentials/{credId}/revoke \ -H "X-API-Key: $AUTHAZ_API_KEY"
Existing access tokens issued by the revoked credential remain valid until their expires_in runs out. Pair with defaultTokenLifetimeSeconds: 300 if you need fast revocation.