Add project files
This commit is contained in:
120
docs/superpowers/specs/2026-05-21-login-auth-design.md
Normal file
120
docs/superpowers/specs/2026-05-21-login-auth-design.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Login Authentication Design (Next.js, PostgreSQL, Brevo SMTP)
|
||||
|
||||
## 1. Overview & Tech Stack
|
||||
| Component | Technology | Reason |
|
||||
|-----------|------------|--------|
|
||||
| Frontend / SSR | Next.js 13 (App Router) | File‑based routing, SSR/SSG, built‑in API routes |
|
||||
| Database | PostgreSQL (self‑hosted, EU datacenter) | ACID, at‑rest encryption, works with Prisma |
|
||||
| ORM | Prisma 2 | Type‑safe queries, easy migrations |
|
||||
| Password hashing | bcrypt (cost = 12) | Industry‑standard, slow enough to deter brute‑force |
|
||||
| Tokens | JWT (HS256) | Access token ~15 min, Refresh token ~7 days |
|
||||
| Session cookies | HttpOnly + Secure + SameSite=Lax (chosen by user) | XSS/CSRF protection |
|
||||
| Email service | Brevo SMTP | GDPR‑compatible, simple configuration |
|
||||
| Deployment | Vercel (server‑less API routes) | Automatic builds, EU region, zero‑config |
|
||||
| Testing | Jest + React Testing Library, Supertest for API | Unit & integration coverage |
|
||||
|
||||
## 2. Database Schema (Prisma)
|
||||
```prisma
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
passwordHash String
|
||||
role Role @default(USER)
|
||||
emailVerified Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
verificationTokens VerificationToken[]
|
||||
passwordResetTokens PasswordResetToken[]
|
||||
}
|
||||
|
||||
model VerificationToken {
|
||||
id String @id @default(cuid())
|
||||
token String @unique
|
||||
expiresAt DateTime
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model PasswordResetToken {
|
||||
id String @id @default(cuid())
|
||||
token String @unique
|
||||
expiresAt DateTime
|
||||
used Boolean @default(false)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
enum Role {
|
||||
ADMIN
|
||||
USER
|
||||
}
|
||||
```
|
||||
|
||||
## 3. API Routes (Next.js `/pages/api/...`)
|
||||
| Route | Method | Purpose | Input | Output |
|
||||
|------|--------|---------|-------|--------|
|
||||
| `/api/auth/register` | POST | Create user, hash password, send verification mail | `{ email, password }` | 201 Created, message "Verification mail sent" |
|
||||
| `/api/auth/verify-email` | GET | Validate verification token, set `emailVerified` | `?token=` | 200 OK, "Email verified" |
|
||||
| `/api/auth/login` | POST | Check credentials, issue access & refresh JWT, set cookies | `{ email, password, rememberMe? }` | 200 OK, cookies set |
|
||||
| `/api/auth/logout` | POST | Clear cookies, optionally blacklist refresh token | – | 200 OK |
|
||||
| `/api/auth/refresh-token` | POST | Verify refresh JWT, issue new access JWT (rotate refresh if >2 days) | – (refresh cookie) | 200 OK, new cookies |
|
||||
| `/api/auth/request-password-reset` | POST | Create reset token, send mail | `{ email }` | 200 OK, message "Mail sent" |
|
||||
| `/api/auth/reset-password` | POST | Validate reset token, store new bcrypt hash, invalidate token | `{ token, newPassword }` | 200 OK |
|
||||
| `/api/auth/me` | GET | Return current user data (no password) | – | 200 OK, `{ email, role, emailVerified }` |
|
||||
|
||||
All endpoints enforce `Content-Type: application/json` and `Cache-Control: no-store`.
|
||||
|
||||
## 4. Email Workflow (Brevo SMTP)
|
||||
1. Registration creates a `VerificationToken` (UUID + HMAC) stored with an expiry (24 h).
|
||||
2. Email template (HTML + text) contains a link:
|
||||
`https://<your‑app>.vercel.app/api/auth/verify-email?token=<<token>>`
|
||||
3. The verification endpoint validates the token, marks the user as verified and deletes the token.
|
||||
4. Password‑reset works analogously with a one‑hour token and a `used` flag.
|
||||
|
||||
SMTP credentials (`BREVO_SMTP_HOST`, `BREVO_SMTP_USER`, `BREVO_SMTP_PASS`) are stored as Vercel environment variables.
|
||||
|
||||
## 5. Session & Cookie Settings
|
||||
| Cookie | Content | Max Age | SameSite | Secure | HttpOnly |
|
||||
|--------|---------|---------|----------|--------|----------|
|
||||
| `accessToken` | JWT (`sub`, `role`, `exp`) | 15 min | Lax (as requested) | true | true |
|
||||
| `refreshToken` | JWT (`sub`, `exp`) | 7 days (user chose "remember me") | Lax | true | true |
|
||||
|
||||
Refresh token is only set when the front‑end sends `rememberMe: true`.
|
||||
|
||||
## 6. Role & Permission System
|
||||
- `requireAuth` middleware validates the access token and attaches `req.user`.
|
||||
- `requireRole('ADMIN')` middleware checks `req.user.role`.
|
||||
- Roles are stored in the `role` column of `User` and encoded into the JWT payload.
|
||||
|
||||
## 7. GDPR & Data‑Minimisation
|
||||
| Measure | Implementation |
|
||||
|---------|----------------|
|
||||
| Minimal data | Store only email, hashed password, role, verification flag. |
|
||||
| Consent | Registration form includes a mandatory "I accept the privacy policy" checkbox. |
|
||||
| Right to be forgotten | `DELETE /api/users/me` removes the user row and all related tokens. |
|
||||
| Data retention | Verification and reset tokens have explicit `expiresAt`; nightly Prisma job deletes expired rows. |
|
||||
| Transport security | All traffic forced via HTTPS (Vercel provides TLS). |
|
||||
| At‑rest encryption | PostgreSQL instance encrypted by the managed provider (EU region). |
|
||||
| Audit log | Optional `AuditLog` table with pseudonymised entries, retained 30 days. |
|
||||
|
||||
## 8. Deployment Pipeline (Vercel)
|
||||
1. Connect the GitHub repo to Vercel.
|
||||
2. Vercel runs `npm install && npm run build && npm test` on each push.
|
||||
3. Preview deployments for PRs (`pr‑<num>--<repo>.vercel.app`).
|
||||
4. Production deploy on merge to `main` (`https://<app>.vercel.app`).
|
||||
5. Environment variables (`DATABASE_URL`, `NEXTAUTH_SECRET`, Brevo SMTP creds) are configured in Vercel > Settings > Environment Variables – same values for Preview and Production.
|
||||
|
||||
## 9. Security Checklist
|
||||
- ✅ bcrypt cost = 12
|
||||
- ✅ HttpOnly + Secure + SameSite Lax cookies
|
||||
- ✅ Refresh‑token rotation on each refresh
|
||||
- ✅ Rate limiting on `/login` and `/request-password-reset`
|
||||
- ✅ CSP, X‑Content‑Type‑Options, Referrer‑Policy headers via `next.config.js`
|
||||
- ✅ Helmet‑like security headers
|
||||
- ✅ Regular dependency audit (`npm audit`) and CI fail on high severity issues
|
||||
|
||||
---
|
||||
*This spec is ready for review. Once approved, the next step will be to create a detailed implementation plan.*
|
||||
Reference in New Issue
Block a user