Authentication boundary
Update: completion work adds account/team controls, owned DNS, private GitHub, Git automation and scheduled cold backups. Where earlier limits below differ, that guide describes the current implementation and required migrations.
Authenticator MFA is now available with migration 015 and a separate dashboard
ACCOUNT_ENCRYPTION_KEY. Read MFA setup, the Auth.js pending-session boundary and acceptance before upgrading. Password reset retains MFA; direct API access also requires second-factor verification for enrolled users.
Auth.js uses the stable next-auth v4 package with Google/GitHub and a custom PostgreSQL adapter. Matching emails do not automatically link accounts (allowDangerousEmailAccountLinking stays disabled). Google requires verified email. GitHub requests only read:user and user:email; repositories need a future separate GitHub App. Auth.js handles OAuth state and Google PKCE.
The stable Credentials provider requires JWT sessions. Password login is therefore a separate same-origin endpoint writing the same sessions table and cookie as OAuth. Registration requires a 12–128 character password, uses Argon2id (64 MiB, 3 iterations), creates a workspace transactionally, and mails a 30-minute verification token. Login requires verification. Forgot-password and resend-verification return generic responses. Reset tokens are consumed atomically; reset revokes all sessions. SMTP failures surface as errors; persisted accounts can resend verification. Mailpit is local-only.
Email links carry tokens in URL fragments to avoid HTTP access logs and Referrer exposure. Verification requires a deliberate POST. Tokens are cleared from the URL after success. All custom mutations require an exact Origin match to NEXTAUTH_URL. Atomic database counters rate-limit action/account identifiers plus a global cap. Add per-client IP limits at a trusted ingress; arbitrary forwarded IP headers are not trusted. Schedule cleanup of expired rate_limits, sessions, and email_verification_tokens.
Cookies: ownserva.session in development; __Host-ownserva.session in production with Secure, HttpOnly, SameSite=Lax, Path=/, no Domain. Production requires HTTPS. Next.js passes the token over the private network as Authorization: Bearer to Go, never to client JavaScript. Go computes SHA256 and joins sessions/users, checking database expiry. Invalid/revoked tokens receive 401; outages receive 503. For multiple hosts use private TLS/mTLS. NEXTAUTH_SECRET must contain at least 32 random bytes.
Google OAuth
- Create a Google Cloud project and consent screen. Add test users while testing.
- Create an OAuth Web application client; authorized JavaScript origin:
http://localhost:3000. - Exact redirect URI:
http://localhost:3000/api/auth/callback/google. - Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET; restart.
- Production needs a separate client with your exact HTTPS origin and
/api/auth/callback/google. Complete Google's applicable verification requirements.
GitHub OAuth
- GitHub Settings → Developer settings → OAuth Apps → New OAuth App.
- Homepage:
http://localhost:3000; callback:http://localhost:3000/api/auth/callback/github. - Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET; restart.
- Use a separate app for the exact production HTTPS origin. No repo scope is requested.
Buttons are disabled without client IDs. Supply both ID and secret together. Never commit credentials.
SMTP uses patched Nodemailer 10.1.7 under the smtp-mailer package alias. This keeps Auth.js's unused optional Nodemailer 7 Email-provider peer out of the runtime. Auth.js EmailProvider is not configured; verification and reset mail use the custom SMTP service. Audit reports zero known npm vulnerabilities for the resolved lockfile.
End-to-end checks
Run Compose. Register, open Mailpit at localhost:8025, follow the link, and press Verify email. Sign in, create an organization, and view its member directory. Sign out and confirm the prior session is rejected by /api/backend/me. Reset a password and confirm token reuse fails and other sessions are revoked. Configure OAuth to test each live provider. A second account must not read the first account's organization UUID. Live OAuth and SMTP require configured services.
Compatibility references: Auth.js Credentials constraints, Next.js requirements, and next-auth npm peer dependencies were checked before installation.