Auth and API Keys
Authentication in Vega works differently depending on the environment: a simple built-in system for local development, and AWS Cognito for production. Both are implemented as adapters behind the IdentityPort interface.
How authentication works
Every protected API endpoint resolves a CurrentUser via the current_user FastAPI dependency in api/dependencies/current_user.py. When a request arrives:
- The
Authorization: Bearer <token>header is extracted IdentityAdapter.validate_token(token)is called — eitherLocalIdentityAdapterorCognitoIdentityAdapterdepending onVEGA_AUTH_PROVIDER- The adapter returns a
CurrentUser(user_id, groups, role)object, or raises401if the token is missing or invalid
Role is derived from group membership: root, operator, or customer. Some endpoints additionally check CurrentUser.role and return 403 if the user lacks the required access level.
Auth configuration endpoint
GET /api/auth/config is an unauthenticated endpoint that returns the active authentication provider and related configuration. The frontend calls this on startup to determine which login flow to use.
{
"auth_provider": "cognito",
"cognito_user_pool_id": "us-west-1_xxxxx",
"cognito_app_client_id": "xxxxx"
}
When auth_provider is "custom", the Cognito fields are null. The frontend uses the returned values to call configureCognitoAuth() at runtime, so Cognito pool IDs don't need to be baked into the frontend build.
Key files:
- app/api/routers/auth.py — GET /auth/config route
- app/adapters/identity/local/ — LocalIdentityAdapter
- app/adapters/identity/cognito/ — CognitoIdentityAdapter
- app/api/dependencies/current_user.py — Bearer auth → CurrentUser dependency
Local (custom) auth
When VEGA_AUTH_PROVIDER=custom (the default for local development), the backend uses LocalIdentityAdapter:
- Login:
POST /api/auth/loginaccepts an email and password. The default credentials aredebug@example.com/vega-debug-password. - Tokens: The adapter issues
local:{email}bearer tokens. No cryptographic signing — these are purely for local development. - Roles: The email prefix determines the role (
root@...→ root,operator@...→ operator, all others → customer).
curl -s http://localhost:8000/api/auth/login \
-H 'content-type: application/json' \
-d '{"email":"debug@example.com","password":"vega-debug-password"}'
Custom auth is not for production
The custom auth system has no real user management, no password hashing, and no MFA. It exists purely to make local development convenient. Always use Cognito in production.
Production (Cognito) auth
When VEGA_AUTH_PROVIDER=cognito, the backend uses CognitoIdentityAdapter:
- The user enters credentials in the frontend.
- The frontend calls Cognito directly using SRP (Secure Remote Password) protocol.
- Cognito returns a JWT access token and a refresh token.
- The frontend sends
Authorization: Bearer <access_token>on every subsequent API request. CognitoIdentityAdapterfetches Cognito's JWKS endpoint and validates the JWT signature, expiry, and claims.- User groups are extracted from the JWT (
cognito:groupsclaim) and mapped to Vega roles.
The backend never sees the user's password — that's handled entirely by Cognito.
Key files:
- app/adapters/identity/cognito/ — JWT validation via JWKS
- infra/terraform/modules/cognito/main.tf — Terraform for the user pool
- frontend/src/auth/cognito.ts — frontend Cognito login flow
Required configuration:
VEGA_AUTH_PROVIDER=cognito
VEGA_COGNITO_REGION=us-west-1
VEGA_COGNITO_USER_POOL_ID=us-west-1_xxxxx
VEGA_COGNITO_APP_CLIENT_ID=xxxxx
User management (Cognito)
New user invitations are managed via POST /api/users/invitations (operator/root only). This calls CognitoIdentityAdapter.invite_user(), which creates a Cognito user and sends an invitation email.
In local mode with LocalIdentityAdapter, user management is not supported — only the debug user exists.
API keys
API keys provide programmatic access for automation, CI/CD pipelines, or external tooling.
Users create API keys from the dashboard (/api-keys). An API key works exactly like a Bearer token:
curl -s https://api.vega.example.com/api/projects \
-H "Authorization: Bearer vk_xxxxxxxxxxxxxxxx"
API keys are stored in the api_keys generic record store (not the identity adapter — they are resolved before the identity layer). The key value (prefixed with vk_) is returned once at creation time and cannot be retrieved again.
Routes:
| Method | Path | Description |
|---|---|---|
GET |
/api/api-keys |
List all API keys for current user |
POST |
/api/api-keys |
Create a new key (returns value once) |
POST |
/api/api-keys/:key_id/revoke |
Revoke and delete a key |
Debugging auth failures
401 invalid_token from /api/auth/me
The token is expired or incorrectly formed. Try logging in again to get a fresh token.
401 on every request in AWS
- Confirm
VEGA_AUTH_PROVIDER=cognitois set in the API task definition. - Confirm the three Cognito env vars (
REGION,USER_POOL_ID,APP_CLIENT_ID) match the deployed Cognito pool. - The Cognito JWKS endpoint must be reachable from the API container — check that outbound HTTPS is allowed from the API security group.
403 forbidden
The user is authenticated but lacks the required role. Check the user's Cognito group membership in the AWS Cognito console. Groups should be root, operator, or user.
Login works locally but not in AWS
Confirm VEGA_AUTH_PROVIDER is not custom in the AWS task definition. Custom auth only works locally.