Authentication & Authorization
Every request to the Alien Intelligence platform is authenticated and authorized before it reaches any data. This page explains how an integrator authenticates a call, how requests are scoped to an organization, how service accounts and their tokens work, and how organization roles gate access.
For the broader picture — network security, per-tenant isolation, and the cluster-side authentication layers — see the Security Model.
Two Token Types
The platform backend runs two independent authentication paths, one per credential kind. The credential kind determines which header you send, and the wrong pairing fails — so it is worth getting right up front.
| Credential | Issued by | Header | Used by |
|---|---|---|---|
| OAuth access token | The OIDC identity provider (e.g. Authentik) | x-oauth-access-token: <jwt> | Interactive user sessions — web apps acting on behalf of a signed-in human |
| API token | The platform, on the Keys / service-account flow | Authorization: Bearer oat_… | Server-to-server and service-account access — scripts, SDKs, CI, integrations |
OAuth access token → x-oauth-access-token
When a request originates from a signed-in human, the calling application forwards the OAuth access token it received from the identity provider (e.g. Authentik) in the x-oauth-access-token header. The platform's OAuth guard validates this JWT against the provider's signing keys, resolves it to a platform user, and auto-provisions the user on first login.
curl https://app.alien.club/users/me \
-H "x-oauth-access-token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
This is the right header for interactive, on-behalf-of-a-user calls. The JWT is short-lived; the front end refreshes it transparently, so application code rarely handles it by hand.
API token → Authorization: Bearer oat_…
For server-to-server access and service accounts, use a platform API token. API tokens are opaque strings prefixed with oat_ and are sent as a standard Bearer credential:
curl https://app.alien.club/datasets \
-H "Authorization: Bearer oat_YOUR_API_TOKEN"
API tokens are validated by the platform's access-tokens guard (the raw value is never stored — only a hash is kept for comparison). They are the credential of choice for non-interactive integrations: a token can be long-lived, scoped, and revoked independently of any human session.
The two guards are independent. An oat_ API token sent in x-oauth-access-token reaches the JWT guard, which cannot decode the non-JWT string and returns 401. Likewise, a JWT sent as Authorization: Bearer … reaches the API-token guard, which will not find it in the token store. Always send an oat_ token as Authorization: Bearer … and a JWT as x-oauth-access-token.
Organization Scoping — x-organization-id
A user can belong to more than one organization, and almost everything on the platform — datasets, workflows, clusters — is scoped to a single organization (the tenant). Two mechanisms decide which organization a given request runs against.
Per-request scoping with the header
Send x-organization-id: <id> to pin a request to a specific organization. The backend validates membership: it checks that the authenticated user is a member of that organization. If they are not, the request is rejected with 401 You are not a member of this organization.. A malformed (non-positive-integer) value returns 400.
curl https://app.alien.club/datasets \
-H "Authorization: Bearer oat_YOUR_API_TOKEN" \
-H "x-organization-id: 42"
This header is the deterministic, stateless way to scope a call — recommended for any integration that operates across more than one organization, because the active organization is then explicit per request rather than carried as session state.
Fallback when the header is absent
When x-organization-id is not present, the backend falls back, in order:
- The
current-org-idrequest cookie, if present (same membership validation as the header). - The user's stored current organization (
currentOrganizationId) — re-validated for membership; if that membership has since been revoked, the platform gracefully drops to the user's first organization (by creation order) instead of throwing. - The user's first organization (oldest membership) if no current organization is set.
If the user belongs to no organization at all, the request runs with no organization context. This fallback chain is what lets simple, single-organization integrations omit the header entirely and still work.
Switching the persistent current organization
To change which organization a user's session defaults to (the value used by the fallback above), call:
POST /organizations/{id}/switch
This updates the user's stored current organization. Use the x-organization-id header for one-off per-request scoping, and /organizations/{id}/switch to persistently move the session's default tenant.
Service Accounts & Token Scopes
API tokens are minted for service accounts, not for human users directly. The platform models this with a userType on every user:
userType | What it is | Can mint API tokens? |
|---|---|---|
human | A real person who signs in interactively via the IdP | No |
client-managed | A service account managed by an organization for programmatic / on-behalf-of-clients access | Yes |
Only client-managed users can have API tokens issued for them. The token-management endpoints (issue, list, revoke) explicitly reject human targets — a human authenticates interactively through the IdP and never holds a static oat_ token.
Token scopes
When you mint a token for a service account, you choose a scope, which expands to a fixed set of abilities:
| Scope | Grants | Use it for |
|---|---|---|
api-key | Read abilities across resources (datasets, entries, workflows, clusters, AI models, …) and execution of agents/workflows the account can already read | Read-only and run-only integrations — querying the catalog, running an existing agent |
api-secret | Everything in api-key, plus write abilities (create/update datasets, upload entries, create and modify workflows, manage tokens, …) | Provisioning integrations that create or modify resources |
The token-mint endpoint accepts only api-key or api-secret (any other value is rejected). Pick the least-privileged scope that covers your integration: a read-and-run integration should use api-key; reserve api-secret for integrations that need to write — create datasets, upload entries, or build/modify workflows.
The raw token value (oat_…) is returned only in the response to the create call and is never retrievable again. Store it securely at creation time. Listing or inspecting a token afterwards returns its metadata (name, abilities, last-used, expiry) but never the secret. A lost token cannot be recovered — revoke it and mint a new one.
Who can mint a token
Token management is an organization-admin operation on Enterprise organizations: the caller must hold write permission and an admin-or-above role in the organization, and the target must be a client-managed service account. See the Users & Organizations endpoints in the Platform API reference for the full lifecycle (POST/GET/DELETE under /organizations/{id}/users/{userId}/tokens).
Roles & the Authorization Model
Authentication answers who you are; authorization answers what you may do. The platform's authorization is organized around organization roles. Every membership carries a role, surfaced on the user object returned by /users/me as roles[].slug:
| Role slug | Position | Typical capabilities |
|---|---|---|
org-client | lowest | Run agents/workflows the organization exposes to its clients |
org-member | Read organization resources; run workflows | |
org-admin | Manage organization users, issue and revoke service-account tokens | |
org-owner | highest | Full organization administration |
Roles are hierarchical — a higher role satisfies any check that requires a lower one. Authorization is enforced by a policy layer in the backend: every controller action checks the caller's role (and, for token-issued requests, the token's abilities) before any database query or downstream call. For example, running an agent requires read access to it plus at least the org-client role (or the agent being public); managing another user's tokens requires org-admin or above on an Enterprise organization.
Two effects compose on every authenticated request:
- The token's abilities cap what the request can do (an
api-key-scoped token cannot perform writes, regardless of the underlying account's role). - The organization role caps what the account may do within the active organization.
A request is allowed only when both permit it — the effective permission is the intersection.
Inspecting effective permissions
Two endpoints let an integrator discover its own authorization context rather than guessing:
GET /users/me— the authenticated identity, including organization memberships androles[].slug.GET /users/me/abilities— the caller's effective grant abilities (and whether any bypass scope applies).
Call these to confirm the active organization and the abilities a credential actually carries before relying on them.
Authenticating Your Requests
A complete request carries an authentication header and, optionally, an organization header. Both credential styles are shown below.
curl https://app.alien.club/datasets \
-H "x-oauth-access-token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "x-organization-id: 42"
curl https://app.alien.club/datasets \
-H "Authorization: Bearer oat_YOUR_API_TOKEN" \
-H "x-organization-id: 42"
curl -X POST https://app.alien.club/agent/123/responses \
-H "Authorization: Bearer oat_YOUR_API_TOKEN" \
-H "x-organization-id: 42" \
-H "Content-Type: application/json" \
-d '{"input": "Summarize the latest filing.", "stream": true}'
Drop x-organization-id to let the platform fall back to your current organization. Use the OAuth header for on-behalf-of-a-user calls and the Bearer oat_ header for service-account calls — never mix them.
Next Steps
- Security Model — Network security, per-tenant isolation, and the full set of authentication layers
- Platform API Overview — Base URLs, conventions, and the endpoint reference (Users, Organizations, Access Tokens)
- Data API Overview — How authentication context flows through to the per-tenant data cluster
- Data Sovereignty — Why organization scoping is enforced at every layer