Authentication Overview
EUnifyer uses bearer-token authentication for all external API access. All tokens resolve to a single organization and carry a bounded set of scopes.
Three auth flows
| Flow | Token format | Best for |
|---|---|---|
| OAuth 2.0 auth code + PKCE | RS256 JWT from Keycloak | Apps acting on behalf of a real user |
| OAuth 2.0 client credentials | RS256 JWT from Keycloak | Server-to-server automation, MSP, reseller |
| Personal Access Token (PAT) | eu_sk_… opaque token | Scripts, CLI tools, legacy integrations |
All three token types are accepted on all external API endpoints using the same Authorization: Bearer <token> header.
User-delegated vs machine access
Some APIs — Drive and Sites — operate on per-user data. They require the request to resolve to an acting user. The three flows handle this differently:
| Flow | Acts as a user? |
|---|---|
| OAuth auth code + PKCE | Yes — the authenticated end user |
| Service account (client credentials) | No — pure machine identity. Rejected by Drive and Sites (which require an acting user). Partner/admin APIs are fine. |
PAT bound to a user_id | Yes — acts as the named user |
| PAT not bound to a user | No — rejected by Drive and Sites |
The Partner API accepts pure machine identity (no acting user needed).
How tokens are validated
- The
Authorization: Bearerheader is extracted. - EUnifyer identifies the token type:
eu_sk_…prefix → PAT lookup (hashed comparison)- RS256 JWT → Keycloak JWKS validation
- HS256 JWT → first-party session (UI dogfooding)
- For PATs: expiry, revocation, and IP allowlist checks run.
- For Keycloak JWTs:
azp(client ID) is matched to a service principal;subis optionally matched to a user. - The result is an
ApiTokenContext:principal_type—pat,keycloak_jwt, oruser_jwtorganization_id— always presentscopes— intersection of the token’s scopes and the service principal / user’s allowed scopesactor_user_id— the acting user, if any
Token storage and security
- PAT secrets are shown once at creation and never again. Store them securely (a secrets manager, not a
.envfile in git). - PATs are stored hashed at rest (SHA-256). EUnifyer cannot recover a lost PAT — rotate instead.
- Keycloak JWTs are short-lived (15 minutes by default) and refreshed using a refresh token or client credentials re-grant.
- All credential events (create, rotate, revoke, use) are recorded in the audit log.
Common header
Authorization: Bearer <your-token>This is the only supported way to pass credentials to external API endpoints. Cookie-based auth is not supported for external integrations.
Admin UI locations
| What | Where |
|---|---|
| Create service principals and API tokens | Admin → API Access (/admin/api-access) |
| Manage webhook subscriptions | Admin → Webhooks (/admin/webhooks) |
| Register OAuth apps for MSP/reseller | Back-office → Service Accounts (/back-office) |
| Personal OAuth app connections | User account settings |