Authentication
I korthet
Authentication is the platform's credential-and-session layer, supporting email + OTP, OAuth2 social login, TOTP/2FA, and WebAuthn passkeys, all issued as JWT ES512 tokens with rotating refresh-token families. Per-route rate limiting and abuse detection guard every entry point, while M2M OAuth2 client credentials cover scoped machine integrations for federations, partner CMSs and sponsor systems.
Så fungerar det
All authentication flows funnel into a single Craft-Easy auth service that issues JWT ES512 access tokens and opaque refresh tokens. Email + OTP is the default passwordless path: the user submits an address, receives a six-digit code by email, and exchanges it for a token pair; codes are SHA-256 hashed at rest, single-use, and rate-limited per address and per IP. OAuth2 sign-in routes through the federated SSO gateway (F02.06), which normalises Google, Microsoft, Apple and GitHub identities and returns the same token shape.
TOTP/2FA registers a secret in the user's authenticator app and is required as a step-up at sensitive endpoints; WebAuthn passkeys provide a phishing-resistant alternative bound to the user's device, with attestation verified server-side. Access tokens use ES512 (P-521 ECDSA) — a deliberately strong curve for long-lived public-key federation — and carry standard claims plus auth_time so downstream services (e.g. account linking, MFA enforcement) can require fresh authentication. Refresh tokens belong to a RefreshTokenFamily: every refresh rotates the token and invalidates the previous one, and detection of a re-used token instantly revokes the entire family, terminating all sessions on that device.
Rate limiting applies per route, per identity and per IP; repeated failures trigger exponential backoff and surface as SecurityEvents (F02.07). For machine-to-machine traffic, the OAuth2 client-credentials grant issues scoped tokens to integrators — federations syncing legacy data, partner CMSs fetching results, or sponsor systems pulling rankings — with capability sets independent of any human user.
Centrala funktioner
- Passwordless email + OTP login with hashed, single-use codes
- OAuth2 social login via the federated SSO gateway
- TOTP/2FA and WebAuthn passkeys for step-up authentication
- JWT ES512 access tokens with auth_time claim for fresh-auth checks
- Rotating refresh-token families with reuse-detection revocation
- Per-route, per-identity and per-IP rate limiting and abuse detection
- M2M OAuth2 client credentials for integrations and partner systems
I praktiken
A Swedish district admin opens the admin app on a new laptop. She types her email; the auth service emails a six-digit code that she enters within thirty seconds, receiving an access token and a refresh token. Because her role requires MFA, she is prompted to register a passkey — her laptop's platform authenticator generates one, and the public key is stored.
The next day she opens the same app, the silent refresh succeeds, and the passkey is asked for only when she opens the financial reports endpoint, which requires fresh auth. Two weeks later her laptop is stolen; from her phone she revokes all sessions, the refresh-token family is invalidated, and any further use of the stolen tokens fails immediately.
Features i detta subsystem
10| ID | Status | Funktioner |
|---|---|---|
| F02.02.01 | Levererad | Email + OTP login ✅ PL-1901 (admin console), ✅ PL-F0202a (per-tenant-matris Sverige/France/Deutschland, enumeration-skydd, abuse-limits), ✅ PL-T310 (premium passwordless flow i app: split-screen desktop / glass-mobil <AuthShell>, refined 6-digit <OtpInput> med auto-advance + paste-spread + monospace, 30 s resend-cooldown, 10 min expiry-countdown, <AuthSuccess>-anim, reduced-motion-fallback, aria-live error-announce) |
| F02.02.02 | Levererad | OAuth2 (Google, Microsoft, GitHub) via SSO-gateway with per-app routing ✅ PL-1801 (infra), ✅ PL-1802 (Microsoft/Entra ID), ✅ PL-1803 (Google), ✅ PL-1804 (GitHub), ✅ PL-1805 (frontend SSO-knappar app + admin, /auth/complete + /auth/native-complete landings, shared gateway-kontrakt), ✅ PL-1806 (Connected Accounts-vy i app + admin, GET /auth/me, GET/DELETE /auth/me/oauth-identities, POST /auth/oauth/{provider}/link/{app} med 5-min fresh-auth-fönster), ✅ PL-F0202a (surface-test Google+Microsoft i providers-listan), ✅ PL-T310 (refined <FederatedRow> icon-buttons med brand-tinted ring + per-provider a11y-label i app-login) |
| F02.02.03 | Levererad | TOTP/2FA (authenticator app) ✅ PL-F0202a (/auth/2fa/setup, /enable, /verify, /status, /disable, recovery-koder engångsbruk, PreAuthToken → UserToken-upgrade, petanque-override av craft-easy require_auth-buggen) |
| F02.02.04 | Levererad | WebAuthn passkeys ✅ PL-F0202a (/webauthn/register/options, /register, /credentials list+delete, petanque-override av craft-easy's user_id-typbug, clientDataJSON/challenge/origin-verifiering, duplicate-guard) |
| F02.02.05 | Levererad | JWT ES512 token-based sessions ✅ PL-1801 (OAuth-gateway), ✅ PL-F0202b (GET /auth/session/me med explicit algorithm-fält, ES512 verifierat via JWT-headerinspektion) |
| F02.02.06 | Levererad | Refresh token rotation ✅ PL-F0202b (RefreshTokenFamily/RefreshToken med SHA-256-hash, family-wide theft detection, POST /auth/session/issue + /refresh + /logout, plrt_-prefix, 32-byte entropi) |
| F02.02.07 | Levererad | Rate limiting and abuse detection ✅ PL-1801 (slowapi på /authorize, /callback, /exchange), ✅ PL-F0202b (AuthAbuseMonitor sliding-window per IP + subject, 60/min slowapi-gräns på /session/refresh, /session/logout, /m2m/token, failure-bucket 10/5 min → 429 med Retry-After) |
| F02.02.08 | Levererad | M2M OAuth2 client credentials for integrations ✅ PL-F0202b (POST /auth/m2m/token RFC 6749 §4.4, M2MClient-modell med capability-scope, plm2m_-prefix, admin-CRUD på /auth/m2m/clients, rotate-secret, revoke, IP-allowlist, RFC 6749 §5.2-felform, Cache-Control: no-store) |
| F02.02.09 | Levererad | Service-account M2M-tokens med admin-scopes ✅ PL-T293 (ServiceAccount-dokument, ApiToken.service_account_id, admin-scopes tenants:write / federations:write / cms:write / admin_invitations:create / users:write / seed:run, /sys/service-accounts CRUD + token-mint/revoke, agent-driven prod-bootstrap utan WebAuthn-step-up, 90-d default TTL, governance + system audit) |
| F02.02.10 | Levererad | Anti-abuse signup-pipeline ✅ PL-T301 — client_ip_cidr24 + time_to_fill_ms + honeypot_triggered + turnstile_score på SignupRequest, fraud-signal-aggregator (ip-cluster/email-repeat/honeypot/fast-fill/stripe-decline-rate) cachat 15 min, sys_security flag-fraud + email-domain-blocklist applicerad direkt vid POST /public/signup, audit-events signup.fraud_signal_triggered + signup.flagged_fraud + signup.email_domain_blocked, auto-SEV3-incident vid alert-severity. Sys-konsol: /customer-base/signups. |