Lucia Auth
Implements secure, production-oriented authentication using the patterns from Lucia Auth and The Copenhagen Book.
Overview
For browser-based web apps, treat auth as a system instead of a pair of login routes. If a user asks to "add auth" and does not explicitly ask for a toy example, ship a production baseline by default.
Production Baseline For Web Apps
When the repo does not already provide equivalents, the default baseline is:
- Email/password sign up, sign in, and sign out
- Server-side sessions in
HttpOnly, Secure, SameSite cookies
- Email verification plus resend flow
- Password reset flow
- Rate limiting on every auth and email-sending endpoint
- CSRF protection or strict
Origin validation on every state-changing route
- Session invalidation on password change, email verification/change, and permission changes
- Re-authentication ("sudo mode") for sensitive actions such as changing password/email, deleting account, disabling MFA, or viewing API keys
- Safe post-auth redirects with open-redirect protection
- Optional OAuth, TOTP, or WebAuthn layered on top as requested
Do not default to JWTs in localStorage for a normal web app. Prefer server-side sessions unless the architecture clearly requires stateless tokens.
Required Reference Reads
For any browser-based web auth task, always read these first:
references/copenhagen-book/password-authentication.md
references/copenhagen-book/sessions.md
references/copenhagen-book/csrf.md
references/copenhagen-book/email-verification.md
references/copenhagen-book/password-reset.md
references/copenhagen-book/open-redirect.md
references/lucia/sessions-basic.md
references/lucia/sessions-inactivity-timeout.md
references/lucia/rate-limit-token-bucket.md
Read these when relevant:
- OAuth:
references/copenhagen-book/oauth.md, then references/lucia/tutorial-github-oauth.md or references/lucia/tutorial-google-oauth.md
- MFA:
references/copenhagen-book/mfa.md
- WebAuthn / passkeys:
references/copenhagen-book/webauthn.md, then references/lucia/example-email-password-2fa-webauthn.md
- Session tradeoffs:
references/lucia/sessions-overview.md, references/lucia/sessions-stateless-tokens.md
Implementation Workflow
- Inspect the repo for existing auth, user, email, session, middleware, and database patterns.
- Decide the auth surface area.
For a standard web app, default to the production baseline above.
- Create or update the auth schema first.
At minimum:
user, session, email_verification, and password_reset.
Add oauth_account, user_totp, user_recovery_code, or WebAuthn tables only when needed.
- Implement secure primitives next.
Password hashing, session issuance/validation, CSRF/origin checks, rate limiting, token generation, and redirect validation.
- Wire complete user flows.
Registration, login, logout, verify email, resend verification, forgot password, reset password, change password, and revoke sessions.
- Add sensitive-action re-auth.
Changing email/password, account deletion, disabling MFA, or security settings should require a fresh session or a new credential challenge.
- Verify behavior.
Confirm cookie flags, rate limits, invalidation behavior, expired-token handling, and unhappy paths.
Security Rules
Passwords
- Hash passwords with Argon2id. Scrypt is an acceptable fallback, bcrypt only for legacy constraints.
- Minimum length is 8 characters. Do not set a low maximum; 64-256 is a reasonable bound.
- Do not silently trim, normalize, or truncate passwords.
- Allow copy/paste and password managers.
- Check leaked passwords with haveibeenpwned when practical.
- Recommend MFA for security-sensitive apps and require it when the app meaningfully needs it.
Emails
- Normalize emails to lowercase before storing or comparing.
- Keep validation simple to avoid ReDoS.
- Do not silently remove
+tag segments.
- If email is used for identity recovery, implement verification before treating it as trusted.
Sessions
- Create a brand new session on login. Never reuse a pre-auth or anonymous session after authentication.
- Store a hash of the session secret, not the raw secret.
- Prefer idle expiration plus an absolute lifetime.
- Track session freshness for re-auth flows.
- Invalidate all sessions when credentials or privileges change.
- Never accept session tokens through URLs.
Cookies
- Use
HttpOnly, Secure, Path=/, and SameSite=Lax by default.
- Use
SameSite=Strict only when the UX tradeoff is acceptable.
- Refresh long-lived cookies when the server refreshes the session inactivity window.
CSRF
- Do not mutate state with
GET.
- Check
Origin on all non-GET browser requests and reject when missing or untrusted.
- For form-heavy apps, add CSRF tokens as a second layer.
- Keep CORS strict so CSRF tokens cannot be harvested cross-origin.
OAuth / OIDC
- Use Authorization Code + PKCE.
- Verify
state and the code verifier on callback.
- Prefer
client_secret_basic when the provider supports it.
- Link accounts by provider subject first, and only auto-link by email when the provider explicitly marks the email as verified.
- Sanitize any post-login
returnTo or redirect_to value to same-origin paths only.
Verification And Reset Tokens
- Use high-entropy random tokens for links.
- Hash link tokens before storage with SHA-256.
- Keep tokens single-use and expire them automatically.
- Put token-bearing pages behind
Referrer-Policy: strict-origin.
- Email-sending endpoints must be strictly rate limited.
Template Map
Use these assets as starting points and adapt them to the framework and ORM already in the repo:
- Password hashing and password policy:
assets/password-utils.ts
- Session issuance, validation, inactivity timeout, and fresh-session helpers:
assets/session-manager.ts
- Core SQL schema:
assets/session-schema.sql
- Email verification links and codes:
assets/email-verification.ts
- Password reset flow:
assets/password-reset.ts
- OAuth + PKCE flow helpers:
assets/oauth-handler.ts
- CSRF and origin validation helpers:
assets/csrf-protection.ts
- Token bucket rate limiting:
assets/rate-limit.ts
- TOTP MFA and recovery codes:
assets/totp-mfa.ts
When To Escalate Beyond The Baseline
Add WebAuthn or passkeys when:
- The user explicitly asks for passkeys or WebAuthn
- The product is security-sensitive
- The app wants phishing-resistant MFA
Add OAuth when:
- The product already uses external identity providers
- The user explicitly asks for social login
- The app benefits from lower signup friction
Use stateless tokens only when:
- The app is an API-first system that cannot rely on same-origin cookies, or
- There is a clear multi-service architecture reason
Output Expectations
When using this skill, the final answer should make it clear:
- Which auth flows were implemented
- Which security controls were included by default
- Any remaining assumptions or provider-specific configuration the user must supply
- What was verified locally and what still needs integration testing
1---2name: lucia-auth3description: Build production-ready web authentication using Lucia Auth and The Copenhagen Book patterns. Use when users ask to "add auth", "implement authentication", "setup login", "add sessions", "password reset", "verify email", "implement OAuth", "add 2FA/MFA", "add passkeys", "password hashing", or reference "lucia auth" or "the copenhagen book". Default to a production baseline for browser-based web apps, not a demo-only login flow.4---56# Lucia Auth78Implements secure, production-oriented authentication using the patterns from [Lucia Auth](https://lucia-auth.com) and [The Copenhagen Book](https://thecopenhagenbook.com).910## Overview1112For browser-based web apps, treat auth as a system instead of a pair of login routes. If a user asks to "add auth" and does not explicitly ask for a toy example, ship a production baseline by default.1314## Production Baseline For Web Apps1516When the repo does not already provide equivalents, the default baseline is:17181. Email/password sign up, sign in, and sign out192. Server-side sessions in `HttpOnly`, `Secure`, `SameSite` cookies203. Email verification plus resend flow214. Password reset flow225. Rate limiting on every auth and email-sending endpoint236. CSRF protection or strict `Origin` validation on every state-changing route247. Session invalidation on password change, email verification/change, and permission changes258. Re-authentication ("sudo mode") for sensitive actions such as changing password/email, deleting account, disabling MFA, or viewing API keys269. Safe post-auth redirects with open-redirect protection2710. Optional OAuth, TOTP, or WebAuthn layered on top as requested2829Do not default to JWTs in `localStorage` for a normal web app. Prefer server-side sessions unless the architecture clearly requires stateless tokens.3031## Required Reference Reads3233For any browser-based web auth task, always read these first:3435- `references/copenhagen-book/password-authentication.md`36- `references/copenhagen-book/sessions.md`37- `references/copenhagen-book/csrf.md`38- `references/copenhagen-book/email-verification.md`39- `references/copenhagen-book/password-reset.md`40- `references/copenhagen-book/open-redirect.md`41- `references/lucia/sessions-basic.md`42- `references/lucia/sessions-inactivity-timeout.md`43- `references/lucia/rate-limit-token-bucket.md`4445Read these when relevant:4647- OAuth: `references/copenhagen-book/oauth.md`, then `references/lucia/tutorial-github-oauth.md` or `references/lucia/tutorial-google-oauth.md`48- MFA: `references/copenhagen-book/mfa.md`49- WebAuthn / passkeys: `references/copenhagen-book/webauthn.md`, then `references/lucia/example-email-password-2fa-webauthn.md`50- Session tradeoffs: `references/lucia/sessions-overview.md`, `references/lucia/sessions-stateless-tokens.md`5152## Implementation Workflow53541. Inspect the repo for existing auth, user, email, session, middleware, and database patterns.552. Decide the auth surface area.56 For a standard web app, default to the production baseline above.573. Create or update the auth schema first.58 At minimum: `user`, `session`, `email_verification`, and `password_reset`.59 Add `oauth_account`, `user_totp`, `user_recovery_code`, or WebAuthn tables only when needed.604. Implement secure primitives next.61 Password hashing, session issuance/validation, CSRF/origin checks, rate limiting, token generation, and redirect validation.625. Wire complete user flows.63 Registration, login, logout, verify email, resend verification, forgot password, reset password, change password, and revoke sessions.646. Add sensitive-action re-auth.65 Changing email/password, account deletion, disabling MFA, or security settings should require a fresh session or a new credential challenge.667. Verify behavior.67 Confirm cookie flags, rate limits, invalidation behavior, expired-token handling, and unhappy paths.6869## Security Rules7071### Passwords7273- Hash passwords with Argon2id. Scrypt is an acceptable fallback, bcrypt only for legacy constraints.74- Minimum length is 8 characters. Do not set a low maximum; 64-256 is a reasonable bound.75- Do not silently trim, normalize, or truncate passwords.76- Allow copy/paste and password managers.77- Check leaked passwords with haveibeenpwned when practical.78- Recommend MFA for security-sensitive apps and require it when the app meaningfully needs it.7980### Emails8182- Normalize emails to lowercase before storing or comparing.83- Keep validation simple to avoid ReDoS.84- Do not silently remove `+tag` segments.85- If email is used for identity recovery, implement verification before treating it as trusted.8687### Sessions8889- Create a brand new session on login. Never reuse a pre-auth or anonymous session after authentication.90- Store a hash of the session secret, not the raw secret.91- Prefer idle expiration plus an absolute lifetime.92- Track session freshness for re-auth flows.93- Invalidate all sessions when credentials or privileges change.94- Never accept session tokens through URLs.9596### Cookies9798- Use `HttpOnly`, `Secure`, `Path=/`, and `SameSite=Lax` by default.99- Use `SameSite=Strict` only when the UX tradeoff is acceptable.100- Refresh long-lived cookies when the server refreshes the session inactivity window.101102### CSRF103104- Do not mutate state with `GET`.105- Check `Origin` on all non-GET browser requests and reject when missing or untrusted.106- For form-heavy apps, add CSRF tokens as a second layer.107- Keep CORS strict so CSRF tokens cannot be harvested cross-origin.108109### OAuth / OIDC110111- Use Authorization Code + PKCE.112- Verify `state` and the code verifier on callback.113- Prefer `client_secret_basic` when the provider supports it.114- Link accounts by provider subject first, and only auto-link by email when the provider explicitly marks the email as verified.115- Sanitize any post-login `returnTo` or `redirect_to` value to same-origin paths only.116117### Verification And Reset Tokens118119- Use high-entropy random tokens for links.120- Hash link tokens before storage with SHA-256.121- Keep tokens single-use and expire them automatically.122- Put token-bearing pages behind `Referrer-Policy: strict-origin`.123- Email-sending endpoints must be strictly rate limited.124125## Template Map126127Use these assets as starting points and adapt them to the framework and ORM already in the repo:128129- Password hashing and password policy: `assets/password-utils.ts`130- Session issuance, validation, inactivity timeout, and fresh-session helpers: `assets/session-manager.ts`131- Core SQL schema: `assets/session-schema.sql`132- Email verification links and codes: `assets/email-verification.ts`133- Password reset flow: `assets/password-reset.ts`134- OAuth + PKCE flow helpers: `assets/oauth-handler.ts`135- CSRF and origin validation helpers: `assets/csrf-protection.ts`136- Token bucket rate limiting: `assets/rate-limit.ts`137- TOTP MFA and recovery codes: `assets/totp-mfa.ts`138139## When To Escalate Beyond The Baseline140141Add WebAuthn or passkeys when:142143- The user explicitly asks for passkeys or WebAuthn144- The product is security-sensitive145- The app wants phishing-resistant MFA146147Add OAuth when:148149- The product already uses external identity providers150- The user explicitly asks for social login151- The app benefits from lower signup friction152153Use stateless tokens only when:154155- The app is an API-first system that cannot rely on same-origin cookies, or156- There is a clear multi-service architecture reason157158## Output Expectations159160When using this skill, the final answer should make it clear:1611621. Which auth flows were implemented1632. Which security controls were included by default1643. Any remaining assumptions or provider-specific configuration the user must supply1654. What was verified locally and what still needs integration testing