Skip to content

Commit bd1b563

Browse files
Merge branch 'feat/webhook-idempotency' into copilot/add-idempotency-helpers
2 parents 0d383d2 + e970f0a commit bd1b563

10 files changed

Lines changed: 364 additions & 255 deletions

File tree

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ dist/
3434
*.test.ts.snap
3535

3636
# Prisma
37-
/prisma/*.db
37+
/prisma/dev.db
3838
/prisma/*.db-journal
39-
/prisma/prisma/*.db
40-
# /prisma/prisma/dev.db
39+
/prisma/prisma/*
40+
/prisma/prisma/dev.db
4141

4242

4343
# Logs
70.9 KB
Loading
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# NextAuth CLIENT_FETCH_ERROR Fix
2+
3+
**Date**: 2025-11-09
4+
**Error**: `[next-auth][error][CLIENT_FETCH_ERROR] "No session token provided"`
5+
**Next.js Version**: 16.0.1 (Turbopack)
6+
**NextAuth Version**: 4.24.13
7+
8+
## Problem Description
9+
10+
The application was experiencing a `CLIENT_FETCH_ERROR` from NextAuth with the message "No session token provided". This error occurred because:
11+
12+
1. **Route Conflict**: There was a custom `/api/auth/session` route that conflicted with NextAuth's built-in session endpoint
13+
2. **Missing basePath**: The `SessionProvider` wasn't configured with an explicit `basePath`
14+
3. **Missing Environment Validation**: No validation that `NEXTAUTH_SECRET` was loaded
15+
16+
## Root Cause
17+
18+
NextAuth expects to own the `/api/auth/*` routes, including `/api/auth/session`. The application had a custom session management system (SessionService) that created its own `/api/auth/session` endpoint, which returned:
19+
20+
```json
21+
{ "error": { "code": "UNAUTHORIZED", "message": "No session token provided" } }
22+
```
23+
24+
When NextAuth's client tried to fetch the session, it received this error response instead of the expected NextAuth session data.
25+
26+
## Changes Made
27+
28+
### 1. Moved Custom Session Route
29+
30+
**Before**: `src/app/api/auth/session/route.ts`
31+
**After**: `src/app/api/auth/custom-session/route.ts`
32+
33+
This allows NextAuth to handle `/api/auth/session` while preserving the custom SessionService functionality under a different endpoint.
34+
35+
### 2. Updated SessionProvider Configuration
36+
37+
**File**: `src/providers/session-provider.tsx`
38+
39+
```typescript
40+
export function SessionProvider({ children, session }: SessionProviderProps) {
41+
return (
42+
<NextAuthSessionProvider
43+
session={session}
44+
basePath="/api/auth" // ✅ Explicit basePath
45+
refetchInterval={5 * 60}
46+
refetchOnWindowFocus={true} // ✅ Auto-refetch on focus
47+
>
48+
{children}
49+
</NextAuthSessionProvider>
50+
);
51+
}
52+
```
53+
54+
**Changes**:
55+
- Added explicit `basePath="/api/auth"` to ensure NextAuth knows where to find its API routes
56+
- Added `refetchOnWindowFocus={true}` for better session synchronization
57+
58+
### 3. Added Environment Variable Validation
59+
60+
**File**: `src/app/api/auth/[...nextauth]/route.ts`
61+
62+
```typescript
63+
// Validate required environment variables
64+
if (!process.env.NEXTAUTH_SECRET) {
65+
throw new Error('NEXTAUTH_SECRET environment variable is required');
66+
}
67+
68+
if (!process.env.NEXTAUTH_URL) {
69+
console.warn('NEXTAUTH_URL environment variable is not set. Using default: http://localhost:3000');
70+
}
71+
```
72+
73+
This ensures the application fails fast with a clear error if critical environment variables are missing.
74+
75+
### 4. Enhanced NextAuth Configuration
76+
77+
**File**: `src/app/api/auth/[...nextauth]/route.ts`
78+
79+
```typescript
80+
export const authOptions: NextAuthOptions = {
81+
// Secret for JWT encryption and CSRF protection
82+
secret: process.env.NEXTAUTH_SECRET, // ✅ Explicit secret
83+
84+
session: {
85+
strategy: 'jwt',
86+
maxAge: 30 * 24 * 60 * 60,
87+
},
88+
89+
jwt: {
90+
secret: process.env.NEXTAUTH_SECRET,
91+
maxAge: 30 * 24 * 60 * 60,
92+
},
93+
// ... rest of configuration
94+
};
95+
```
96+
97+
**Changes**:
98+
- Added explicit `secret` property to `authOptions` (recommended for Next.js 16)
99+
100+
### 5. Created Test Endpoint
101+
102+
**File**: `src/app/api/auth/test/route.ts`
103+
104+
A diagnostic endpoint to verify NextAuth configuration:
105+
106+
```bash
107+
# Test endpoint
108+
curl http://localhost:3000/api/auth/test
109+
```
110+
111+
Returns:
112+
```json
113+
{
114+
"success": true,
115+
"hasSession": false,
116+
"session": null,
117+
"env": {
118+
"hasSecret": true,
119+
"hasUrl": true,
120+
"nodeEnv": "development"
121+
}
122+
}
123+
```
124+
125+
## Verification Steps
126+
127+
1. **Stop the dev server** if running:
128+
```bash
129+
# Press Ctrl+C in terminal
130+
```
131+
132+
2. **Restart the dev server**:
133+
```bash
134+
npm run dev
135+
```
136+
137+
3. **Verify environment variables**:
138+
```bash
139+
# Check .env file contains:
140+
# NEXTAUTH_SECRET="d0100e34088ba2052854abf0ee63d4942e7c42d9c35d708858f3eaae137c3553"
141+
# NEXTAUTH_URL="http://localhost:3000"
142+
```
143+
144+
4. **Test NextAuth session endpoint**:
145+
```bash
146+
# Should return NextAuth session data (not custom session error)
147+
curl http://localhost:3000/api/auth/session
148+
```
149+
150+
5. **Test the application**:
151+
- Navigate to `http://localhost:3000/login`
152+
- Login with test credentials
153+
- Verify no console errors
154+
- Verify session is established
155+
156+
## Architecture Notes
157+
158+
### Two Session Systems
159+
160+
The application now has TWO distinct session systems:
161+
162+
1. **NextAuth Sessions** (`/api/auth/*`)
163+
- JWT-based
164+
- Used by `useSession()` hook
165+
- Managed by NextAuth.js
166+
- Routes: `/api/auth/session`, `/api/auth/signin`, `/api/auth/signout`, etc.
167+
168+
2. **Custom Sessions** (`/api/auth/custom-session`)
169+
- Database-backed
170+
- Uses `session_token` cookie
171+
- Managed by `SessionService`
172+
- Route: `/api/auth/custom-session`
173+
174+
### Migration Path
175+
176+
For future cleanup, consider:
177+
178+
1. **Option A**: Migrate fully to NextAuth
179+
- Remove `SessionService`
180+
- Use NextAuth's built-in session management
181+
- Simplify authentication flow
182+
183+
2. **Option B**: Keep both systems
184+
- Use NextAuth for authentication
185+
- Use custom SessionService for extended session data
186+
- Keep endpoints separate
187+
188+
## Expected Behavior After Fix
189+
190+
**No more `CLIENT_FETCH_ERROR`** in console
191+
**NextAuth session endpoint returns proper data**
192+
**Login flow works correctly**
193+
**useSession hook works throughout app**
194+
**Session persists across page refreshes**
195+
196+
## Related Files
197+
198+
- `src/app/api/auth/[...nextauth]/route.ts` - NextAuth configuration
199+
- `src/providers/session-provider.tsx` - SessionProvider wrapper
200+
- `src/app/api/auth/custom-session/route.ts` - Custom session endpoint (renamed)
201+
- `src/services/session-service.ts` - Custom session service
202+
- `.env` - Environment variables
203+
204+
## References
205+
206+
- [NextAuth.js Documentation](https://next-auth.js.org/)
207+
- [Next.js 16 App Router](https://nextjs.org/docs/app)
208+
- [NextAuth with Next.js 16](https://next-auth.js.org/configuration/initialization#route-handlers-app)

0 commit comments

Comments
 (0)