Authentication
Purpose
Section titled “Purpose”Describe the authentication model for both human users and edge nodes.
Overview
Section titled “Overview”Users authenticate at POST /api/v1/auth/login and receive a stateless
HS256 JWT. The token’s custom claims (internal/auth) are tid (tenant),
sub (user id), email and role, plus standard iss/aud/exp. Every
/api/v1 request carries it as a Bearer token; the middleware validates it,
rejects tokens missing tid/sub, and pins the request to the tenant. WebSocket
endpoints (/ws/supervisor, /ws/agent) verify the token from a ?token=
query parameter since browsers can’t set headers on the upgrade.
Edge nodes use a separate scheme: a raw API key (issued at registration)
presented as a bearer token and matched against the SHA-256 digest in
nodes.api_key_hash.
Configuration
Section titled “Configuration”AUTH_JWT_SECRET=... # signing secret, >= 16 bytesAUTH_JWT_ISSUER=get2dialAUTH_JWT_AUDIENCE=get2dial-controlAUTH_JWT_TTL_SECONDS=43200 # 12hAUTH_BCRYPT_COST=12AUTH_BOOTSTRAP_TOKEN= # empty disables POST /api/v1/auth/bootstrapDEFAULT_TENANT_DOMAIN=dev.get2dial.local # login fallback workspaceExamples
Section titled “Examples”Login accepts {email, password, tenant_domain?}. With tenant_domain omitted,
the workspace is resolved from the email (the password disambiguates collisions),
falling back to DEFAULT_TENANT_DOMAIN. A successful login returns a JWT the web
app sends on every subsequent request:
GET /api/v1/auth/meAuthorization: Bearer <jwt>- JWTs are stateless —
POST /api/v1/auth/logoutis audit-only; there is no server-side revocation yet, so keep the TTL sane. - Failed logins lock the account after 10 attempts for 15 minutes and return generic errors to avoid enumeration.
- Rotating
AUTH_JWT_SECRETinvalidates all outstanding tokens.