Authentication

What authentication modes does Areev support?

Areev supports four pluggable authentication modes — none, api-key, oidc, and composite — configured via the --auth CLI flag. This context database attaches an AuthIdentity (principal, scopes, auth method) to every request through an AuthLayer middleware, ensuring that AI memory access is always attributable to a known identity.

The request pipeline applies middleware in order: Request -> CORS -> RateLimit -> AuthLayer -> AI Disclosure -> Handler. When auth is disabled (--auth none), anonymous identities receive read and write scopes but not admin, enforcing least-privilege even without authentication. Public endpoints (/api/health, /api/config, /.well-known/*, /api/auth/oauth/*, /api/auth/register, /api/auth/login, /api/auth/verify-email, /api/billing/webhooks/*) bypass authentication entirely regardless of the configured mode.

import requests

# Authenticate with an API key
resp = requests.get("http://localhost:4009/api/memories", headers={
    "Authorization": "Bearer ar_7f3a9bc2d1e4..."
})
GET /api/memories HTTP/1.1
Host: localhost:4009
Authorization: Bearer ar_7f3a9bc2d1e4...
# Start with each auth mode
areev serve --http 0.0.0.0:4011 --auth none
areev serve --http 0.0.0.0:4011 --auth api-key
areev serve --http 0.0.0.0:4011 --auth oidc \
  --oidc-issuer https://accounts.google.com \
  --oidc-audience YOUR_CLIENT_ID
areev serve --http 0.0.0.0:4011 --auth composite

How do API keys work?

API keys use an ar_ prefix (67 characters: ar_ + 64 hex-encoded random bytes) and are SHA-256 hashed at rest in the ControlPlane store (Fjall partition, with legacy fallback to .api_keys.enc). The raw key is returned exactly once at creation time and never stored in plaintext, so this autonomous memory system never holds reversible credentials on disk.

Key management exposes three endpoints: POST /api/auth/keys (create, returns raw key once), GET /api/auth/keys (list with prefix only, no secrets), and DELETE /api/auth/keys/{key_id} (revoke). Creating a key requires admin scope and accepts a principal, name, and scopes array. The AI agent memory tracks each key’s principal identity so that all downstream operations are attributed to the correct service or user.

# Create an API key
resp = requests.post("http://localhost:4009/api/auth/keys",
    headers={"Authorization": "Bearer <admin-token>"},
    json={"name": "my-service", "principal": "service:my-app", "scopes": ["read", "write"]}
)
raw_key = resp.json()["raw_key"]  # ar_7f3a9bc2d1e4... — shown once
curl -X POST http://localhost:4009/api/auth/keys \
  -H "Authorization: Bearer <admin-token>" \
  -d '{"name":"my-service","principal":"service:my-app","scopes":["read","write"]}'

How does OIDC/JWT authentication work?

With --auth oidc, Areev validates JWT bearer tokens against configured OIDC providers by fetching the provider’s JWKS (JSON Web Key Set) for signature verification. The --oidc-principal-claim flag controls which JWT claim maps to the principal identifier (default: email).

Principals follow a consistent format across auth modes: anonymous for none, the stored principal for API keys (e.g., service:atmatic-prod), and user:{claim} for OIDC (e.g., user:john@example.com). This context database maps each principal format into a unified AuthIdentity struct, so downstream authorization and audit trail entries work identically regardless of the authentication method used.

# Configure OIDC with Google
areev serve --http 0.0.0.0:4011 --auth oidc \
  --oidc-issuer https://accounts.google.com \
  --oidc-audience YOUR_CLIENT_ID \
  --oidc-principal-claim email
GET /api/memories HTTP/1.1
Host: localhost:4009
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

How are authentication events audited?

All authentication events are recorded in the hash-chained audit trail with dedicated event types. This AI memory system logs 10 auth event types covering the full lifecycle from registration through logout, including failed attempts, password resets, and organization switching.

The audit trail captures auth.login, auth.register, auth.logout, auth.refresh, auth.password_change, auth.password_reset, auth.failed_login, auth.oauth_link, auth.oauth_unlink, and auth.org_switch. Failed login attempts are tracked for SOC 2 CC7.2 (security incident monitoring) and HIPAA 164.312(b) (audit controls) compliance. Each event includes the pseudonymized actor identity, timestamp, and hash chain link, making the record tamper-evident.

auth.login           User logged in via OAuth or email/password
auth.register        New user registered
auth.logout          User logged out (refresh token revoked)
auth.refresh         JWT token refreshed
auth.password_change User changed their password
auth.password_reset  User reset their password via email flow
auth.failed_login    Failed login attempt (SOC 2 CC7.2, HIPAA 164.312(b))
auth.oauth_link      OAuth provider linked to account
auth.oauth_unlink    OAuth provider unlinked from account
auth.org_switch      Organization context switched (from/to org, role change)