Refresh Token
Obtain a new access token using a refresh token. This endpoint implements refresh token rotation - the old refresh token is invalidated and a new one is issued.
Request
POST /api/v1/auth/refresh
Authentication
Public - No authentication required (refresh token is provided in request body).
Request Body
{
"refreshToken": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
| Name | Type | Required | Description |
|---|---|---|---|
| refreshToken | string | Yes | Valid refresh token obtained from login or previous refresh |
Response
Success Response (200 OK)
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "a89fc20c-68dd-5483-b678-1f13c3d4e590",
"expiresIn": 3600,
"tokenType": "Bearer",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"email": "[email protected]",
"name": "John Doe",
"isOrgAdmin": true,
"organizationId": "223e4567-e89b-12d3-a456-426614174001",
"organizationName": "Acme Corporation",
"organizationSlug": "acme-corporation",
"subscriptionTier": "BUSINESS",
"mfaEnabled": false
}
}
| Field | Type | Description |
|---|---|---|
| accessToken | string | New JWT access token for authenticated requests |
| refreshToken | string | New refresh token (old token is now invalidated) |
| expiresIn | number | Access token expiration time in seconds |
| tokenType | string | Token type (always "Bearer") |
| user | object | User information object |
| user.id | string | Unique user ID (UUID) |
| user.email | string | User's email address |
| user.name | string | User's full name |
| user.isOrgAdmin | boolean | Whether the user is an organization admin |
| user.organizationId | string | Organization ID (UUID) |
| user.organizationName | string | Organization name |
| user.organizationSlug | string | URL-friendly organization identifier |
| user.subscriptionTier | string | Subscription tier (FREE, BUSINESS, ENTERPRISE, PLATFORM) |
| user.mfaEnabled | boolean | Whether MFA is enabled for this user |
Error Responses
| Status Code | Description |
|---|---|
| 400 Bad Request | Invalid request body (missing refresh token) |
| 401 Unauthorized | Invalid, expired, or revoked refresh token |
| 403 Forbidden | User or organization is suspended |
| 429 Too Many Requests | Rate limit exceeded |
| 500 Internal Server Error | Server error occurred |
Token Rotation
EntryGuard implements refresh token rotation for enhanced security:
- When you refresh an access token, you receive both a new access token AND a new refresh token
- The old refresh token is immediately invalidated and cannot be reused
- Always store the new refresh token and discard the old one
- Attempting to reuse an old refresh token will result in a 401 Unauthorized error
Example
curl -X POST https://api.entryguard.io/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}'
Example Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjNlNDU2Ny1lODliLTEyZDMtYTQ1Ni00MjY2MTQxNzQwMDAiLCJvcmdJZCI6IjIyM2U0NTY3LWU4OWItMTJkMy1hNDU2LTQyNjYxNDE3NDAwMSIsInJvbGVzIjpbIk9SR19BRE1JTiJdLCJpYXQiOjE3MDkwNTMyMDAsImV4cCI6MTcwOTA1NjgwMH0.abc456",
"refreshToken": "a89fc20c-68dd-5483-b678-1f13c3d4e590",
"expiresIn": 3600,
"tokenType": "Bearer",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"email": "[email protected]",
"name": "John Doe",
"isOrgAdmin": true,
"organizationId": "223e4567-e89b-12d3-a456-426614174001",
"organizationName": "Acme Corporation",
"organizationSlug": "acme-corporation",
"subscriptionTier": "BUSINESS",
"mfaEnabled": false
}
}
Best Practices
- Store refresh tokens securely (e.g., httpOnly cookies for web apps, secure storage for mobile)
- Refresh access tokens before they expire to maintain a seamless user experience
- Handle 401 errors by attempting to refresh the token once, then redirect to login if refresh fails
- Never expose refresh tokens in URLs or client-side JavaScript