Token
The token endpoint exchanges credentials for access tokens. It supports three grant types: authorization_code, refresh_token, and client_credentials.
Exchanges credentials for access tokens. Supports authorization_code (with PKCE), refresh_token, and client_credentials (M2M, RFC 6749 §4.4) grant types.
| Parameter | Type | Description |
|---|---|---|
| grant_type* body | "authorization_code" | "refresh_token" | "client_credentials" | |
| code body | string | Authorization code (required for authorization_code grant) |
| redirect_uri body | string | Must match the original request (required for authorization_code grant) |
| client_id body | string | |
| client_secret body | string | |
| code_verifier body | string | PKCE verifier (required for authorization_code grant) |
| refresh_token body | string | Refresh token (required for refresh_token grant) |
| scope body | string | Space-separated scopes (optional, client_credentials grant). Must be a subset of the client's registered scopes. If omitted, all registered scopes are issued. |
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...",
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"scope": "openid profile email"
}Client Credentials (M2M)
The client_credentials grant (RFC 6749 §4.4) is for service-to-service authentication where there is no user. The client must be registered with client_credentials in its grant_types; otherwise the response is unauthorized_client (400).
curl -X POST https://your-app.aero2.dev/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=api:read api:write"The scope parameter is optional. If omitted, the response includes all scopes registered for the client. Each requested scope must be a subset of the client's registered scopes; otherwise the response is invalid_scope (400). No refresh token is issued — the client re-authenticates when the access token expires.
Issued token claims
{
"sub": "YOUR_CLIENT_ID",
"aud": "YOUR_CLIENT_ID",
"iss": "https://your-app.aero2.dev",
"scope": "api:read api:write",
"client_id": "YOUR_CLIENT_ID",
"gty": "client_credentials",
"token_use": "access",
"iat": 1735686000,
"exp": 1735689600
}The gty: "client_credentials" claim (a non-standard convention popularized by Auth0/Okta) lets resource servers branch cleanly between user-bearing tokens and M2M tokens without inspecting the shape of sub.
Token Lifetimes
| Token | Lifetime |
|---|---|
| Access token | 1 hour |
| ID token | 1 hour |
| Refresh token | 30 days |
| Session token | 1 hour |