Skip to content

Authentication

Alga uses session-based authentication with HTTP-only cookies, CSRF protection, and role-based access control.

Authentication Models

Alga supports three authentication models depending on the caller:

ModelMechanismUse Case
Session cookiealga_session cookie + CSRF tokenBrowser / web UI
Personal Access TokenAuthorization: Bearer alga_pat_...Automation, scripting
Agent tokenAuthorization: Bearer <agent-token>AI agent API and SSE

Session Authentication

The web UI authenticates via session cookies. State-changing methods (POST, PUT, PATCH, DELETE) require a CSRF token in the X-CSRF-Token header that matches the alga_csrf cookie (double-submit cookie pattern).

Personal Access Tokens (PAT)

PATs use Bearer alga_pat_... and bypass CSRF validation (intended for machine-to-machine use). A PAT's effective permissions are the intersection of the PAT's granted scopes and the owning user's role permissions — a PAT can never grant access beyond what the user already has.

Agent Tokens

Agent tokens use Bearer <agent-token> with capability checks. Agent routes are protected by agentBearerMiddleware with per-agent-token rate limiting and do not rely on CSRF cookies.

Login

Authenticate via the API or the web UI:

sh
curl -c cookies.txt -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@alga.local", "password": "your-password"}'

The response sets two cookies:

  • alga_session — HTTP-only session cookie
  • alga_csrf — CSRF token for state-changing requests

Google Sign-In

Alga supports Google Sign-In via standard OAuth 2.0. When configured, users can authenticate with their Google account instead of email/password.

Configuration

Set the following environment variables (or configure at runtime via System Configuration API):

VariableRequiredDescription
GOOGLE_CLIENT_IDYesGoogle OAuth client ID
GOOGLE_CLIENT_SECRETYesGoogle OAuth client secret
GOOGLE_OAUTH_REDIRECT_URLNoOverride callback URL (auto-detected from request headers if not set)

When GOOGLE_CLIENT_ID is set, the login page displays a "Sign in with Google" button.

API Endpoints

MethodPathAuthDescription
GET/api/v1/auth/google/enabledNoneCheck if Google OAuth is enabled
GET/api/v1/auth/googleNoneRedirect to Google OAuth authorization
GET/api/v1/auth/google/callbackNoneGoogle OAuth callback

Flow

  1. User clicks "Sign in with Google" on the login page
  2. Browser redirects to Google's authorization page
  3. User authorizes the application
  4. Google redirects back to Alga's callback URL
  5. Alga finds an existing account linked by Google ID or matching a verified email and establishes a session. Accounts are provisioned via setup or invite — sign-in never creates one.

Slack Sign-In

Users can authenticate by linking their Slack identity, configured from Settings > Integrations per user (/api/v1/users/me/slack/*). A workspace-level Slack app is a prerequisite. The endpoints are /api/v1/auth/slack/enabled, /api/v1/auth/slack, and /api/v1/auth/slack/callback.

OIDC SSO

Alga supports generic OIDC identity providers (e.g. Okta, Keycloak, Google, Auth0) using the Authorization Code flow with PKCE. Login state (including the PKCE verifier and provider ID) is stored in Valkey as a single-use record with a 10-minute TTL, preventing replay of authorization codes.

Configure from System > Authentication or via the System Configuration API. See OIDC SSO for setup.

Password Recovery

Alga provides a self-service password reset flow via email.

Prerequisites

  • SMTP_HOST must be configured (see Email Configuration)
  • SECRET_PEPPER must be set for HMAC token hashing

API Endpoints

MethodPathAuthDescription
POST/api/v1/auth/forgot-passwordNoneRequest password reset email
POST/api/v1/auth/reset-passwordNoneReset password with token

Flow

  1. User submits their email to /api/v1/auth/forgot-password
  2. If the email exists, Alga sends a reset link with a time-limited token (valid 1 hour)
  3. The response is always the same message regardless of whether the email exists — this prevents email enumeration
  4. User clicks the link, which opens /reset-password?token=... in the frontend
  5. Frontend submits the token and new password to /api/v1/auth/reset-password
  6. Alga validates the token (not expired, not used), checks the password against the password policy, and updates the password

Reset tokens are hashed before storage and expire after use.

Request Password Reset

sh
curl -X POST http://localhost:8080/api/v1/auth/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Reset Password

sh
curl -X POST http://localhost:8080/api/v1/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{"token": "reset-token-from-email", "new_password": "NewP@ssw0rd!"}'

Account Lockout

Failed login attempts are tracked per account (failed_login_attempts). After the threshold is reached, the account is locked (locked_until) for a cooldown period. Successful authentication resets the counter.

Roles & Permissions

Alga has three built-in roles and 52 permissions. Every authenticated request is checked against the route's required permission using OR semantics — if a route accepts multiple permissions, having any one of them grants access.

Admin

Full access to all features and every permission, including destructive and administrative scopes (deletes, system config, user/token/OIDC management, credential management).

Operator

Day-to-day operations: read/write for operational domains (alerts, knowledge, memories, incidents, triage, post-mortems, playbooks, heartbeats, status pages), incident command, notification management, and credential management. No system config, no deletes (except knowledge/memories), no token/OIDC management, no admin:access.

Viewer

Read-only access across all operational resources.

Permission Matrix

PermissionAdminOperatorViewer
alerts:read / alerts:writeYesYesRead only
alerts:deleteYes
knowledge:read / knowledge:writeYesYesRead only
knowledge:deleteYes
memories:read / memories:writeYesYesRead only
memories:deleteYes
routes:readYesYesYes
routes:writeYes
integrations:readYesYesYes
integrations:writeYes
integrations:testYesYes
users:manageYesYes
tokens:manageYes
dashboard:readYesYesYes
channels:readYesYesYes
audit:readYesYes
notifications:read / notifications:writeYesYesRead only
system:read / system:writeYes
triage:read / triage:writeYesYesRead only
triage:overrideYesYes
incidents:read / incidents:writeYesYesRead only
incidents:commandYesYes
incidents:deleteYes
services:readYesYesYes
services:writeYes
oncall:readYesYesYes
oncall:writeYes
escalation:readYesYesYes
escalation:writeYes
postmortems:read / postmortems:writeYesYesRead only
postmortems:deleteYes
playbooks:read / playbooks:writeYesYesRead only
playbooks:deleteYes
heartbeats:read / heartbeats:writeYesYesRead only
heartbeats:deleteYes
statuspages:read / statuspages:writeYesYesRead only
statuspages:deleteYes
oidc:manageYes
credentials:readYesYes
credentials:manageYesYes
admin:accessYes

Password Policy

Alga enforces the following password requirements:

  • Minimum 8 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • At least one special character

Passwords are hashed with Argon2id (OWASP baseline: 64 MiB memory, 3 iterations, parallelism 2, 16-byte salt, 32-byte key) with a server-side HMAC pepper pre-hash (SECRET_PEPPER).

Session Management

  • Sessions expire after SESSION_EXPIRY_HOURS (default: 24 hours, max: 720) and SESSION_MAX_LIFETIME (default 12h absolute cap, ASVS V3.2/V3.3)
  • Refresh tokens enable seamless session renewal
  • Refresh tokens rotate on every use; the previous token hash is recorded (prev_refresh_token_hashes) within a session family (family_id)
  • Reuse of a previously-rotated refresh token — or presenting a rotated-out session cookie — is detected as replay and revokes all of the user's sessions (session_replay_detected / refresh_token_reuse_detected audit reasons)
  • API clients can drive refresh-token rotation via the optional HttpOnly alga_rt cookie issued alongside alga_session; browsers never need to present it
  • When SECURE_COOKIES=true, cookies are only sent over HTTPS
  • Cookie-side session IDs and refresh tokens are HMAC-SHA-256 hashed before persistence
  • Valkey is preferred at runtime; every session write goes to both Postgres and Valkey when available so a restart does not invalidate sessions; reads/deletes check Valkey first and fall back to Postgres automatically
  • See Session Management — Self-Service API for the user-facing routes: GET /api/v1/auth/sessions (list own, current:true exactly one, HMAC digest IDs, MRU-sorted, expired filtered), DELETE /api/v1/auth/sessions/{id} (revoke one; current → 400 "sign out instead", foreign/missing → 404 anti-enumeration, PAT → 400), and DELETE /api/v1/auth/sessions (revoke all others, returns {revoked:n}). All three require a session cookie and CSRF, and are audited as session_revoked / sessions_revoked_all. The Settings → Security tab (/settings/security) renders the list with device/IP, last-used time, and Revoke actions.

API Tokens

Webhook Tokens

Bearer tokens for alert ingestion endpoints. Tokens are shown exactly once on creation and stored as HMAC-SHA-256 hashes with a non-secret lookup_prefix for efficient lookup. Send them via the Authorization header — the ?token= query parameter is denied by default (WEBHOOK_ALLOW_QUERY_TOKEN=true is a temporary escape hatch slated for removal; credentials in URLs leak into proxy/access logs, Referer headers and browser history):

sh
curl -X POST http://localhost:8080/webhooks/alerts \
  -H "Authorization: Bearer alga_..." \
  -H "Content-Type: application/json" \
  -d '{"alerts": [...]}'

Agent Tokens

Bearer tokens for AI agent API and SSE. The SSE endpoint also accepts Authorization headers (fetch-based SSE); a legacy ?token= query fallback is denied by default (AGENT_SSE_ALLOW_QUERY_TOKEN=true escape hatch only):

sh
# SSE connection
curl -N http://localhost:8080/api/v1/agent/events \
  -H "Authorization: Bearer alga_agent_..."

# REST API
curl http://localhost:8080/api/v1/agent/alerts \
  -H "Authorization: Bearer alga_agent_..."

Personal Access Tokens

Personal Access Tokens (PATs) allow users to authenticate API requests for automation and scripting without using session cookies:

  • Token format: alga_pat_...
  • CSRF bypass: PATs are intended for machine-to-machine communication and bypass CSRF validation
  • Permission model: A PAT's permissions intersect with the owning user's role — a PAT cannot grant access beyond what the user already has
  • Management: Create, list, and revoke PATs from the user profile settings

See Personal Access Tokens for details.

Cryptographic Primitives

PrimitiveAlgorithmConfiguration
Password hashingArgon2id64 MiB memory, time 3, parallelism 2, 16-byte salt, 32-byte key
Envelope encryptionAES-256-GCMENCRYPTION_KEYS (comma-separated kid:base64-key pairs, supports key rotation via kid)
Token hashingHMAC-SHA-256SECRET_PEPPER as the HMAC key
Secret comparisonConstant-timecrypto/subtle for all secret, token, and signature checks

Security Features

  • CSRF Protection — Double-submit cookie pattern (alga_csrf cookie + X-CSRF-Token header) for state-changing methods
  • Secure Cookies — HttpOnly, Secure (HTTPS), SameSite=Strict
  • Fail-Closed Startup — Refuses to start without ENCRYPTION_KEYS (or ENCRYPTION_KEY) AND SECRET_PEPPER in every environment, not only production
  • HSTSStrict-Transport-Security emitted on all HTTPS responses regardless of the SecureCookies flag
  • Encryption at Rest — AES-256-GCM envelope encryption for integration secrets and auth secrets (Google/OIDC client secrets in system config)
  • Constant-Time Comparison — All secret checks use crypto/subtle
  • Rate Limiting — Per-IP fixed-window rate limiting (default 20/min, RATE_LIMIT_GENERAL_PER_MINUTE) for public endpoints; per-agent-token limiting (default 120/min, RATE_LIMIT_AGENT_PER_MINUTE) for agent endpoints — both backends enforce identical semantics; login attempts limited to 5 per 15 minutes
  • Account Lockout — Failed login tracking with time-based lockout
  • Audit Logging — Fire-and-forget audit trail for every create, update, delete, command, and state transition; must not block request success (bursts may drop events under saturation — at-most-once delivery). Rows carry the middleware request ID so HTTP-triggered actions correlate with structured logs. Admins and operators can review the trail via GET /api/v1/audit-events (audit:read permission; paginated, filterable by event, entity_type, entity_id) — read-only, no API to mutate or delete audit rows. The account_unlocked and suspicious_activity event types are reserved for future features that do not exist yet.
  • Idempotency-Key — Optional replay protection for mutating requests (requires Valkey); first request executes, subsequent requests with the same key return the cached response
  • Bearer Token Storage — Tokens stored as HMAC-SHA-256 hashes with non-secret lookup_prefix for indexed lookup; never stored in plaintext
  • Webhook Tokens — Shown exactly once on creation; cannot be retrieved afterward
  • OIDC Security — Authorization Code + PKCE flow; Valkey-backed single-use login state with 10-minute TTL prevents authorization code replay
  • Password Reset — Token-based, hashed before storage, time-limited expiry
  • Session Rotation — Refresh tokens rotate on use; family-based replay detection revokes the entire session family on reuse
  • Security Headers — Middleware emits standard security headers on all responses
  • Trusted ProxiesTRUSTED_PROXIES configures which upstream proxy IPs are trusted for X-Forwarded-For client IP extraction
  • SMTP TLSSMTP_SKIP_TLS_VERIFY=true disables TLS certificate verification for outgoing email; logs a loud warning at startup due to MITM risk. Use only for testing.
  • SSO — Google Sign-In, Slack Sign-In, and multi-provider OIDC SSO (see OIDC SSO)

Released under the MIT License.