JWT Token Endpoint
Overview
The JWT token endpoint issues self-contained JSON Web Tokens. Unlike OAuth2 opaque tokens, JWTs can be validated offline by inspecting the signature and claims, without calling back to Apinizer.
Endpoint
| Mode | Method | Endpoint |
|---|---|---|
| Manage From This Policy | POST | https://yourApinizerAddress/auth/jwt |
| Manage From ACL | POST | https://yourApinizerAddress/credential/jwt |
Request
Headers
| Header | Value | Required |
|---|---|---|
| Content-Type | application/x-www-form-urlencoded | Yes |
| Authorization | Basic (base64-encoded credentials) | See below |
Authentication
Callers must authenticate using HTTP Basic authentication in the Authorization header:
Authorization: Basic base64(client_id:client_secret)
- In "Manage From This Policy" mode:
client_idandclient_secretare the application key and secret from the API proxy, proxy group, or policy group Overview section. - In "Manage From ACL" mode:
client_idandclient_secretare from the credential entity.
Alternatively, credentials can be sent in the request body (see below).
Request Body
The request body is sent as application/x-www-form-urlencoded with the following parameters:
client_credentials Grant Type
| Parameter | Type | Required | Description |
|---|---|---|---|
| grant_type | string | Yes | Must be client_credentials |
| client_id | string | Yes (if not in Authorization header) | The application key or credential client ID |
| client_secret | string | No (if not in Authorization header) | The application secret or credential client secret |
| scope | string | No | Space-separated list of requested scopes |
password Grant Type
| Parameter | Type | Required | Description |
|---|---|---|---|
| grant_type | string | Yes | Must be password |
| client_id | string | Yes (if not in Authorization header) | The application key or credential client ID |
| client_secret | string | No (if not in Authorization header) | The application secret or credential client secret |
| username | string | Yes | Username from the selected authentication pool |
| password | string | Yes | Password from the selected authentication pool |
| scope | string | No | Space-separated list of requested scopes |
refresh_token Grant Type
| Parameter | Type | Required | Description |
|---|---|---|---|
| grant_type | string | Yes | Must be refresh_token |
| client_id | string | Yes (if not in Authorization header) | The application key or credential client ID |
| client_secret | string | No (if not in Authorization header) | The application secret or credential client secret |
| refresh_token | string | Yes | The refresh token value from a previous token response |
Example Request: client_credentials
curl -X POST \
"https://yourApinizerAddress/auth/jwt" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=your-app-key&client_secret=your-app-secret"
Or send the secret via Basic Authentication header (alternative to body params):
curl -X POST \
"https://yourApinizerAddress/auth/jwt" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic $(echo -n 'your-app-key:your-app-secret' | base64)" \
-d "grant_type=client_credentials"
Example Request: password Grant
curl -X POST \
"https://yourApinizerAddress/auth/jwt" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password&client_id=your-app-key&client_secret=your-app-secret&username=user1&password=user_password"
Example Request: refresh_token Grant
curl -X POST \
"https://yourApinizerAddress/auth/jwt" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&client_id=your-app-key&client_secret=your-app-secret&refresh_token=the_refresh_token_value"
Response
Success Response (200 OK)
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": "read write"
}
| Field | Type | Description |
|---|---|---|
| access_token | string | The issued JWT token (base64-encoded) |
| token_type | string | Always Bearer |
| expires_in | integer | Token expiration time in seconds |
| refresh_token | string | The refresh token JWT (if refresh is enabled) |
| scope | string | Resolved scope for the token (if scope was requested and roles are configured) |
JWT Claims
A typical JWT access token contains the following claims:
{
"iss": "https://yourApinizerAddress/auth",
"sub": "user1",
"aud": "your-app-key",
"exp": 1234567890,
"iat": 1234567200,
"scope": "read write"
}
| Claim | Description |
|---|---|
| iss | Issuer (Apinizer gateway address) |
| sub | Subject (username, if password grant; otherwise the client_id) |
| aud | Audience (usually the application key) |
| exp | Expiration time (unix timestamp) |
| iat | Issued at time (unix timestamp) |
| scope | Space-separated list of scopes (if scope was requested) |
The exact claims included in a JWT can be configured via policies and may vary based on your setup. The claims listed above are common defaults.
Error Response (400 Bad Request)
{
"error": "invalid_grant",
"error_description": "The client_id is invalid or the user is not found."
}
Common error codes:
invalid_client— Authentication failed (invalid client_id or client_secret)invalid_grant— Grant type is not supported or credentials are invalidinvalid_scope— Requested scope is not available for this client
JWT Refresh Endpoint
To refresh an expired JWT access token without re-authenticating, call the main JWT endpoint with grant_type=refresh_token (same URL as issuance):
curl -X POST \
"https://yourApinizerAddress/auth/jwt" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&client_id=your-app-key&client_secret=your-app-secret&refresh_token=the_refresh_token_value"
The response is identical to the main token endpoint — a new JWT access token is issued if the refresh token is still valid.
JWT Regenerate Endpoint
When JWT Authentication policy regenerate is configured (Authentication API + Regenerator service), you can obtain a new access JWT from a still-valid access token:
| Mode | Method | Endpoint |
|---|---|---|
| Manage From This Policy | POST | https://yourApinizerAddress/auth/jwt/regenerate |
| Manage From ACL | POST | https://yourApinizerAddress/credential/jwt/regenerate |
Regenerate Request
Send the current access JWT as a Bearer token. Authenticate the client with client_id and client_secret in the form body (or Basic auth):
curl -X POST \
"https://yourApinizerAddress/auth/jwt/regenerate" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Bearer YOUR_CURRENT_ACCESS_JWT" \
-d "client_id=your-app-key&client_secret=your-app-secret"
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_id | string | Yes (if not in Authorization Basic header) | Application key or credential client ID |
| client_secret | string | Yes (if not in Authorization Basic header) | Application secret or credential client secret |
Regenerate is not the same as refresh: refresh uses grant_type=refresh_token on /auth/jwt; regenerate uses /auth/jwt/regenerate with a Bearer access token. Do not send grant_type=refresh_token to the regenerate URL.
Related Pages
- OAuth2 Token Endpoint — Issue opaque tokens instead
- Token Introspection — Check token validity
- Token Revocation — Revoke tokens
- Discovery & JWKS — Discover endpoints and public keys