Offline Tokens
Offline tokens are long-lived authentication tokens designed for offline capture scenarios where devices need to operate without continuous network connectivity. These tokens are valid for 12 months and can be used to upload, edit, and list resources.
Overview
Offline tokens enable data capture devices to authenticate and upload data over extended periods without frequent re-authentication. These tokens are designed for remote scenarios where an administrator logs in once, generates a token, stores it on the device, and the device uses that token for up to 12 months to upload captured data.
Offline tokens have a 12-month lifetime and limited permissions. They can upload resources, list resources, and edit existing resources, but cannot perform administrative operations like user management or token generation.
Create Offline Token
Generates a new offline token that expires in 12 months.
POST /api/authorization/offline_token
Authorization Required: Administrator role
Request
Headers:
Authorization: Bearer {admin_access_token}Body: None
Response
Success (200 OK):
{
"token": "base64-encoded-token-string",
"expiresAt": "2026-10-07T12:00:00Z"
}Response Fields:
token(string): The offline authentication token to be used for API requestsexpiresAt(string, ISO 8601): The UTC timestamp when this token will expire
Error Responses:
401 Unauthorized: No valid authentication token provided403 Forbidden: User is not an administrator
Example Request:
curl -X POST https://api.example.com/api/authorization/offline_token \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6..."Example Response:
{
"token": "dGhpc2lzYW5vZmZsaW5ldG9rZW4=",
"expiresAt": "2026-10-07T09:30:00Z"
}List Offline Tokens
Returns metadata for all offline tokens. Token values are never included in the response.
GET /api/authorization/offline_token
Authorization Required: Administrator role
Request
Headers:
Authorization: Bearer {admin_access_token}Body: None
Response
Success (200 OK):
[
{
"secretId": "550e8400-e29b-41d4-a716-446655440000",
"userId": "660e8400-e29b-41d4-a716-446655440001",
"username": "admin",
"expiresAt": "2026-10-07T12:00:00Z",
"lastUsedAt": "2025-10-07T09:30:00Z",
"revoked": false,
"tokenHint": "abcd"
}
]Response Fields:
secretId(string, UUID): Stable identifier for revoke operationsuserId(string, UUID): Admin user who created the tokenusername(string): Username of the creating adminexpiresAt(string, ISO 8601): UTC expiry timestamplastUsedAt(string, ISO 8601): Last successful validation timestamprevoked(boolean): Whether the token has been revokedtokenHint(string): Last four characters of the token for identification
Error Responses:
401 Unauthorized: No valid authentication token provided403 Forbidden: User is not an administrator, or caller is using an offline token
Revoke a Single Offline Token
Revokes one offline token without affecting other tokens for the same user.
DELETE /api/authorization/offline_token/{secretId}
Authorization Required: Administrator role
Request
Headers:
Authorization: Bearer {admin_access_token}Path parameter: secretId (UUID from the list endpoint)
Response
Success (204 No Content): Token revoked.
Error Responses:
401 Unauthorized: No valid authentication token provided403 Forbidden: User is not an administrator404 Not Found: No offline token with thatsecretId
v2 Management API (recommended for control center UIs)
Cluster Manager and other operator tools should call the v2 public API rather than heat-auth directly. Ingress routes /api/v2/* to heat-v2-api, which proxies to heat-auth with the caller’s Bearer token.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v2/admin/offline-tokens | Create offline token |
GET | /api/v2/admin/offline-tokens | List offline token metadata |
DELETE | /api/v2/admin/offline-tokens/{secretId} | Revoke one offline token |
All three routes require an Administrator access token. Offline tokens cannot call these routes.
See HEAT v2 API Documentation for request and response examples.
Using Offline Tokens
Offline tokens are designed exclusively for heat-api endpoints (data uploads, resource management). They cannot be used with heat-auth endpoints.
Example - Using with heat-api:
curl -X GET https://api.example.com/api/resources \
-H "Authorization: Bearer dGhpc2lzYW5vZmZsaW5ldG9rZW4="Example - Blocked by heat-auth (403 Forbidden):
curl -X GET https://heat-auth.example.com/api/users \
-H "Authorization: Bearer dGhpc2lzYW5vZmZsaW5ldG9rZW4="
# Returns: 403 Forbidden - "Offline tokens cannot access this endpoint"Key differences from standard tokens:
- Lifetime: 12 months instead of 8 hours
- No Refresh: Offline tokens cannot be refreshed. When expired, a new token must be generated by an administrator.
- Scope: Limited to heat-api operations - blocked from all heat-auth authenticated endpoints
- Validation: Can only be validated via
/authorization/validate- all other heat-auth endpoints reject offline tokens
Validating Tokens
The standard token validation endpoint returns additional metadata for offline tokens.
Endpoint: POST /api/authorization/validate
Request Body:
{
"token": "dGhpc2lzYW5vZmZsaW5ldG9rZW4="
}Response (200 OK):
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"username": "admin",
"firstName": "Admin",
"lastName": "User",
"title": "",
"company": "",
"email": "admin@example.com",
"role": "Administrator",
"createdAt": "2025-01-01T00:00:00Z",
"updatedAt": "2025-10-07T00:00:00Z",
"forceChangePasswordNextSignin": false,
"isRegistrationComplete": true,
"hasAcceptedDataPrivacy": true,
"isActive": true,
"isOfflineToken": true
}Key Field:
isOfflineToken(boolean): Indicates whether this is an offline token. Consuming services should check this field to enforce scope limitations.
Token Scope and Permissions
Note: Scope enforcement in heat-api is not yet implemented. The permissions below represent the intended scope for offline tokens.
Offline tokens have the following scope:
Allowed Operations
- Upload Resources: POST requests to create new data/resources (heat-api)
- List Resources: GET requests to retrieve lists of resources (heat-api)
- Edit Resources: PUT/PATCH requests to update existing resources (heat-api)
- Read Resources: GET requests for individual resource details (heat-api)
Restricted Operations
- Delete Resources: Cannot delete resources
- User Management: Cannot create, update, or delete users
- Administrative Operations: Cannot perform admin-only operations
- Token Management: Cannot generate new tokens or revoke other tokens
Implementing Scope Enforcement
In HEAT Auth Service
Offline tokens in heat-auth are blocked from all authenticated endpoints. The [AuthorizeRole] attribute automatically rejects offline tokens with a 403 Forbidden response.
Why? Offline tokens are designed exclusively for heat-api (data uploads, resource management). They should never be used for:
- Creating, updating, or deleting users
- Generating new tokens
- Any heat-auth administrative operations
The only heat-auth endpoint that accepts offline tokens is /authorization/validate, which is intentionally not protected by [AuthorizeRole] so that other services can validate offline tokens.
In HEAT API and Other Services
TODO: Scope enforcement for offline tokens in heat-api is not yet implemented. This section will be updated once the implementation is complete in a future ticket.
Services consuming offline tokens (e.g., heat-api for data uploads) must enforce scope restrictions:
- Validate the token using heat-auth’s
/authorization/validateendpoint - Check the
isOfflineTokenfield in the response - Enforce restrictions based on token type (block DELETE operations, etc.)
Token Revocation
Revoke a single offline token (preferred)
Use the per-token revoke endpoint when one capture device is lost or compromised:
DELETE /api/authorization/offline_token/{secretId}
Or via v2: DELETE /api/v2/admin/offline-tokens/{secretId}
Revoke all tokens for a user
The standard token revocation endpoint revokes all tokens for a user, including offline tokens and active login sessions:
POST /api/authorization/revoke
Request Body:
{
"username": "admin"
}Important: Bulk revoke invalidates every token for that user. Prefer single-token revoke when only one device needs to be cut off.
Security Considerations
-
Store Securely: Offline tokens should be stored securely on capture devices (encrypted storage, secure enclaves, etc.)
-
Limit Distribution: Only generate offline tokens when necessary for legitimate offline capture scenarios
-
Monitor Usage: Track which devices are using offline tokens and monitor for suspicious activity
-
Rotation: While tokens last 12 months, consider rotating them periodically if devices can be accessed
-
Revocation: If a device is lost or compromised, revoke that offline token by
secretId. Use bulk user revoke only when all tokens for that admin must be invalidated. -
Admin Only: Only administrators can generate offline tokens, ensuring controlled distribution
Implementation Notes
- Offline tokens are stored in the same
Secretstable as standard tokens, differentiated by theIsOfflineTokenflag - Token validation logic is unchanged - offline tokens go through the same expiry and revocation checks
- The 12-month expiry is enforced at generation time and validated during each API request
- No refresh mechanism exists for offline tokens by design
Example Workflow
This example shows the complete lifecycle of an offline token, from generation to expiration.
Admin Generates Token
An administrator logs in and uses their access token to generate an offline token:
# Admin logs in and gets access token
curl -X POST https://api.example.com/api/authorization/token \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "password123",
"rememberMe": false
}'
# Use access token to generate offline token
curl -X POST https://api.example.com/api/authorization/offline_token \
-H "Authorization: Bearer {admin_access_token}"Store Token on Capture Device
Store the returned token value securely on the capture device using encrypted storage or a secure enclave.
Device Uses Token for Uploads
The device uses the offline token to authenticate requests for the next 12 months:
# Device uploads captured data
curl -X POST https://api.example.com/api/captures \
-H "Authorization: Bearer {offline_token}" \
-H "Content-Type: application/json" \
-d '{
"data": "captured_data_here"
}'Token Expiration
When the token expires after 12 months, the device receives 401 Unauthorized responses. An administrator must generate a new offline token and update the device.
Frequently Asked Questions
Can offline tokens be refreshed?
No. Offline tokens have a fixed 12-month lifetime and cannot be refreshed. This is by design to simplify offline scenarios.
What happens if the admin user who created the token is deleted?
The token is invalidated since tokens are tied to user accounts.
Can non-admin users generate offline tokens?
No. Only users with the Administrator role can generate offline tokens.
How many offline tokens can be created?
There is no hard limit. Each token is tied to the admin user who creates it.
Can I see a list of all offline tokens?
Yes. Administrators can list offline token metadata via GET /api/authorization/offline_token (heat-auth) or GET /api/v2/admin/offline-tokens (v2 API). Token values are never returned after creation.
How do I know if a device is using an offline token?
When validating a token, check the isOfflineToken field in the response. You can also query the database Secrets table with IsOfflineToken = true.