Authentication
The Hubrix API uses short-lived JWT access tokens (15 minutes) carried as Authorization: Bearer <token>. Tokens are obtained via one of three flows: email/password, Google SSO, or Microsoft SSO.
Email / password
Call POST /auth/login with your credentials. On success you receive:
{
"access_token": "eyJhbGc...", // JWT, valid 15 minutes
"refresh_token": "abc123...", // 32-byte random, valid 30 days
"user": { "id": "uuid", "email": "you@example.com", "role": "owner" }
}If MFA is enabled, include totp_code in the same request body. An omitted TOTP code returns 401 mfa_required.
# cURL
curl -X POST https://api.hubrix.ai/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "YOUR_PASSWORD", "totp_code": "123456"}'Token refresh
Before the access token expires, call POST /auth/refresh. Each call rotates the refresh token — the previous one is immediately invalidated. A race between two concurrent refreshes will cause one to fail with 401 token_invalid; the client should retry with the newer token.
curl -X POST https://api.hubrix.ai/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "abc123..."}'Google SSO
- Redirect the user to
GET /auth/google/start. This stores a CSRF nonce in Redis (300s TTL) and returns a redirect to the Google consent screen with scopesopenid email. - Google redirects to
GET /auth/google/callback?code=…&state=…. The API validates the state, exchanges the code, and either logs in an existing user or creates a new one (if a valid invite exists). - The callback sets
hubrix_tokenas an httpOnly cookie and redirects to/app. For programmatic use, callGET /auth/google/start?redirect_uri=YOUR_URI(when implemented).
Microsoft SSO
Same flow via /auth/microsoft/start and /auth/microsoft/callback. Uses MSAL with User.Read openid scopes and microsoft_tenant_id=common for multi-tenant accounts.
MFA (TOTP)
Users enable TOTP from POST /me/mfa/setup (returns QR code URI) then confirm with POST /me/mfa/verify. The secret is Fernet-encrypted at rest. Once enabled, every login requires a TOTP code. Recovery codes (8 generated at setup, stored as hashed values) can substitute for a TOTP code.
Step-up authentication
Sensitive operations (disabling MFA, changing email, requesting account deletion) require re-authentication within the last 5 minutes. These endpoints return 403 with type: step_up_required if the session is older. Call POST /auth/step-up with your password (and TOTP if enabled) to refresh the step-up claim.
API keys
Create API keys from Settings → API Keys. Keys have the format hbx_…. The plaintext key is shown exactly once at creation — only the SHA-256 hash is stored. Keys authenticate as the company without user context; role is effectively admin.
curl https://api.hubrix.ai/v1/me/profile \ -H "Authorization: Bearer hbx_your_api_key_here"
Personal API tokens (user-scoped, with fine-grained permissions) are planned for a future release. Current API keys authenticate at company level.
JWT structure
Access tokens are HS256 JWTs. Decode the payload to inspect claims — do not rely on them for authorization (the server validates the signature on every request):
{
"sub": "user-uuid", // user_id
"cid": "company-uuid", // company_id
"role": "owner", // owner | admin | member
"exp": 1746376800 // Unix epoch — 15 min from issue time
}The SECRET_KEY used to sign tokens is never exposed. Do not attempt to verify tokens client-side — treat them as opaque.
Logout
Call POST /auth/logout to revoke the current refresh token server-side and clear the httpOnly session cookie. All other active sessions remain valid until their access tokens expire. To revoke all sessions, call POST /me/sessions/revoke-all.