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, use the dedicated refresh endpoint:
| Mode | Method | Endpoint |
|---|---|---|
| Manage From This Policy | POST | https://yourApinizerAddress/auth/jwt/regenerate |
| Manage From ACL | POST | https://yourApinizerAddress/credential/jwt/regenerate |
Refresh Request
curl -X POST \
"https://yourApinizerAddress/auth/jwt/regenerate" \
-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.
The scope field is only included in the response if scope was requested in the request body and the endpoint is configured to return it. This behavior is controlled by Token Management Settings.
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