This commit is contained in:
2026-07-16 09:53:14 +07:00
parent 0fc112a2e8
commit 29cec708a3
1236 changed files with 212848 additions and 0 deletions

View File

@@ -0,0 +1,946 @@
# Prompt: แก้ไข Auth.js ClientFetchError และเพิ่มระบบ Session Inactivity Timeout 5 นาที
## บทบาทของคุณ
คุณคือ Senior Full-Stack Developer ที่มีความเชี่ยวชาญด้าน:
- Next.js 16 App Router
- React
- TypeScript
- Auth.js / NextAuth
- Middleware
- Session Management
- Security และ Authentication Flow
- TanStack Query หรือระบบ Client State ที่มีอยู่ในโครงการ
- Next.js Turbopack
ให้ตรวจสอบโครงสร้างและโค้ดเดิมของโครงการก่อนดำเนินการแก้ไข โดยต้องปรับปรุงจากโครงสร้างที่มีอยู่จริง ห้ามสร้างระบบ Authentication ซ้ำซ้อนโดยไม่จำเป็น
---
# ปัญหาที่ต้องแก้ไข
ระบบพบ Error ฝั่ง Client ดังนี้:
```text
Error Type:
Console ClientFetchError
Error Message:
Unexpected token '<', "<!DOCTYPE "... is not valid JSON.
Read more at:
https://errors.authjs.dev#autherror
Next.js version:
16.2.6 (Turbopack)
```
Error นี้บ่งชี้ว่า Client ของ Auth.js คาดว่าจะได้รับ JSON แต่ Endpoint เช่น:
```text
/api/auth/session
```
กลับส่ง HTML Response เช่น:
```html
<!DOCTYPE html>
```
ซึ่งอาจเกิดจาก:
- Auth.js Route ไม่ทำงานหรืออยู่ผิดตำแหน่ง
- `/api/auth/session` ตอบกลับเป็น 404 หรือ 500
- Middleware Redirect `/api/auth/*` ไปหน้าล็อกอิน
- Auth.js Configuration Error
- Database หรือ Adapter Error
- Environment Variable ไม่ครบหรือไม่ถูกต้อง
- Custom Error Handler ส่ง HTML แทน JSON
- Reverse Proxy หรือ Application Redirect ทำให้ Auth API ถูกเปลี่ยนปลายทาง
- Client เรียก `getSession()` หรือ `useSession()` ขณะที่ Auth Route ล้มเหลว
- SessionProvider ถูกตั้งค่าผิดตำแหน่ง
- Error Boundary หรือ Route Handler จัดการ Error ไม่ถูกต้อง
---
# เป้าหมายหลัก
ดำเนินการให้ครบทั้ง 2 ส่วนดังนี้:
1. ตรวจสอบและแก้ไข Auth.js `ClientFetchError`
2. เพิ่มระบบ Session Inactivity Timeout เมื่อผู้ใช้งานไม่มีการเคลื่อนไหวต่อเนื่อง 5 นาที
---
# ส่วนที่ 1: ตรวจสอบและแก้ไข Auth.js ClientFetchError
## 1. ตรวจสอบโครงสร้าง Auth.js ปัจจุบัน
ตรวจสอบไฟล์ที่เกี่ยวข้องทั้งหมด เช่น:
```text
auth.ts
src/auth.ts
app/api/auth/[...nextauth]/route.ts
src/app/api/auth/[...nextauth]/route.ts
middleware.ts
src/middleware.ts
proxy.ts
src/proxy.ts
providers.tsx
session-provider.tsx
layout.tsx
.env
.env.local
next.config.ts
```
รวมถึงไฟล์ Authentication, Authorization และ Database Adapter ที่เกี่ยวข้อง
ห้ามสมมติชื่อไฟล์หรือโครงสร้าง ให้ค้นหาจากโครงการจริงก่อน
---
## 2. ตรวจสอบ Auth Route
ตรวจสอบว่า Auth.js Route อยู่ในตำแหน่งที่ถูกต้องสำหรับ App Router เช่น:
```text
src/app/api/auth/[...nextauth]/route.ts
```
และ Export Handler ถูกต้อง เช่น:
```ts
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
```
ตรวจสอบเพิ่มเติมว่า:
- Import path ถูกต้อง
- `handlers` ถูก Export จาก Auth configuration จริง
- ไม่มี Circular Dependency
- ไม่มี Route อื่นชนกับ `/api/auth/[...nextauth]`
- ไม่มี Rewrite หรือ Redirect ที่กระทบ Auth Route
---
## 3. ตรวจสอบ Auth.js Configuration
ตรวจสอบไฟล์ Auth configuration ว่ามีรูปแบบถูกต้อง เช่น:
```ts
import NextAuth from "next-auth";
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [],
});
```
ตรวจสอบ:
- Providers
- Credentials Provider
- Adapter
- Session Strategy
- JWT Callback
- Session Callback
- Authorized Callback
- Sign-in Page
- Error Page
- Environment Variables
- Database Connection
- Cookie Configuration
- Trust Host Configuration
- Base Path หากมีการตั้งค่า
หากมี Custom Adapter หรือ LDAP/Active Directory ให้ตรวจสอบ Error Handling ของส่วนนั้นด้วย
---
## 4. ตรวจสอบ Endpoint `/api/auth/session`
ทดสอบ Endpoint นี้โดยตรง:
```text
GET /api/auth/session
```
ผลลัพธ์ที่ถูกต้องต้องเป็น JSON และมี `Content-Type` เป็น:
```text
application/json
```
ตัวอย่างผลลัพธ์เมื่อยังไม่ได้เข้าสู่ระบบ:
```json
{}
```
หรือ Response ตามมาตรฐานของ Auth.js
ต้องไม่ตอบกลับเป็น:
- HTML
- หน้า Login
- หน้า 404
- หน้า Error ของ Next.js
- Redirect ไปหน้าอื่น
- Reverse Proxy Error Page
ให้ตรวจสอบ HTTP Status เช่น:
```text
200
302
307
401
404
500
```
และหาสาเหตุจาก Status ที่พบจริง
---
## 5. ตรวจสอบ Middleware หรือ Proxy
ตรวจสอบว่า Middleware หรือ Proxy ไม่ได้ดัก Route ต่อไปนี้:
```text
/api/auth
/api/auth/*
/_next/*
/favicon.ico
```
Auth.js API Route ต้องไม่ถูก Redirect ไปหน้าล็อกอิน
ปรับ Matcher ให้ยกเว้น Auth API และ Static Assets อย่างเหมาะสม เช่นแนวทาง:
```ts
export const config = {
matcher: ["/((?!api/auth|_next/static|_next/image|favicon.ico).*)"],
};
```
แต่ต้องปรับให้เข้ากับโครงสร้างจริงของโครงการ และต้องไม่ทำให้ Route Protection เดิมเสียหาย
หากโครงการใช้ `proxy.ts` ตามโครงสร้างของ Next.js รุ่นปัจจุบัน ให้ตรวจสอบไฟล์นั้นด้วย ไม่จำกัดเฉพาะ `middleware.ts`
---
## 6. ตรวจสอบ Environment Variables
ตรวจสอบ Environment Variables ที่เกี่ยวข้อง เช่น:
```text
AUTH_SECRET
AUTH_URL
NEXTAUTH_SECRET
NEXTAUTH_URL
DATABASE_URL
```
รวมถึง Environment Variables ของ:
- LDAP
- Active Directory
- OAuth Provider
- Database Adapter
- Reverse Proxy
- Internal API
ให้ใช้ชื่อตัวแปรตาม Version และโครงสร้าง Auth.js ที่โครงการใช้งานจริง
ห้ามเปิดเผย Secret ใน Log หรือ Commit
หาก Environment Variable ที่จำเป็นขาด ให้เพิ่มตัวอย่างใน:
```text
.env.example
```
โดยใช้ Placeholder เท่านั้น
---
## 7. ตรวจสอบ Server Error ที่แท้จริง
ตรวจสอบ Server Log และ Terminal Log ขณะที่เรียก:
```text
/api/auth/session
```
ค้นหา Root Cause เช่น:
- Database Connection Error
- Prisma Initialization Error
- LDAP Connection Error
- Provider Configuration Error
- Invalid Secret
- Callback Error
- JWT Decryption Error
- Cookie Parsing Error
- Runtime Compatibility Error
- Edge Runtime ไม่รองรับ Library บางตัว
- Node Runtime Configuration Error
ห้ามแก้ด้วยการซ่อน Error ฝั่ง Client เพียงอย่างเดียว ต้องแก้ Root Cause ที่ทำให้ Endpoint ส่ง HTML
---
## 8. ปรับปรุง Error Handling
ปรับปรุง Error Handling เพื่อให้:
- Auth API ไม่ส่ง HTML Response โดยไม่จำเป็น
- Client ไม่เกิด Unhandled Promise Rejection
- ไม่แสดง Stack Trace หรือข้อมูล Sensitive แก่ผู้ใช้งาน
- Server Log มีข้อมูลเพียงพอสำหรับ Debug
- Production แสดงข้อความที่เหมาะสม
- Development ยังสามารถตรวจสอบ Root Cause ได้
หาก `useSession()`, `getSession()`, `SessionProvider` หรือ Custom API Client มี Error Handling ไม่ครบ ให้ปรับปรุงด้วย
ห้ามใช้วิธีแก้แบบ:
```ts
try {
// ...
} catch {
return null;
}
```
หากทำให้ Root Cause ถูกซ่อนโดยไม่มี Logging ที่เหมาะสม
---
# ส่วนที่ 2: เพิ่มระบบ Session Inactivity Timeout 5 นาที
## ความต้องการ
เมื่อผู้ใช้งานเข้าสู่ระบบแล้ว หากไม่มีการเคลื่อนไหวหรือไม่มี Interaction กับระบบต่อเนื่องเป็นเวลา:
```text
5 นาที
```
ให้ระบบดำเนินการดังนี้:
1. แสดงข้อความแจ้งผู้ใช้งานว่า:
```text
คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่
```
2. ทำการ Sign out จาก Auth.js อย่างถูกต้อง
3. ล้าง Client State หรือข้อมูล Session ที่เกี่ยวข้อง
4. Redirect กลับไปหน้าล็อกอิน
5. ผู้ใช้งานต้องเข้าสู่ระบบใหม่ก่อนใช้งานระบบต่อ
6. ห้ามเกิด Redirect Loop
7. ห้ามกระทบผู้ใช้งานที่ยังมีการเคลื่อนไหวอยู่
---
## 1. นิยาม Activity ของผู้ใช้งาน
ให้ถือว่า Event ต่อไปนี้เป็น Activity:
```text
mousedown
mousemove
keydown
scroll
touchstart
click
focus
```
สามารถเลือกใช้เฉพาะ Event ที่เหมาะสมเพื่อไม่ให้เกิด Performance Issue
ต้องใช้ Event แบบ Throttle หรือ Debounce เพื่อไม่ให้ Reset Timer ถี่เกินไป โดยเฉพาะ:
```text
mousemove
scroll
```
---
## 2. เริ่มตรวจจับเฉพาะผู้ที่เข้าสู่ระบบแล้ว
ระบบ Inactivity Timeout ต้องทำงานเฉพาะเมื่อ:
```ts
status === "authenticated";
```
ห้ามเริ่ม Timer ในกรณี:
```ts
status === "loading";
status === "unauthenticated";
```
เมื่อผู้ใช้งาน Logout แล้ว ต้อง Cleanup:
- Timer
- Event Listener
- Storage Listener
- Broadcast Channel
- Pending Callback
ทั้งหมดอย่างถูกต้อง
---
## 3. ระยะเวลา Timeout
กำหนดค่ากลาง เช่น:
```ts
const INACTIVITY_TIMEOUT_MS = 5 * 60 * 1000;
```
ควรจัดเก็บไว้ใน Configuration หรือ Constant กลาง เพื่อให้เปลี่ยนภายหลังได้ง่าย
ห้ามกระจายค่า `300000` ไว้หลายจุดในระบบ
---
## 4. รูปแบบการแจ้งเตือน
เมื่อครบ 5 นาที ให้แสดง Dialog, AlertDialog, Modal หรือ Toast ตาม Component มาตรฐานของโครงการ
แนะนำให้ใช้:
```text
AlertDialog
```
ข้อความ:
```text
เซสชันหมดอายุ
```
รายละเอียด:
```text
คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่
```
ปุ่ม:
```text
เข้าสู่ระบบใหม่
```
เมื่อผู้ใช้งานกดปุ่ม ให้ Redirect ไปหน้าล็อกอิน
อย่างไรก็ตาม เพื่อความปลอดภัย ระบบต้อง Sign out และถือว่า Session หมดอายุทันทีเมื่อครบเวลา ไม่ควรรอให้ผู้ใช้งานกดปุ่มก่อนจึงค่อย Sign out
หากใช้ Toast ให้ตั้งระยะเวลาที่ผู้ใช้งานสามารถอ่านข้อความได้อย่างเหมาะสมก่อน Redirect
ห้ามใช้ Native Browser Alert หากโครงการมี UI Component มาตรฐานอยู่แล้ว
---
## 5. ลำดับการทำงานเมื่อหมดเวลา
ลำดับที่ต้องการ:
```text
ครบเวลาไม่มี Activity
ป้องกันการทำงานซ้ำด้วย Flag
หยุด Timer และถอด Event Listener
แสดงข้อความแจ้ง Session หมดอายุ
ล้างข้อมูล Client State ที่มีความ Sensitive
เรียก signOut ของ Auth.js
Redirect ไปหน้า Login
```
ตัวอย่างแนวทาง:
```ts
await signOut({
redirect: false,
});
router.replace("/login?reason=inactivity");
router.refresh();
```
ให้ปรับตาม Auth.js API และโครงสร้างจริงของโครงการ
หากจำเป็นต้องแสดงข้อความหลัง Redirect ให้ส่ง Query Parameter เช่น:
```text
/login?reason=inactivity
```
จากนั้นหน้า Login แสดงข้อความ:
```text
คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่
```
ต้องลบหรือ Replace URL อย่างเหมาะสมหลังแสดงข้อความ เพื่อไม่ให้ข้อความแสดงซ้ำเมื่อ Refresh โดยไม่จำเป็น
---
## 6. รองรับหลาย Tab
ระบบควรรองรับกรณีเปิดหลาย Browser Tab
เมื่อผู้ใช้งานมี Activity ใน Tab หนึ่ง ควร Sync `lastActivity` ให้ Tab อื่นรับรู้ เพื่อไม่ให้ Tab อื่น Logout ผู้ใช้งานผิดพลาด
สามารถใช้:
```text
localStorage
storage event
BroadcastChannel
```
แนวทางที่แนะนำ:
```text
auth:last-activity
auth:session-expired
```
ข้อกำหนด:
- Activity จาก Tab หนึ่งต้องอัปเดตเวลาให้ Tab อื่น
- เมื่อ Session หมดอายุใน Tab หนึ่ง Tab อื่นต้อง Logout ตาม
- ป้องกันหลาย Tab เรียก `signOut()` พร้อมกันจำนวนมาก
- Cleanup Channel และ Listener เมื่อ Component Unmount
- ต้องตรวจสอบการทำงานใน Browser ที่ไม่รองรับ `BroadcastChannel`
---
## 7. ห้ามใช้เฉพาะ Client Timer เป็น Security Control
Client-side inactivity timer เป็นส่วนของ UX เท่านั้น
ต้องตรวจสอบ Session Configuration ฝั่ง Server ร่วมด้วย เช่น:
- JWT expiration
- Session maxAge
- Cookie expiration
- Server-side authorization
- Permission validation ใน Protected Route
- API Route ต้องตรวจ Session ทุกครั้ง
ห้ามถือว่าผู้ใช้หมดสิทธิ์เพียงเพราะ Client Redirect แล้วเท่านั้น
อย่างไรก็ตาม ระยะเวลาหมดอายุฝั่ง Server ไม่จำเป็นต้องเท่ากับ Inactivity Timeout 5 นาที หากระบบต้องรองรับ Sliding Session แต่ต้องอธิบายความแตกต่างไว้ใน Implementation Report
---
## 8. ระวังการสูญหายของข้อมูลใน Form
ตรวจสอบว่าหน้าใดมี Form ที่ผู้ใช้งานอาจกำลังกรอกข้อมูล
เมื่อ Session หมดอายุ:
- ต้องไม่พยายามบันทึกข้อมูลหลังหมด Session
- ต้องไม่เกิด API Request ด้วย Session ที่หมดอายุ
- ต้องไม่เก็บข้อมูล Sensitive ไว้ใน Local Storage โดยไม่จำเป็น
- สามารถแจ้งข้อความว่าข้อมูลที่ยังไม่ได้บันทึกอาจสูญหายได้ หากเหมาะสม
ไม่ต้องเพิ่มระบบ Auto Save เว้นแต่โครงการมีอยู่แล้ว
---
# สถาปัตยกรรมที่แนะนำ
สร้าง Component หรือ Hook กลาง เช่น:
```text
src/components/auth/session-inactivity-guard.tsx
```
หรือ:
```text
src/hooks/use-session-inactivity.ts
```
แล้วนำไปติดตั้งในตำแหน่งที่ครอบคลุมเฉพาะ Protected Area เช่น:
```text
src/app/dashboard/layout.tsx
```
หรือ Protected Layout ที่มีอยู่จริง
ไม่ควรติดตั้งใน Root Layout หากทำให้หน้า Login เริ่มจับเวลาโดยไม่จำเป็น
ตัวอย่างโครงสร้าง:
```text
Protected Layout
├── SessionProvider
├── SessionInactivityGuard
└── Protected Page Content
```
ให้ใช้ Provider และ Layout เดิมของโครงการ หากมีอยู่แล้ว
---
# ข้อกำหนดด้าน UX
## ข้อความภาษาไทย
หัวข้อ:
```text
เซสชันหมดอายุ
```
รายละเอียด:
```text
คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่
```
ปุ่ม:
```text
เข้าสู่ระบบใหม่
```
กรณี Redirect ไปหน้า Login โดยตรง ให้หน้า Login แสดงข้อความ:
```text
คุณไม่ได้ใช้งานระบบเป็นเวลานาน กรุณาเข้าสู่ระบบใหม่
```
---
# ข้อกำหนดด้านความปลอดภัย
- ห้าม Log Token
- ห้าม Log Cookie
- ห้าม Log Password
- ห้าม Log LDAP Credential
- ห้ามเปิดเผย Environment Secret
- ห้ามเก็บ Access Token ใน Local Storage หากระบบเดิมไม่ได้ออกแบบเช่นนั้น
- API และ Server Action ต้องตรวจ Session ฝั่ง Server
- Protected Route ต้องไม่พึ่ง Client Guard เพียงอย่างเดียว
- ป้องกัน Open Redirect
- Redirect URL ต้องเป็น Internal Path ที่กำหนดไว้
- ป้องกันการเรียก Logout ซ้ำ
- ป้องกัน Redirect Loop ระหว่าง Login และ Protected Route
---
# Test Cases ที่ต้องตรวจสอบ
## Auth.js Error
### TC-AUTH-001
เปิด:
```text
/api/auth/session
```
ผลลัพธ์ที่คาดหวัง:
- HTTP Status ถูกต้อง
- Response เป็น JSON
- `Content-Type` เป็น JSON
- ไม่มี HTML Response
### TC-AUTH-002
เปิดหน้า Protected Route ขณะยังไม่เข้าสู่ระบบ
ผลลัพธ์ที่คาดหวัง:
- Redirect ไปหน้า Login อย่างถูกต้อง
- `/api/auth/session` ไม่ถูก Middleware Redirect
- ไม่เกิด `Unexpected token '<'`
### TC-AUTH-003
เข้าสู่ระบบสำเร็จ
ผลลัพธ์ที่คาดหวัง:
- `useSession()` ได้สถานะ `authenticated`
- ไม่มี `ClientFetchError`
- Session โหลดได้ตามปกติ
### TC-AUTH-004
Database หรือ LDAP ไม่พร้อมใช้งาน
ผลลัพธ์ที่คาดหวัง:
- Server มี Error Log ที่เหมาะสม
- Client ไม่เกิด Unhandled Error
- ผู้ใช้งานได้รับข้อความที่เหมาะสม
- ไม่มีข้อมูล Sensitive ถูกเปิดเผย
---
## Session Inactivity Timeout
### TC-IDLE-001
เข้าสู่ระบบและไม่มี Activity 5 นาที
ผลลัพธ์ที่คาดหวัง:
- แสดงข้อความ Session หมดอายุ
- Sign out สำเร็จ
- Redirect ไปหน้า Login
- ต้อง Login ใหม่
### TC-IDLE-002
มี Activity ก่อนครบ 5 นาที
ผลลัพธ์ที่คาดหวัง:
- Timer ถูก Reset
- ผู้ใช้งานไม่ถูก Logout
### TC-IDLE-003
มี Activity ต่อเนื่อง
ผลลัพธ์ที่คาดหวัง:
- ระบบไม่ Logout
- ไม่มี Memory Leak
- ไม่มี Timer ถูกสร้างซ้ำ
### TC-IDLE-004
เปิดระบบหลาย Tab และใช้งานอยู่ใน Tab หนึ่ง
ผลลัพธ์ที่คาดหวัง:
- Activity Sync ไปยัง Tab อื่น
- Tab อื่นไม่ Logout ผู้ใช้งานผิดพลาด
### TC-IDLE-005
Session หมดอายุใน Tab หนึ่ง
ผลลัพธ์ที่คาดหวัง:
- ทุก Tab รับรู้ว่า Session หมดอายุ
- ทุก Tab กลับหน้า Login
- ไม่เรียก Sign out ซ้ำอย่างผิดปกติ
### TC-IDLE-006
Logout ด้วยตนเองก่อนครบเวลา
ผลลัพธ์ที่คาดหวัง:
- Timer และ Event Listener ถูก Cleanup
- ไม่แสดงข้อความ Inactivity ภายหลัง
### TC-IDLE-007
Refresh หน้าใกล้ครบเวลา
ผลลัพธ์ที่คาดหวัง:
- ระบบอ่าน `lastActivity` ที่เหมาะสม
- ไม่ Reset Timeout อย่างไม่ถูกต้อง หากไม่มี Activity จริง
- ไม่ Logout ซ้ำ
### TC-IDLE-008
อยู่หน้า Login
ผลลัพธ์ที่คาดหวัง:
- ไม่มี Inactivity Timer ทำงาน
- ไม่มี Redirect Loop
- ไม่มีข้อความหมดอายุแสดงซ้ำโดยไม่จำเป็น
### TC-IDLE-009
ผู้ใช้งานกำลังกรอก Form แต่ไม่มี Mouse หรือ Keyboard Activity เกิน 5 นาที
ผลลัพธ์ที่คาดหวัง:
- Session หมดอายุตามข้อกำหนด
- ระบบแจ้งเตือนอย่างชัดเจน
- ไม่มีการส่ง Form หลัง Session หมดอายุ
---
# Quality Gate
ก่อนจบงานต้องดำเนินการ:
```bash
npm run lint
npm run typecheck
npm run build
```
หรือใช้คำสั่งที่มีอยู่จริงใน `package.json`
ต้องแก้ไข:
- TypeScript Error
- ESLint Error
- Build Error
- Import Error
- Hydration Error
- Unhandled Promise Rejection
- Memory Leak จาก Timer หรือ Event Listener
ห้ามปิด Rule หรือใช้:
```ts
any
@ts-ignore
eslint-disable
```
โดยไม่มีเหตุผลที่จำเป็นและมีคำอธิบาย
---
# ข้อจำกัดในการแก้ไข
- รักษาโครงสร้างและ Coding Convention เดิม
- ใช้ Component มาตรฐานที่โครงการมีอยู่แล้ว
- ไม่สร้าง Auth Provider ซ้ำ
- ไม่เปลี่ยน Authentication Flow โดยไม่จำเป็น
- ไม่ลบ Permission หรือ Route Protection เดิม
- ไม่ Hardcode Domain
- ไม่ Hardcode Secret
- ไม่ Hardcode Login URL หลายตำแหน่ง
- ไม่เปลี่ยน Session Strategy หากไม่มีเหตุผลรองรับ
- ไม่แก้เฉพาะอาการโดยละเลย Root Cause
- ห้ามทำให้ `/api/auth/session` ถูก Redirect ไปหน้า Login
---
# ผลลัพธ์ที่ต้องส่งมอบ
หลังดำเนินการเสร็จ ให้จัดทำรายงานสรุป Markdown โดยประกอบด้วย:
## 1. Root Cause
ระบุสาเหตุจริงของ:
```text
Unexpected token '<', "<!DOCTYPE "... is not valid JSON
```
พร้อมระบุว่า HTML Response มาจาก:
- Route ใด
- HTTP Status ใด
- Middleware, Server Error หรือ Configuration ส่วนใด
## 2. Files Changed
ระบุรายการไฟล์ที่:
- เพิ่มใหม่
- แก้ไข
- ลบ
พร้อมสรุปหน้าที่ของแต่ละไฟล์
## 3. Auth.js Fix
อธิบาย:
- สิ่งที่ผิด
- วิธีแก้
- เหตุผลที่วิธีใหม่ถูกต้อง
- ผลทดสอบ `/api/auth/session`
## 4. Inactivity Timeout Implementation
อธิบาย:
- จุดที่ติดตั้ง Guard
- Event ที่ใช้ตรวจ Activity
- วิธี Reset Timer
- วิธี Logout
- วิธี Redirect
- วิธีรองรับหลาย Tab
- วิธี Cleanup
## 5. Security Notes
อธิบาย:
- Client Timeout
- Server Session Expiration
- Protected API
- Cookie และ Token Handling
- ข้อจำกัดที่ยังเหลืออยู่
## 6. Test Results
สรุปผล:
```text
Lint
Typecheck
Build
Manual Test
Auth Session Endpoint Test
Multi-tab Test
Inactivity Test
```
## 7. Remaining Risks
หากยังมีข้อจำกัดหรือสิ่งที่ต้องดำเนินการต่อ ให้ระบุอย่างตรงไปตรงมา ห้ามรายงานว่าสำเร็จหากยังไม่ได้ทดสอบจริง
---
# Acceptance Criteria
งานถือว่าเสร็จสมบูรณ์เมื่อ:
- ไม่เกิด `ClientFetchError`
- ไม่เกิด `Unexpected token '<'`
- `/api/auth/session` ตอบกลับเป็น JSON
- Middleware ไม่ Redirect Auth API
- ผู้ใช้เข้าสู่ระบบได้ตามปกติ
- ผู้ใช้ที่ไม่มี Activity ครบ 5 นาทีถูก Sign out
- มีข้อความแจ้งว่าไม่ได้ใช้งานระบบเป็นเวลานาน
- Redirect กลับหน้า Login สำเร็จ
- ต้องเข้าสู่ระบบใหม่
- Activity ก่อนครบเวลาสามารถ Reset Timer ได้
- รองรับหลาย Tab
- ไม่มี Redirect Loop
- ไม่มี Timer หรือ Event Listener ค้าง
- Protected API ยังตรวจสอบ Session ฝั่ง Server
- Lint, Typecheck และ Build ผ่าน
- มี Implementation Report สรุป Root Cause และการแก้ไข