Skip to Content
This documentation is provided with the HEAT environment and is relevant for this HEAT instance only.
APIAuthOffline Tokens (HEAT Auth)

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 requests
  • expiresAt (string, ISO 8601): The UTC timestamp when this token will expire

Error Responses:

  • 401 Unauthorized: No valid authentication token provided
  • 403 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 operations
  • userId (string, UUID): Admin user who created the token
  • username (string): Username of the creating admin
  • expiresAt (string, ISO 8601): UTC expiry timestamp
  • lastUsedAt (string, ISO 8601): Last successful validation timestamp
  • revoked (boolean): Whether the token has been revoked
  • tokenHint (string): Last four characters of the token for identification

Error Responses:

  • 401 Unauthorized: No valid authentication token provided
  • 403 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 provided
  • 403 Forbidden: User is not an administrator
  • 404 Not Found: No offline token with that secretId

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.

MethodPathPurpose
POST/api/v2/admin/offline-tokensCreate offline token
GET/api/v2/admin/offline-tokensList 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:

  1. Lifetime: 12 months instead of 8 hours
  2. No Refresh: Offline tokens cannot be refreshed. When expired, a new token must be generated by an administrator.
  3. Scope: Limited to heat-api operations - blocked from all heat-auth authenticated endpoints
  4. 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:

  1. Validate the token using heat-auth’s /authorization/validate endpoint
  2. Check the isOfflineToken field in the response
  3. 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

  1. Store Securely: Offline tokens should be stored securely on capture devices (encrypted storage, secure enclaves, etc.)

  2. Limit Distribution: Only generate offline tokens when necessary for legitimate offline capture scenarios

  3. Monitor Usage: Track which devices are using offline tokens and monitor for suspicious activity

  4. Rotation: While tokens last 12 months, consider rotating them periodically if devices can be accessed

  5. 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.

  6. Admin Only: Only administrators can generate offline tokens, ensuring controlled distribution


Implementation Notes

  • Offline tokens are stored in the same Secrets table as standard tokens, differentiated by the IsOfflineToken flag
  • 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.