Tokens
POST /v1/auth/token, /token/refresh and /token/revoke — the session token pair and "refresh means rotate".
These three endpoints turn a finished flow into a session, keep it alive, and end it. None of them requires a session token: the first two take a flow token or a refresh token, and revocation takes a refresh token.
POST /token
Exchange the flow token for a session token pair. The flow token goes in the Bearer header, and the body carries the device id.
| Parameter | Type | Required | Notes |
|---|---|---|---|
did | string | ✅ | Device id, 8–256 chars; the session is bound to it |
{
"success": true,
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900,
"acr": "urn:muoceon:acr:aal2",
"auth_time": "2026-11-14T08:31:12.000Z"
}| Field | Notes |
|---|---|
access_token | Short-lived session token |
refresh_token | Rotation token; not returned when the flow requires no persistent session |
expires_in | Access token lifetime in seconds |
acr | Achieved authentication level for this session |
auth_time | When authentication actually happened; step-up compares against it |
POST /token/refresh
| Parameter | Type | Required | Notes |
|---|---|---|---|
refresh_token | string | ✅ | The refresh token issued previously |
{
"success": true,
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 900,
"acr": "urn:muoceon:acr:aal1",
"auth_time": "2026-11-14T08:31:12.000Z"
}Refresh means rotate
Every refresh invalidates the old refresh token and issues a new one. The client must overwrite the stored value. A refresh token that has already been rotated can never be used again; a replayed one is treated as theft and the whole session is revoked.
| Rule | Notes |
|---|---|
auth_time does not change | Refresh does not re-authenticate; the original authentication time is preserved, so a stale session cannot become "recently verified" by refreshing |
| Session is re-checked | If the session has been signed out elsewhere, refresh returns 401 |
| Device must match | The did bound at creation must match the stored value |
POST /token/revoke
| Parameter | Type | Required | Notes |
|---|---|---|---|
refresh_token | string | ✅ | The refresh token to invalidate |
{ "success": true, "message": "Session revoked" }Idempotent: revoking an already invalid token also returns 200. The whole session behind the refresh token is terminated.
When to use which
| Situation | Endpoint |
|---|---|
| The flow is finished and you need a session | /token |
| The access token expired but the session should continue | /token/refresh |
| The user chose "sign out on this device" | /token/revoke |
| The user chose "sign out everywhere" | DELETE /session/others in Sessions |
| A third-party client gives up its authorization | POST /revoke in the oauth context |
Related
- Session management: Sessions
- Step-up re-signs the access token: Session elevation