Token Endpoints
POST /token/refresh
Exchange a valid refresh token for a new access + refresh token pair. The old refresh token is revoked (rotation).
Request:
{
"refresh_token": "a1b2c3d4...",
"app_id": "uuid"
}
Success Response (200):
{
"access_token": "eyJhbG...",
"refresh_token": "new-token...",
"token_type": "Bearer",
"expires_in": 900
}
Errors: | Status | Detail | Meaning | |--------|--------|---------| | 401 | Invalid or expired refresh token | Token not found, expired, or already used | | 401 | Token does not belong to this app | app_id mismatch | | 403 | Account suspended | User suspended for this app |
Replay Detection: If a revoked token is reused, ALL refresh tokens for that user+app are revoked.
POST /token/revoke
Revoke a refresh token (logout).
Request:
{
"refresh_token": "a1b2c3d4..."
}
Response (200):
{ "status": "ok" }
Always returns 200, even if the token doesn't exist (prevents information leakage).
POST /token/verify
Verify an access token and return its claims. For apps that can't do local JWT verification.
Request:
{
"token": "eyJhbG...",
"audience": "your-app-id"
}
Valid Response:
{
"valid": true,
"claims": {
"sub": "user-uuid",
"email": "user@example.com",
"roles": ["user", "admin"],
"aud": "app-uuid",
"iss": "https://keymaster.cloud-monitor.com",
"exp": 1710548100
}
}
Invalid Response:
{
"valid": false,
"error": "Token has expired"
}
Note: Prefer local JWKS verification for production. This endpoint is for debugging and apps that can't handle JWTs locally.
POST /auth/token
OAuth2 token endpoint. Currently supports client_credentials grant.
Request (form-encoded):
grant_type=client_credentials
&client_id=app-uuid
&client_secret=your-secret
&scope=push:send
Success Response (200):
{
"access_token": "eyJhbG...",
"token_type": "bearer",
"expires_in": 900,
"scope": "push:send"
}
Errors:
| Status | Detail |
|--------|--------|
| 400 | unsupported_grant_type |
| 400 | invalid_scope: xyz |
| 401 | invalid_client |
| 429 | too_many_requests (10 attempts/15min per client_id) |
GET /.well-known/jwks.json
Public keys for JWT verification. Cache these and refresh hourly or when kid doesn't match.
Response:
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"kid": "a1b2c3d4e5f6",
"n": "base64url-encoded-modulus...",
"e": "AQAB"
}
]
}
GET /.well-known/openid-configuration
OIDC discovery document.
Response:
{
"issuer": "https://keymaster.cloud-monitor.com",
"authorization_endpoint": "https://keymaster.cloud-monitor.com/login",
"token_endpoint": "https://keymaster.cloud-monitor.com/auth/token",
"userinfo_endpoint": "https://keymaster.cloud-monitor.com/userinfo",
"jwks_uri": "https://keymaster.cloud-monitor.com/.well-known/jwks.json",
"revocation_endpoint": "https://keymaster.cloud-monitor.com/token/revoke",
"response_types_supported": ["code"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"],
"scopes_supported": ["openid", "profile", "email", "roles", "push:send"],
"token_endpoint_auth_methods_supported": ["client_secret_post"],
"grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"]
}