Skip to main content

Authentication

The Heimdall API uses Bearer token authentication for secure access to protected endpoints.

Authentication Methods

Bearer Token Authentication

All authenticated requests must include an Authorization header with a Bearer token:

Authorization: Bearer YOUR_API_TOKEN

Obtaining an API Token

API tokens can be created in the Backend Console by users with the appropriate permissions, or by system administrators.

Token Roles

API keys are assigned roles that determine their permissions:

RoleAccess LevelDescription
API Read OnlyRead-onlyCan view GPS data, users, roles, and public endpoints
API Full AccessFull accessCan create, update, delete all resources
Custom RolesConfigurableCustom roles with specific permissions

See the Authentication System for details on roles and permissions.

Making Authenticated Requests

Using cURL

curl -H "Authorization: Bearer YOUR_TOKEN" \
https://api.elcto.com/v1/gps/current

Using JavaScript (Fetch)

const response = await fetch('https://api.elcto.com/v1/gps/current', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}
});

const data = await response.json();

Using Python (Requests)

import requests

headers = {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
}

response = requests.get(
'https://api.elcto.com/v1/gps/current',
headers=headers
)

data = response.json()

Validate Your Token

You can validate your token using the validation endpoint:

POST /v1/auth/validate
Content-Type: application/json

{
"token": "YOUR_TOKEN"
}

Response:

{
"valid": true,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"role": "ADMIN"
}
}
Not Implemented

This endpoint is a placeholder and currently returns 501 Not Implemented. Use the GraphQL me query to inspect the authenticated context instead.

GraphQL Authentication

The GraphQL endpoint (/v1/gql) requires authentication for all queries and mutations. Include the Authorization header with your Bearer token:

curl -X POST https://api.elcto.com/v1/gql \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "{ me { userId apiKeyId roles permissions isSuperAdmin } }"}'

Response:

{
"data": {
"me": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"apiKeyId": null,
"roles": ["Admin"],
"permissions": ["*:*"],
"isSuperAdmin": true
}
}
}

Using GraphiQL (Development Only)

The GraphiQL IDE (/v1/graphiql) is only available in development environments. To use it:

  1. Ensure APP_ENV is not set to production
  2. Open http://localhost:3000/v1/graphiql
  3. Click "HTTP HEADERS" at the bottom left
  4. Add your authorization header:
{
"Authorization": "Bearer YOUR_TOKEN"
}
  1. Execute your queries
warning

GraphiQL is disabled in production environments for security. Use the /v1/gql endpoint directly with your HTTP client in production.

WebSocket Authentication

WebSocket connections do not require authentication at the connection level. Subscribe to channels after connecting:

const ws = new WebSocket('wss://api.elcto.com/v1/ws');

ws.onopen = () => {
// Subscribe to GPS updates
ws.send(JSON.stringify({
type: 'Subscribe',
channel: 'gps'
}));
};

Authentication Errors

401 Unauthorized

Returned when no authentication token is provided or the token is invalid:

{
"error": "Unauthorized",
"message": "Invalid or missing authentication token"
}

403 Forbidden

Returned when the authenticated user lacks sufficient permissions:

{
"error": "Forbidden",
"message": "Insufficient permissions for this operation"
}

Security Best Practices

Security Tips
  1. Never expose your API token in client-side code or public repositories
  2. Use HTTPS in production to encrypt token transmission
  3. Rotate tokens regularly for enhanced security
  4. Use environment variables to store tokens
  5. Implement token expiration policies in your applications

Rate Limiting

Authenticated requests are subject to rate limiting:

  • Default: 100 requests per minute per token
  • Admin endpoints: 30 requests per 60 seconds

Rate limiting is applied per-route via middleware (keyed by client IP). No X-RateLimit-* headers are emitted. When a limit is exceeded the API responds with 400 Bad Request and a message describing the limit (e.g. Rate limit exceeded. Max 30 requests per 60 seconds).

Next Steps