Files
alla-tms/plans/fix-auth-client-fetch-error-and-session-inactivity-timeout.md
2026-07-16 09:53:14 +07:00

30 KiB

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 ดังนี้:

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 เช่น:

/api/auth/session

กลับส่ง HTML Response เช่น:

<!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 ปัจจุบัน

ตรวจสอบไฟล์ที่เกี่ยวข้องทั้งหมด เช่น:

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 เช่น:

src/app/api/auth/[...nextauth]/route.ts

และ Export Handler ถูกต้อง เช่น:

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 ว่ามีรูปแบบถูกต้อง เช่น:

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 นี้โดยตรง:

GET /api/auth/session

ผลลัพธ์ที่ถูกต้องต้องเป็น JSON และมี Content-Type เป็น:

application/json

ตัวอย่างผลลัพธ์เมื่อยังไม่ได้เข้าสู่ระบบ:

{}

หรือ Response ตามมาตรฐานของ Auth.js

ต้องไม่ตอบกลับเป็น:

  • HTML
  • หน้า Login
  • หน้า 404
  • หน้า Error ของ Next.js
  • Redirect ไปหน้าอื่น
  • Reverse Proxy Error Page

ให้ตรวจสอบ HTTP Status เช่น:

200
302
307
401
404
500

และหาสาเหตุจาก Status ที่พบจริง


5. ตรวจสอบ Middleware หรือ Proxy

ตรวจสอบว่า Middleware หรือ Proxy ไม่ได้ดัก Route ต่อไปนี้:

/api/auth
/api/auth/*
/_next/*
/favicon.ico

Auth.js API Route ต้องไม่ถูก Redirect ไปหน้าล็อกอิน

ปรับ Matcher ให้ยกเว้น Auth API และ Static Assets อย่างเหมาะสม เช่นแนวทาง:

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 ที่เกี่ยวข้อง เช่น:

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 ที่จำเป็นขาด ให้เพิ่มตัวอย่างใน:

.env.example

โดยใช้ Placeholder เท่านั้น


7. ตรวจสอบ Server Error ที่แท้จริง

ตรวจสอบ Server Log และ Terminal Log ขณะที่เรียก:

/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 ไม่ครบ ให้ปรับปรุงด้วย

ห้ามใช้วิธีแก้แบบ:

try {
  // ...
} catch {
  return null;
}

หากทำให้ Root Cause ถูกซ่อนโดยไม่มี Logging ที่เหมาะสม


ส่วนที่ 2: เพิ่มระบบ Session Inactivity Timeout 5 นาที

ความต้องการ

เมื่อผู้ใช้งานเข้าสู่ระบบแล้ว หากไม่มีการเคลื่อนไหวหรือไม่มี Interaction กับระบบต่อเนื่องเป็นเวลา:

5 นาที

ให้ระบบดำเนินการดังนี้:

  1. แสดงข้อความแจ้งผู้ใช้งานว่า:
คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่
  1. ทำการ Sign out จาก Auth.js อย่างถูกต้อง
  2. ล้าง Client State หรือข้อมูล Session ที่เกี่ยวข้อง
  3. Redirect กลับไปหน้าล็อกอิน
  4. ผู้ใช้งานต้องเข้าสู่ระบบใหม่ก่อนใช้งานระบบต่อ
  5. ห้ามเกิด Redirect Loop
  6. ห้ามกระทบผู้ใช้งานที่ยังมีการเคลื่อนไหวอยู่

1. นิยาม Activity ของผู้ใช้งาน

ให้ถือว่า Event ต่อไปนี้เป็น Activity:

mousedown
mousemove
keydown
scroll
touchstart
click
focus

สามารถเลือกใช้เฉพาะ Event ที่เหมาะสมเพื่อไม่ให้เกิด Performance Issue

ต้องใช้ Event แบบ Throttle หรือ Debounce เพื่อไม่ให้ Reset Timer ถี่เกินไป โดยเฉพาะ:

mousemove
scroll

2. เริ่มตรวจจับเฉพาะผู้ที่เข้าสู่ระบบแล้ว

ระบบ Inactivity Timeout ต้องทำงานเฉพาะเมื่อ:

status === "authenticated";

ห้ามเริ่ม Timer ในกรณี:

status === "loading";
status === "unauthenticated";

เมื่อผู้ใช้งาน Logout แล้ว ต้อง Cleanup:

  • Timer
  • Event Listener
  • Storage Listener
  • Broadcast Channel
  • Pending Callback

ทั้งหมดอย่างถูกต้อง


3. ระยะเวลา Timeout

กำหนดค่ากลาง เช่น:

const INACTIVITY_TIMEOUT_MS = 5 * 60 * 1000;

ควรจัดเก็บไว้ใน Configuration หรือ Constant กลาง เพื่อให้เปลี่ยนภายหลังได้ง่าย

ห้ามกระจายค่า 300000 ไว้หลายจุดในระบบ


4. รูปแบบการแจ้งเตือน

เมื่อครบ 5 นาที ให้แสดง Dialog, AlertDialog, Modal หรือ Toast ตาม Component มาตรฐานของโครงการ

แนะนำให้ใช้:

AlertDialog

ข้อความ:

เซสชันหมดอายุ

รายละเอียด:

คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่

ปุ่ม:

เข้าสู่ระบบใหม่

เมื่อผู้ใช้งานกดปุ่ม ให้ Redirect ไปหน้าล็อกอิน

อย่างไรก็ตาม เพื่อความปลอดภัย ระบบต้อง Sign out และถือว่า Session หมดอายุทันทีเมื่อครบเวลา ไม่ควรรอให้ผู้ใช้งานกดปุ่มก่อนจึงค่อย Sign out

หากใช้ Toast ให้ตั้งระยะเวลาที่ผู้ใช้งานสามารถอ่านข้อความได้อย่างเหมาะสมก่อน Redirect

ห้ามใช้ Native Browser Alert หากโครงการมี UI Component มาตรฐานอยู่แล้ว


5. ลำดับการทำงานเมื่อหมดเวลา

ลำดับที่ต้องการ:

ครบเวลาไม่มี Activity
    ↓
ป้องกันการทำงานซ้ำด้วย Flag
    ↓
หยุด Timer และถอด Event Listener
    ↓
แสดงข้อความแจ้ง Session หมดอายุ
    ↓
ล้างข้อมูล Client State ที่มีความ Sensitive
    ↓
เรียก signOut ของ Auth.js
    ↓
Redirect ไปหน้า Login

ตัวอย่างแนวทาง:

await signOut({
  redirect: false,
});

router.replace("/login?reason=inactivity");
router.refresh();

ให้ปรับตาม Auth.js API และโครงสร้างจริงของโครงการ

หากจำเป็นต้องแสดงข้อความหลัง Redirect ให้ส่ง Query Parameter เช่น:

/login?reason=inactivity

จากนั้นหน้า Login แสดงข้อความ:

คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่

ต้องลบหรือ Replace URL อย่างเหมาะสมหลังแสดงข้อความ เพื่อไม่ให้ข้อความแสดงซ้ำเมื่อ Refresh โดยไม่จำเป็น


6. รองรับหลาย Tab

ระบบควรรองรับกรณีเปิดหลาย Browser Tab

เมื่อผู้ใช้งานมี Activity ใน Tab หนึ่ง ควร Sync lastActivity ให้ Tab อื่นรับรู้ เพื่อไม่ให้ Tab อื่น Logout ผู้ใช้งานผิดพลาด

สามารถใช้:

localStorage
storage event
BroadcastChannel

แนวทางที่แนะนำ:

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 กลาง เช่น:

src/components/auth/session-inactivity-guard.tsx

หรือ:

src/hooks/use-session-inactivity.ts

แล้วนำไปติดตั้งในตำแหน่งที่ครอบคลุมเฉพาะ Protected Area เช่น:

src/app/dashboard/layout.tsx

หรือ Protected Layout ที่มีอยู่จริง

ไม่ควรติดตั้งใน Root Layout หากทำให้หน้า Login เริ่มจับเวลาโดยไม่จำเป็น

ตัวอย่างโครงสร้าง:

Protected Layout
 ├── SessionProvider
 ├── SessionInactivityGuard
 └── Protected Page Content

ให้ใช้ Provider และ Layout เดิมของโครงการ หากมีอยู่แล้ว


ข้อกำหนดด้าน UX

ข้อความภาษาไทย

หัวข้อ:

เซสชันหมดอายุ

รายละเอียด:

คุณไม่ได้ใช้งานระบบเป็นเวลานาน เซสชันของคุณหมดอายุแล้ว กรุณาเข้าสู่ระบบใหม่

ปุ่ม:

เข้าสู่ระบบใหม่

กรณี Redirect ไปหน้า Login โดยตรง ให้หน้า Login แสดงข้อความ:

คุณไม่ได้ใช้งานระบบเป็นเวลานาน กรุณาเข้าสู่ระบบใหม่

ข้อกำหนดด้านความปลอดภัย

  • ห้าม 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

เปิด:

/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

ก่อนจบงานต้องดำเนินการ:

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 หรือใช้:

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

ระบุสาเหตุจริงของ:

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

สรุปผล:

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 และการแก้ไข