7. Authentication - A Detailed Guide (Overview)
The foundation of Authentication (AuthN) and Authorization (AuthZ) before reading 8. NextAuth v5 and 9. JWT Dual Auth.
On this page
- Table of Contents
- 1. AuthN vs AuthZ
- 2. Three Phases in a Real App
- 3. Session Storage Models
- 4. Access + Refresh Token
- 5. Where to Store the Token - Cookie vs localStorage
- 6. OAuth / Google Login - The Idea
- 7. Credentials Login - The Idea
- 8. Layered Defense (Next.js Recommendation)
- 9. What Model Does Nova Shop Use?
- 10. FAQ & Exercises
7. Authentication - A Detailed Guide (Overview)
The foundation of Authentication (AuthN) and Authorization (AuthZ) before reading 8. NextAuth v5 and 9. JWT Dual Auth.
Read in order: 7 (this file) → 8 (NextAuth) → 9 (JWT Nova) → 6 (Middleware).
Docs: Authentication Guide
Table of Contents
- AuthN vs AuthZ
- Three phases in a real app
- Session storage models
- Access + Refresh token
- Where to store the token - cookie vs localStorage
- OAuth / Google login - the idea
- Credentials login - the idea
- Layered defense (Next.js recommendation)
- What model does Nova Shop use?
- FAQ & exercises
1. AuthN vs AuthZ
| Authentication (AuthN) | Authorization (AuthZ) | |
|---|---|---|
| Question | Who are you? | What are you allowed to do? |
| Example | Log in with email/password | Only admin can delete a product |
| Nova | NextAuth + JWT cookies | /products requires a session; NestJS checks role/ownership |
Common confusion: Being logged in (AuthN) ≠ being allowed to edit someone else's order (AuthZ).
2. Three Phases in a Real App
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 1. Login │ → │ 2. Session │ → │ 3. API call │
│ verify user │ │ holds state │ │ sends token │
└──────────────┘ └──────────────┘ └──────────────┘
| Phase | Nova Shop |
|---|---|
| Login | signIn → NestJS /login or /google |
| Session | NextAuth JWT + access_token cookies |
| API | authFetch attaches Bearer |
3. Session Storage Models
A. Server-side session (sessionId cookie)
Client: cookie sessionId=abc
Server: DB sessions[abc] = { userId, ... }
| Pros | Cons |
|---|---|
| Revoke instantly (delete from DB) | Requires Redis/DB |
| Easy to audit | Scaling needs a shared store |
B. Stateless JWT
Client: cookie token=eyJhbG...
Server: verify signature, read claims - no DB lookup
| Pros | Cons |
|---|---|
| Scales easily | Hard to revoke before expiry |
| Larger token than a session id |
C. Dual token (Nova backend)
See section 4 - short-lived access + long-lived refresh.
4. Access + Refresh Token
| Token | TTL (Nova) | Used for |
|---|---|---|
| Access | Short (ACCESS_TOKEN_MAX_AGE) | Every authFetch |
| Refresh | Long (REFRESH_TOKEN_MAX_AGE) | Only /token |
Why not one long-lived token? The access token is exposed on many requests → a smaller attack window.
5. Where to Store the Token - Cookie vs localStorage
| Location | Stealable via XSS? | Sent automatically? | Nova |
|---|---|---|---|
| HttpOnly cookie | Hard (JS can't read it) | Yes (same-site) | ✅ access_token |
| localStorage | Easy | No | ❌ |
| Memory | Lost when tab closes | No | Rarely used in production |
Nova's cookie flags:
httpOnly: true,
secure: production,
sameSite: "lax",
CSRF: sameSite: lax + a Server Actions origin check reduce the risk of the cookie being sent automatically from a foreign site.
6. OAuth / Google Login - The Idea
User → NextAuth redirects to Google
→ Google returns an authorization code / id_token
→ NextAuth signIn callback
→ Nova POSTs /google { idToken } to NestJS
→ NestJS verifies with Google, returns a JWT
→ setAuthCookies
| Side | Job |
|---|---|
| NextAuth | OAuth UI, redirect URI, state |
| NestJS | The final source of trust - issues the system's own JWT |
Never just trust the client-side token - the backend verifies the id_token.
7. Credentials Login - The Idea
Email/password form
→ Server Action authenticate()
→ signIn("credentials")
→ authorize() → POST /login NestJS
→ setAuthCookies
→ redirect /products
The password is never stored on Next.js - it's only forwarded to the API.
Validation: Zod in authorize (email, password min 6 characters).
8. Layered Defense (Next.js Recommendation)
Layer 1 - middleware.ts
Cookie + NextAuth? → redirect to /login early
Layer 2 - Server Component / Action
authFetch, unauthorized() on 401
Layer 3 - NestJS API
Verify JWT, ownership (this user's own cart)
Middleware alone isn't enough - an attacker could call a Server Action directly.
Data Access Layer pattern (docs): group auth checks close to where data is read - Nova's equivalent is authFetch + the services layer.
9. What Model Does Nova Shop Use?
┌─────────────────────────────────────────┐
│ NextAuth v5 (JWT session) │ ← UX, useSession, middleware
├─────────────────────────────────────────┤
│ HttpOnly cookies (access + refresh) │ ← authFetch → NestJS
├─────────────────────────────────────────┤
│ NestJS JWT validation │ ← business source of truth
└─────────────────────────────────────────┘
This is "dual auth" / a BFF - more complex than an Auth.js-only tutorial, but reasonable when an API already exists.
| File | Role |
|---|---|
auth.ts, auth.config.ts | NextAuth |
auth-tokens.ts | Cookies + refresh |
api-client.ts | authFetch |
middleware.ts | Route gating |
10. FAQ & Exercises
FAQ
Q: What is AUTH_SECRET used for?
Signs the NextAuth session JWT - required in production.
Q: What does logging out clear?
The signOut event → POST /logout to NestJS + clearAuthCookies.
Q: Can I just use NextAuth and drop the backend JWT?
Only if the API also trusts the NextAuth session - Nova's API needs its own Bearer token.
Exercises
- What's the difference between AuthN and AuthZ, using
/cartas an example? - Why isn't the refresh token sent with every product list request?
Next: 8. NextAuth v5 · 9. JWT Cookies
