Skip to main content

Tokens

Apps can be shared externally via tokens, allowing access without a full Informer account. Tokens provide read-only access and are managed through the Token API.

Token Types

Apps use the app-view token type, which:

  • Grants read-only access to the app
  • Requires an appId field
  • Can be used to access /api/apps/{id}/view endpoints
  • Cannot be used for write operations

GET /api/apps/{id}/tokens

Get all tokens associated with an app.

Authentication: Required

Permissions Required: None (any user who can read the app)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID

Response:

Returns a HAL collection of Token records.

{
"_links": {
"self": { "href": "/api/apps/analytics:sales-dashboard/tokens" }
},
"_embedded": {
"inf:app-token": [
{
"_links": {
"self": { "href": "/api/tokens/token-uuid-1" }
},
"id": "token-uuid-1",
"type": "app-view",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"name": "Public Dashboard Link",
"token": "abc123def456...",
"readOnly": true,
"createdAt": "2024-02-10T10:00:00.000Z",
"expiresAt": null
}
]
},
"tokens": [...]
}

Key Fields:

FieldDescription
idToken UUID
typeAlways "app-view" for app tokens
appIdAssociated app UUID
nameOptional display name
tokenThe actual token string (use for authentication)
readOnlyAlways true for app-view tokens
expiresAtExpiration date (null = never expires)

Error Responses:

  • 404 Not Found - App doesn't exist or user lacks access

Creating App Tokens

Tokens are created through the general Token API (POST /api/tokens), not through the app-specific endpoint.

Example: Create an App Token

POST /api/tokens
Content-Type: application/json

{
"type": "app-view",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"name": "Public Dashboard Link",
"expiresAt": "2025-12-31T23:59:59.000Z"
}

Response:

{
"id": "token-uuid-1",
"type": "app-view",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"name": "Public Dashboard Link",
"token": "abc123def456ghi789...",
"readOnly": true,
"createdAt": "2024-02-13T10:30:00.000Z",
"expiresAt": "2025-12-31T23:59:59.000Z"
}

Required Fields:

FieldTypeDescription
typestringMust be "app-view"
appIdstringApp UUID

Optional Fields:

FieldTypeDescription
namestringDisplay name for the token
expiresAtstringISO 8601 date (null = never expires)

Using App Tokens

Once a token is created, it can be used to access the app without authentication.

Token Authentication

Include the token in requests using the Authorization header:

GET /api/apps/d4f8a2b1-1234-5678-90ab-cdef12345678/view
Authorization: Bearer abc123def456ghi789...

View Endpoint Access

App-view tokens grant access to:

  • GET /api/apps/{id}/view - App entry point (HTML)
  • GET /api/apps/{id}/view/-/{path*} - Static assets (CSS, JS, images)
  • GET /api/apps/{id}/view/api/{path*} - Proxied API calls (subject to whitelist)
  • GET /api/apps/{id}/contents/{path*} - Read app files

Restrictions:

  • Read-Only: Tokens cannot be used to modify the app or its data
  • No Write Operations: PUT, POST, PATCH, DELETE are not allowed
  • Whitelist Enforcement: API proxy calls are subject to the app's data access whitelist
  • App-Specific: Token only works for the specified appId

Revoking Tokens

Tokens are revoked through the general Token API.

Example: Revoke a Token

DELETE /api/tokens/token-uuid-1

Response:

Returns 204 No Content on success.

Effect:

  • Token immediately becomes invalid
  • Any in-progress requests using the token may fail
  • The token string can no longer be used for authentication

Common Token Workflows

// 1. Create a token for the app
const token = await POST('/api/tokens', {
type: 'app-view',
appId: 'analytics:sales-dashboard',
name: 'Public Dashboard - Q1 2024',
expiresAt: '2024-04-01T00:00:00.000Z'
});

// 2. Construct the shareable URL
const dashboardURL = `https://your-informer.com/api/apps/${appId}/view?token=${token.token}`;

console.log('Share this URL:', dashboardURL);

List All Tokens for an App

const response = await GET('/api/apps/analytics:sales-dashboard/tokens');

console.log(`Found ${response.tokens.length} tokens:`);
for (const token of response.tokens) {
console.log(`- ${token.name || 'Unnamed'} (expires: ${token.expiresAt || 'never'})`);
}

Revoke Expired Tokens

// Get all tokens for the app
const response = await GET('/api/apps/analytics:sales-dashboard/tokens');

const now = new Date();

// Find expired tokens
const expiredTokens = response.tokens.filter(t =>
t.expiresAt && new Date(t.expiresAt) < now
);

// Revoke them
for (const token of expiredTokens) {
await DELETE(`/api/tokens/${token.id}`);
console.log(`Revoked expired token: ${token.name || token.id}`);
}
// Create a token that expires in 7 days
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + 7);

const token = await POST('/api/tokens', {
type: 'app-view',
appId: 'analytics:sales-dashboard',
name: 'Demo Link - Week of Feb 13',
expiresAt: expiresAt.toISOString()
});

console.log('Demo link:', `${baseURL}/api/apps/${appId}/view?token=${token.token}`);
console.log('Expires:', expiresAt.toLocaleDateString());

Rotate Tokens

// Get existing token
const response = await GET('/api/apps/analytics:sales-dashboard/tokens');
const oldToken = response.tokens.find(t => t.name === 'Public Dashboard');

// Create new token with same settings
const newToken = await POST('/api/tokens', {
type: 'app-view',
appId: 'analytics:sales-dashboard',
name: 'Public Dashboard',
expiresAt: oldToken.expiresAt
});

// Revoke old token
if (oldToken) {
await DELETE(`/api/tokens/${oldToken.id}`);
}

console.log('New token:', newToken.token);

Security Considerations

Token Visibility

  • Tokens are visible to anyone who can read the app
  • The token string itself provides access, so treat it as a password
  • Anyone with the token can access the app (until expiration or revocation)

Best Practices

  1. Use Expiration: Always set expiresAt for public tokens
  2. Name Tokens: Use descriptive names to track usage
  3. Rotate Regularly: Change tokens periodically for public apps
  4. Monitor Usage: Check the tokens list regularly and revoke unused ones
  5. Limit Scope: Create separate tokens for different use cases

Token Validation

The app-view token driver enforces:

  • appId must be present
  • readOnly is always set to true
  • Token is only valid for the specified app

API Proxy Whitelist

Even with a valid token, API calls through /api/apps/{id}/view/api/ are subject to the app's data access whitelist. This prevents malicious apps from accessing arbitrary data.


Token Lifecycle

  1. Creation: Token is created via POST /api/tokens
  2. Active: Token can be used to access the app
  3. Expiration: If expiresAt is set, token becomes invalid at that time
  4. Revocation: Token is deleted via DELETE /api/tokens/{id}
  5. Cleanup: Expired tokens should be periodically cleaned up
  • POST /api/tokens - Create tokens
  • GET /api/tokens/{id} - Get token details
  • DELETE /api/tokens/{id} - Revoke tokens
  • GET /api/tokens - List all tokens (admin)