มหาวิทยาลัยตาปีTapee Oneมหาวิทยาลัยตาปีกลับ Tapee One
AI & Developer Guide

เชื่อมโปรแกรมของคุณ
กับ Tapee One

ปรับโปรแกรมเดิมหรือสร้างใหม่ ให้ใช้บัญชีและสิทธิ์จากศูนย์กลางบริการบุคลากร

ส่งลิงก์นี้ให้ AI เริ่มทำงานได้เลย

https://one.tapee.ac.th/developers/ai-guide.md

อ่านได้โดยไม่ต้อง Login · ไม่ต้องส่ง Client Secret ให้ AI · สัญญาเฉพาะแพลตฟอร์ม

เวอร์ชันเอกสาร 2026-10-21 · อ้างอิง implementation ปัจจุบันของ one.tapee.ac.th

คู่มือนี้ใช้กับ AI coding agent และผู้พัฒนาที่จะปรับโปรแกรมเดิมหรือสร้างโปรแกรมใหม่ของมหาวิทยาลัยตาปี ให้เข้าสู่ระบบและตรวจสิทธิ์ผ่าน Tapee One ใช้อ่านร่วมกับ source ของโปรแกรมปลายทางก่อนเริ่มแก้ไข ไม่ต้องส่งข้อมูลรับรองจริงให้ AI อ่านเอกสารนี้

1. เริ่มต้นจากลิงก์เหล่านี้

เอกสารเหล่านี้เป็นข้อมูลสาธารณะ ไม่มี Client Secret, Bot Token, ข้อมูลบุคลากร หรือค่าตั้งค่า production ปุ่ม Login และ API ที่ป้องกันยังต้องใช้การยืนยันตัวตนตามปกติ

2. Prompt ที่นำไปใช้กับ AI ในโปรเจกต์อื่นได้

คัดลอกข้อความด้านล่าง แล้วเติมชื่อโปรแกรมและเส้นทางโปรเจกต์:

ให้ปรับโปรแกรม [ชื่อโปรแกรม] ใน [เส้นทาง source] ให้ใช้ Tapee One SSO
อ่าน https://one.tapee.ac.th/developers/ai-guide.md และ
https://one.tapee.ac.th/developers/contract.json ก่อนเริ่ม
ตรวจ stack, route, middleware, user model, role และการ deploy ของโปรเจกต์จริง
เก็บ Client ID/Secret ฝั่ง server เท่านั้น ห้ามใส่ค่าลับใน prompt, Git หรือ frontend
รองรับ callback start=1, browser-bound state, one-time code exchange
และ introspection ก่อนทุก protected request โดย fail closed หากตรวจสิทธิ์ไม่ได้
ผูกบัญชีเดิมอัตโนมัติด้วย email ที่ยืนยันแล้วจาก introspection เมื่ออีเมลตรงเพียงบัญชีเดียว
บันทึก issuer+sub จับคู่บัญชีถาวร รักษาข้อมูลและสิทธิ์เดิม ห้ามตั้งทุกคนเป็น Admin
คง Login ตรงด้วยอีเมล/รหัสผ่านหรือ Google ของโปรแกรมเดิมไว้ควบคู่ One
ตรวจ introspection เฉพาะเซสชันที่เข้าโดย One ไม่ fallback จาก SSO ที่ล้มเหลวเป็น local session
เพิ่ม tests สำหรับการเข้าตรง การระงับ การหมดอายุ state ผิด และระบบกลางล่ม
ส่งรายการไฟล์ที่แก้ วิธีตั้งค่า วิธีทดสอบ และ rollback plan
ก่อน deploy ต้องสำรอง source ไป Git และตรวจ remote สำเร็จก่อน
อย่าระบุว่าเชื่อมจริงสำเร็จจนทดสอบกับบัญชีและโปรแกรมที่ได้รับอนุญาตแล้ว

สำหรับโปรแกรมใหม่ ให้เพิ่มข้อกำหนด: สร้าง backend/BFF สำหรับ SSO, ใช้ session ของแอป, กำหนดสิทธิ์ภายในแอป, สร้างหน้าไม่มีสิทธิ์และระบบกลางไม่พร้อม พร้อมคู่มือติดตั้ง ค่าเริ่มต้นต้องไม่ให้สิทธิ์พิเศษ

3. สิ่งที่ระบบรองรับจริง

Tapee One เป็นศูนย์กลางบุคลากร Google Workspace @tapee.ac.th และสิทธิ์เปิดใช้โปรแกรม ใช้ SSO แบบ confidential backend เฉพาะแพลตฟอร์ม: authorization code + token exchange + introspection

  • ยังไม่ใช่ OAuth 2.0 / OpenID Connect / SAML provider มาตรฐานครบชุด
  • ไม่มี discovery endpoint, JWKS, ID token, JWT signature verification, refresh token หรือ scopes แบบมาตรฐาน ให้ใช้ endpoint และ payload ในคู่มือนี้เท่านั้น
  • Token เป็น opaque string ไม่ใช่ JWT ห้าม decode แล้วเชื่อข้อมูลโดยไม่ introspect
  • โปรแกรมที่มีเฉพาะ static frontend / SPA ต้องเพิ่ม backend หรือ BFF ที่เก็บ Secret และ session ได้ก่อน ห้ามใส่ Secret ลง JavaScript หรือเรียก token/introspect จากเบราว์เซอร์
  • ไม่ต้องคัดลอกรหัสผ่าน Google ไม่ต้องแชร์ Google OAuth Secret หรือ Telegram Bot Token ให้แต่ละโปรแกรม และไม่ต้องแชร์ session cookie ข้าม subdomain
  • การเพิ่มรายการโปรแกรมใน One อย่างเดียวไม่ทำให้โปรแกรมเดิมรองรับ SSO ต้องปรับ backend และทดสอบจริงด้วย
  • One เป็นช่องทางเพิ่มเติม ต้องคง Login ตรงด้วยอีเมล/รหัสผ่านและ Google เดิมตามที่โปรแกรมรองรับไว้ แม้บัญชีผูกกับ One แล้ว ไม่บังคับให้ทุกเซสชันผ่าน One

4. ข้อมูลที่ต้องเตรียมและลงทะเบียน

ผู้พัฒนาตรวจ repository ของโปรแกรมปลายทาง แล้วกำหนดชื่อโปรแกรม stack backend URL production และ callback route เช่น https://your-app.tapee.ac.th/auth/tapee-one/callback ซึ่งเป็นตัวอย่าง ไม่ใช่ URL โปรแกรมที่ลงทะเบียนแล้ว

Admin ของ One เปิดเมนู จัดการโปรแกรม ที่ https://one.tapee.ac.th/admin/programs เพิ่มโปรแกรม ระบุ HTTPS callback ของ backend เปิดใช้งาน และเลือกเปิดรับคำขอตามนโยบาย ระบบสร้าง Client ID และ Client Secret ซึ่งแสดงครั้งเดียว เก็บผ่านช่องทางลับของ deployment เท่านั้น

ตัวแปรของโปรแกรมปลายทาง (ตัวอย่าง ไม่มีค่ารับรองจริง):

ONE_ISSUER=https://one.tapee.ac.th
ONE_CLIENT_ID=
ONE_CLIENT_SECRET=
  • ตั้ง issuer จาก server config ที่เชื่อถือได้ ห้ามรับ host/endpoint จาก query ของผู้ใช้
  • callback ใช้ URL ที่ Admin ลงทะเบียนไว้ ระบบกลางไม่รับ redirect_uri จาก request เพื่อเปลี่ยนปลายทาง ผู้ใช้ต้องไม่ควบคุม callback URL
  • callback route ควรไม่มี query string เดิม โดยเฉพาะชื่อ start, code, state เพื่อไม่ให้ชนกับพารามิเตอร์ SSO
  • กำหนดสิทธิ์โปรแกรมให้บัญชีทดสอบหรือกลุ่มที่ได้รับอนุญาตก่อนทดสอบ
  • Secret ของแต่ละโปรแกรมแยกกัน ไม่ใช้ Client ของอีกโปรแกรมแทน ไม่เชื่อมฐานข้อมูลของ One โดยตรง

5. ลำดับ Login และการตรวจสิทธิ์

  1. ผู้ใช้ Login ที่ https://one.tapee.ac.th ผ่าน Google แล้วเลือกโปรแกรมที่มีสิทธิ์ One ตรวจสิทธิ์ที่ POST /programs/{id}/launch แล้วตอบหน้า HTML ภายใน One (HTTP 200) เพื่อจบการส่งฟอร์ม โดยคง CSP form-action self ไว้ (route นี้ใช้ session/CSRF ของ One ไม่ใช่ API สำหรับปลายทาง)
  2. หน้าเปิดโปรแกรมใช้ JavaScript ที่โฮสต์ใน One นำเบราว์เซอร์ไป callback ที่ลงทะเบียนด้วย top-level GET พร้อม start=1 มีลิงก์ให้กดต่อได้หาก JavaScript ปิดอยู่ โปรแกรมปลายทางสร้าง cryptographically random state อย่างน้อย 32 ตัวอักษร เก็บพร้อมเวลาหมดอายุใน server session ของเบราว์เซอร์นั้น
  3. ปลายทาง redirect ไป GET https://one.tapee.ac.th/sso/authorize?client_id=...&state=...
  4. One ตรวจบัญชีและสิทธิ์ปัจจุบัน แล้ว redirect กลับ callback เดิมพร้อม code และ state
  5. ปลายทางตรวจ state แบบ timing-safe ให้ตรงกับ session และยังไม่หมดอายุ แล้วลบทิ้ง ใช้ code จาก callback แลก token ด้วย backend POST เพียงครั้งเดียว
  6. หลังแลกสำเร็จ ให้ introspect token เพื่อตรวจตัวตน/สิทธิ์ก่อนสร้าง local authenticated session จากนั้น regenerate session ID เก็บ token ฝั่ง server แล้ว redirect ไปหน้า URL สะอาด ไม่มี code/state
  7. ทุกคำขอที่ป้องกันของเซสชันที่ Login ผ่าน One รวมหน้าเว็บ API export download งานเปลี่ยนข้อมูล และการเข้าจากลิงก์ตรง ต้องผ่าน server middleware ที่ introspect token และยอมรับเฉพาะ boolean active === true เซสชันที่ Login ตรงใช้การตรวจบัญชี บทบาท และสิทธิ์เดิมของโปรแกรม
  8. ถ้า active=false ให้ล้าง local SSO session และแสดงว่าไม่มีสิทธิ์หรือหมดอายุ เมื่อระบบกลางหรือการตรวจ SSO ไม่พร้อมให้หยุด protected action และตอบ 503 ห้ามใช้สถานะอนุญาตเก่าต่อ

สถานะ Login อยู่ใน session ของแต่ละระบบ ปัจจุบันถ้ายังไม่ Login ที่ One การเข้าหน้า authorize จะถูกส่งไปหน้า Login และ Google Login กลับหน้าหลัก One จึงควร Login ที่ One แล้วกดเลือกโปรแกรมใหม่ อย่าสัญญาว่าการเริ่มจากลิงก์ปลายทางที่ยังไม่มี One session จะกลับเข้าโปรแกรมอัตโนมัติครบทุกกรณี

State ต้องไม่คงที่ ไม่เก็บแค่ใน cookie ที่แก้เองได้ หรือรับจากผู้ใช้โดยไม่ผูก session ตัวอย่าง PHP รองรับหนึ่ง login ที่รอดำเนินการต่อ session หากต้องรองรับหลายแท็บพร้อมกัน ให้เก็บ state หลายรายการแบบจำกัดจำนวน/อายุและ consume เฉพาะรายการนั้น

6. สัญญา API ที่ต้องใช้ตรงตามนี้

6.1 Authorize ผ่านเบราว์เซอร์

GET https://one.tapee.ac.th/sso/authorize

พารามิเตอร์ กติกา
client_id string ไม่เกิน 100 ตัวอักษร จากการลงทะเบียน
state 32–128 ตัวอักษร อนุญาต A–Z, a–z, 0–9, underscore, hyphen

ต้องมี session ของ One ที่ active และสิทธิ์ใช้โปรแกรม ถ้าสำเร็จตอบ redirect ไป callback ที่ลงทะเบียนพร้อม code (64 ตัวอักษร อายุ 60 วินาที) และ state เดิม ไม่มีการส่ง token ใน authorize response

6.2 แลก Code ด้วย backend

POST https://one.tapee.ac.th/api/sso/token

ส่ง Accept: application/json และ body แบบ application/x-www-form-urlencoded หรือ JSON โดยมี client_id, client_secret, code ห้ามส่ง Secret ใน URL

ตัวอย่าง body แบบ JSON ที่ใช้ placeholder:

{
  "client_id": "<registered-client-id>",
  "client_secret": "<server-secret>",
  "code": "<one-time-code-from-callback>"
}

สำเร็จ HTTP 200:

{
  "access_token": "<opaque-access-token>",
  "token_type": "Bearer",
  "expires_in": 3600
}

Token อายุ 1 ชั่วโมงนับจากเวลาออก Token ส่วน code แลกได้ครั้งเดียวและเฉพาะ Client ที่ออกให้ หากคำขอแลก code timeout และไม่ทราบผล ให้เริ่ม Login ด้วย state/code ใหม่ ไม่ retry code เดิมวนซ้ำ ตัว API นี้ไม่มี grant_type, code_verifier, refresh token หรือ standard OAuth error schema

6.3 ตรวจ Token และสิทธิ์ด้วย backend

POST https://one.tapee.ac.th/api/sso/introspect

ส่ง client_id, client_secret, token ใน body พร้อม Accept: application/json ใช้ค่า token จาก server session ไม่รับ token จาก query ของผู้ใช้ เส้นทางนี้ใช้ body parameters ไม่ได้ยืนยัน Client ด้วยเพียง Authorization: Bearer

สำเร็จและยังมีสิทธิ์ HTTP 200:

{
  "active": true,
  "sub": "123",
  "name": "Example Staff",
  "email": "example@tapee.ac.th",
  "email_verified": true,
  "program_id": 7,
  "exp": 1800000000
}

ค่าด้านบนเป็นตัวอย่าง sub เป็น string รหัสบุคลากรภายใน One, program_id เป็นรหัสโปรแกรมของ Client นี้, exp เป็น Unix timestamp จริงของ token ห้าม hardcode ค่าตัวอย่างในแอป

Token ไม่พบ หมดอายุ ถูกยกเลิก ถูกใช้กับ Client อื่น หรือไม่มีสิทธิ์ปัจจุบัน ตอบ HTTP 200:

{"active": false}

6.4 ข้อผิดพลาดและขีดจำกัด

กรณี ผลปัจจุบัน การจัดการของปลายทาง
Client ผิด/Secret ผิด/โปรแกรมปิด 401 ใน token/introspect ปฏิเสธ ตรวจ config ฝั่ง server ไม่ให้ user กรอก Secret
Code ผิด หมดอายุ ใช้ซ้ำ หรือสิทธิ์ไม่อนุญาต 403 ตอน token exchange เริ่ม Login ใหม่หลังตรวจสิทธิ์ ห้าม retry code เดิม
authorize ไม่อนุญาต 403 แสดงทางกลับ One เพื่อขอสิทธิ์
Payload ไม่ถูกต้อง 422 แก้ implementation ไม่แสดง response ที่อาจมีรายละเอียดภายในต่อผู้ใช้
เกิน throttle 429 หยุด action แสดงให้ลองใหม่ เคารพ Retry-After ถ้ามี
TLS/timeout/5xx/JSON ไม่ถูกต้อง/active ไม่ใช่ boolean true ไม่สามารถยืนยัน fail closed; 503 สำหรับ dependency failure, ไม่ใช้สิทธิ์เก่า

Route throttle ปัจจุบัน: authorize 60/min, token 120/min, introspect 600/min ตาม key ของ Laravel middleware ไม่ได้เป็นโควตาที่รับรองแยกให้แต่ละผู้ใช้หรือ Client โปรแกรมหลายตัวหลัง IP เดียวกันอาจใช้ key ร่วมกัน ให้ประเมินโหลดก่อนเปิดใช้จำนวนมาก ห้ามแก้ด้วยการ cache ผลอนุญาตข้าม protected requests จนสิทธิ์ระงับไม่มีผล

7. จับคู่บัญชีและสิทธิ์ภายในโปรแกรม

ใช้คู่ (issuer, sub) เป็น external identity ที่มี unique constraint เช่น external_identities(provider, subject, user_id) โดย provider เป็น issuer ที่กำหนดไว้ ไม่ใช้ชื่อหรือ email เป็น primary key ของผู้ใช้จาก One และไม่ถือว่า sub คือ Google subject

สำหรับโปรแกรมเดิม:

  1. สำรวจ users เดิม ระบบ Login บทบาท tenant/คณะ เจ้าของข้อมูล background jobs และ protected routes ก่อนแก้
  2. เพิ่มตาราง identity mapping ด้วย migration ที่รักษาข้อมูลเดิม ไม่ล้าง users และไม่เปลี่ยน primary key เดิม
  3. ผูกบัญชีเก่าอัตโนมัติในการเข้าโปรแกรมครั้งแรก เมื่อ email_verified === true จาก introspection ที่ backend ตรวจแล้ว และ email ที่ trim/แปลงเป็นตัวพิมพ์เล็กตรงกับบัญชี active เดิมเพียงบัญชีเดียว ห้ามเชื่อ email ที่ browser ส่งมา หาก email ซ้ำ กำกวม หรือ local account ผูกกับ sub อื่นอยู่แล้ว ให้ปฏิเสธและส่งให้ Admin ตรวจ ห้าม merge หรือย้าย mapping อัตโนมัติ
  4. บัญชีใหม่จาก One เริ่มด้วยสิทธิ์พื้นฐานหรือรออนุมัติตามนโยบายแอป ไม่เลื่อนเป็น Admin/เจ้าของข้อมูลจาก email domain หรือจากการ Login สำเร็จ
  5. ตรวจข้อมูลใน introspection: active เป็น true จริง, sub เป็น string ไม่ว่าง, email/name มีรูปแบบตาม schema ที่แอปรองรับ, exp ยังไม่หมด และถ้าตั้ง expected program_id ไว้ต้องตรง ห้ามเชื่อ identity จาก browser/query
  6. ยังคงตรวจ role, ownership, tenant boundary และ CSRF ภายในโปรแกรมทุกครั้งหลังผ่านสิทธิ์ One

ขั้นตอนผูกอัตโนมัติที่ทุกโปรแกรมต้องทำ

  1. ตรวจ state แลก code ที่ backend และ introspect token ต้อง active === true และ sub/email/exp/program_id ถูกต้องตามสัญญา สำหรับการผูกครั้งแรกต้อง email_verified === true
  2. ค้นหา (issuer, sub) ที่เคยผูกก่อนเสมอ หากพบให้ใช้ user_id เดิมและตรวจบัญชียัง active แม้ email เปลี่ยน ไม่ค้นหา email ใหม่เพื่อย้ายบัญชี
  3. หากยังไม่ผูก เปิด transaction ค้นหาและ lock บัญชี local ด้วย email ที่ trim/lowercase ต้องพบ active account เพียงบัญชีเดียว ไม่ใช้ชื่อหรือ domain เพียงอย่างเดียว
  4. ตรวจ mapping ทั้งด้าน subject และ local user อีกครั้งภายใต้ lock พร้อม unique constraints ที่ (issuer, subject) และ (issuer, user_id) หากขัดแย้งให้ปฏิเสธ ไม่ทับข้อมูลเดิม
  5. สร้าง mapping ไป user_id เดิม บันทึก audit การผูกจาก email match โดยไม่บันทึก code/token/secret ไม่เปลี่ยนรหัสผ่าน local role กลุ่ม เจ้าของข้อมูล หรือสิทธิ์เดิม
  6. regenerate session แล้วเข้าสู่โปรแกรมด้วยบัญชีเดิม กรณี email ตรงชัดเจนไม่ต้องให้ Admin ผูกด้วยมือ
  7. ไม่พบ email ให้แสดงว่าบัญชียังไม่พร้อมเชื่อมและให้ Admin ตรวจ ไม่สร้างบัญชีหรือกำหนด Admin อัตโนมัติ แต่ละโปรแกรมอาจมีขั้นตอนสร้างบัญชีพื้นฐานแยกตามนโยบายของตน

One ส่ง email_verified เป็น boolean ตามสถานะยืนยันอีเมล เมื่อ Admin เปลี่ยนอีเมลจะล้างสถานะยืนยันและยกเลิก code/token เดิม บุคลากรต้องยืนยันผ่าน Google Login อีกครั้งก่อนใช้ email นั้นผูกบัญชีใหม่ การผูกเป็นงานของ backend โปรแกรมปลายทาง One ไม่สามารถเขียนตาราง users ของโปรแกรมอื่นได้เพียงเพิ่มรายการโปรแกรม

คง Login ตรงด้วยอีเมลควบคู่ One

  • แสดงทั้งปุ่ม One และช่องอีเมล/รหัสผ่านเดิม รวมถึง Google โดยตรงถ้าโปรแกรมตั้งค่าไว้ บุคลากรที่ผูก One แล้วต้องยังใช้บัญชีเดิม Login ตรงได้
  • บันทึกวิธีการยืนยันตัวตนใน server-side session หลังตรวจข้อมูลรับรองสำเร็จเท่านั้น ไม่รับ auth source หรือ user_id จาก browser เพื่อข้าม One
  • เซสชัน One ต้อง introspect ทุก protected request และตรวจสิทธิ์ภายในโปรแกรมตามเดิม เมื่อ One ระงับ/หมดอายุ/ติดต่อไม่ได้ ให้ปฏิเสธเซสชันนั้น ห้ามเปลี่ยนเป็น local session อัตโนมัติ
  • เซสชัน Login ตรงต้องตรวจ password หรือ Google identity จริง พร้อม local active/role/scope/auth_version ตามระบบเดิม ไม่ต้องมี token ของ One การผูก mapping ไม่ใช่เหตุให้ปิดช่องทางนี้
  • ผู้ใช้ต้อง Login ตรงใหม่อย่างชัดเจนเมื่อต้องการใช้ช่องทางตรง การเริ่ม One ต้องล้างเครื่องหมาย local authentication เดิม และการ Login ตรงสำเร็จต้องล้าง One token เดิม พร้อม regenerate session และ CSRF token ตามระบบ
  • การเพิกถอนสิทธิ์ใน One มีผลกับเซสชัน One เท่านั้น หากต้องปิดการเข้าใช้ทั้งสองช่องทาง ให้ระงับบัญชีที่โปรแกรมปลายทางด้วย การเชื่อม One ไม่เปลี่ยนสิทธิ์ local เดิมโดยอัตโนมัติ
identity = introspect(server_session_token)
require identity.active === true
mapping = find(configured_issuer, identity.sub)
if mapping exists: return require_active_local_user(mapping.user_id)
require identity.email_verified === true
transaction:
  user = exactly_one_active_local_user_for_update(lowercase(trim(identity.email)))
  recheck both mapping unique keys; reject conflicts
  insert mapping(configured_issuer, identity.sub, user.id)
  audit auto_link_by_email without tokens
return user  // existing roles and ownership unchanged

สิทธิ์ One ตัดสินว่าเปิดใช้โปรแกรมได้หรือไม่ ไม่ได้ให้สิทธิ์แก้ข้อมูลทุกประเภทในโปรแกรม introspection ปัจจุบันไม่ส่ง is_admin หรือรายชื่อคณะ/กลุ่ม ห้ามอนุมานว่าผู้ดูแล One เป็นผู้ดูแลปลายทาง และห้ามอ่านตารางฐานข้อมูลกลางเพื่อหลีกเลี่ยงข้อจำกัดนี้

8. แนวทางแยกตาม Stack

Stack ปลายทาง ส่วนที่ต้องเพิ่ม
PHP / Laravel callback route, server HTTP client, OneAccess middleware, mapping user, server session และ tests
Node.js / Express / NestJS backend callback, server session store, HTTP client, guard ก่อน handlers และ CSRF ของ local mutations
Next.js / Nuxt server routes/BFF สำหรับ callback และ introspection, session ฝั่ง server; ตรวจสิทธิ์ใน server actions/API ด้วย ไม่พึ่ง client component
Python / Django / FastAPI callback view, session/auth adapter, dependency/middleware ตรวจ One และ local roles
.NET / Java / Go server controller/handler, session store, authorization filter และ external identity mapping
SPA / static site เพิ่ม backend/BFF ก่อน ไม่มีวิธีเก็บ Client Secret อย่างปลอดภัยใน frontend-only app ของสัญญารุ่นนี้

ใช้ HTTP client ของ stack นั้นโดยเปิด TLS certificate/hostname verification จำกัด timeout และไม่ follow redirect ของ server-to-server requests ห้ามติดตั้ง generic OIDC adapter โดยชี้มาที่ One แล้วคาดว่าจะทำงานตามมาตรฐานที่ยังไม่มี

โครงสร้าง pseudocode ที่ต้องได้:

GET registered_callback?start=1:
    create random state + expires_at bound to local browser session
    redirect to fixed One authorize endpoint

GET registered_callback?code=...&state=...:
    validate and consume browser session state
    exchange code via backend using this app's client credentials
    introspect returned token; require active === true and valid identity
    map issuer+sub to local user without expanding local permissions
    regenerate session id; store token only on server
    redirect to a fixed clean local URL

EVERY protected request:
    if no local One token: deny or offer restart from One
    introspect token via backend
    if unavailable: stop action with 503
    if inactive: clear SSO login and deny
    validate local role + object/tenant ownership + CSRF where relevant
    only then execute the request

9. ตัวอย่าง PHP และการติดตั้ง Route

ดาวน์โหลด https://one.tapee.ac.th/developers/sso-client.php.txt เก็บเป็นไฟล์ PHP ฝั่ง backend ของแอป ไม่วางเป็นไฟล์ดาวน์โหลดที่มีค่าจริง ตัวอย่างต้องใช้ PHP 8.1+ และ cURL สำหรับฟังก์ชันในไฟล์นี้ สำหรับ Laravel ให้ปรับเป็น service/middleware และใช้ session ของ framework ไม่เรียก session_start ซ้ำ

Route ตัวอย่างที่ลงทะเบียนเป็น callback:

<?php
require '/private/path/to/sso-client.php';
if (isset($_GET['code'])) {
    oneCallback(); // ตรวจ state, exchange, introspect แล้วกลับ URL สะอาด
}
oneStart(); // รองรับ start=1 และการเริ่ม Login ใหม่

protected route ตัวอย่าง:

<?php
require '/private/path/to/sso-client.php';
$identity = oneRequireAccess();
// ต่อด้วยตรวจ local role/ownership และ CSRF ก่อนเปลี่ยนข้อมูล
// ผูก local account ด้วย ONE_ISSUER + $identity['sub'] ไม่ใช้ email เป็น user id

ตัวอย่างนี้เป็น adapter เริ่มต้น ยังไม่มี user mapping, local roles, storage policy หรือ CSRF ของโปรแกรมธุรกิจ ต้องเพิ่มส่วนเหล่านั้นก่อนใช้งานจริง ตั้ง session cookie Secure, HttpOnly, SameSite=Lax และ host-only; ใช้ session store ฝั่ง server ห้ามใช้ session driver ที่ส่ง access token กลับไปเก็บใน cookie/client

10. การเพิกถอน Logout และการหมดอายุ

กติกากลางคือ บัญชี active AND โปรแกรม active AND (ได้รับสิทธิ์ตรง OR จากกลุ่มที่ active) AND ไม่ถูกระงับรายบุคคล การระงับรายบุคคลมีผลเหนือกลุ่ม การเพิกถอนสิทธิ์ตรงอย่างเดียวอาจยังมีสิทธิ์จากกลุ่มได้

การเพิกถอน/ระงับมีผลกับ protected request ถัดไปที่ introspect ไม่มีระบบ push logout ไปปิดหน้าต่างหรือยกเลิกงานที่เริ่มประมวลผลไปแล้ว งานสำคัญหรือไฟล์ stream ยาวต้องกำหนดจุดตรวจซ้ำตามนโยบายแอป

  • Logout เฉพาะปลายทาง: ล้าง local session/token ของปลายทาง ไม่ได้ Logout One และไม่ยกเลิก token ฝั่งกลางทันที เพราะไม่มี revoke endpoint สาธารณะในรุ่นนี้
  • Logout One: ระบบกลางลบ code/token ของผู้ใช้นั้นทั้งหมด ปลายทางหยุดอนุญาตเมื่อ introspect ครั้งถัดไป การ Logout One ไม่ได้ Logout บัญชี Google
  • หมดอายุ 1 ชั่วโมง: เริ่ม flow ใหม่ด้วย state/code ใหม่ ไม่ต่ออายุ token จากค่าที่จำไว้
  • Admin หมุน Client Secret: code/token ของโปรแกรมนั้นถูกยกเลิก ต้องอัปเดต Secret ฝั่ง server และ Login ใหม่

11. ถ้าต้องแก้ระบบ One หรือเชื่อม Telegram

สำหรับ AI ที่ทำงานใน source ของ One: อ่าน AGENTS.md ก่อน Source หลักอยู่ที่ app/ กติกาสิทธิ์อยู่ที่ app/app/Services/Platform.php สัญญา SSO อยู่ที่ app/app/Http/Controllers/SsoController.php และ app/routes/web.php การแก้สิทธิ์ต้องผ่าน authorization, transaction และ audit เดิม ไม่เพิ่ม endpoint ข้าม Admin

API ข้างต้นเป็น API Login/ตรวจสิทธิ์ ไม่มี API สาธารณะสำหรับจัดการกลุ่ม ให้/ระงับสิทธิ์ ส่งประกาศ หรือส่ง Telegram ในฐานะระบบกลาง โปรแกรมที่ต้องการ integration เพิ่มต้องออกแบบสัญญาและการอนุญาตแยก ไม่ใช้ session/Secret/Bot Token ของ One แทนสิทธิ์เฉพาะงาน

Telegram ที่ผูกกับ One ใช้สำหรับบริการและข้อความของ One ไม่ได้ทำให้โปรแกรมที่ลงทะเบียนส่ง Telegram ได้อัตโนมัติ หากต้องเพิ่มความสามารถนี้ ให้จัดทำ requirement และ implementation เพิ่มอย่างชัดเจน

12. ชุดทดสอบที่ AI ต้องส่งมอบ

  • Login จาก One ที่มีสิทธิ์ เข้าปลายทางได้โดยไม่กรอกรหัสผ่านอีก และ identity ตรงกับบัญชีจริง
  • ผู้ไม่ Login / ไม่มีสิทธิ์ / บัญชีปิด / โปรแกรมปิด เข้าหน้า API หรือดาวน์โหลดผ่านลิงก์ตรงไม่ได้
  • สิทธิ์จากกลุ่มใช้ได้ และการระงับรายบุคคลทำให้ protected request ถัดไปถูกปฏิเสธ แม้ยังอยู่ในกลุ่ม
  • State หาย ผิด หมดอายุ หรือมาจากอีก browser session ต้องไม่สร้าง local login; ทดสอบการเปิดหลายแท็บตามนโยบาย state ที่เลือก
  • Code หมดอายุ ใช้ซ้ำ หรือเป็นของอีก Client ต้องถูกปฏิเสธ; token ของอีก Client ใช้ไม่ได้
  • Token หมดอายุ Logout One และหมุน Secret ทำให้ protected requests ถูกปฏิเสธ
  • One timeout/TLS error/5xx/JSON เสีย/active เป็น string "true" ต้องไม่อนุญาต และ mutation ต้องยังไม่เกิด
  • ทดสอบ local role, ownership, tenant separation, CSRF และบัญชีเก่าที่ email ซ้ำ/เปลี่ยน โดยไม่เพิ่มสิทธิ์พิเศษ
  • Secret/code/token ไม่หลุดใน frontend bundle, browser storage, logs, error pages, analytics หรือ Git
  • Health check และ rollback plan ของปลายทางทำงานได้โดยรักษาข้อมูลเดิม

แยกผลทดสอบจำลอง HTTP ออกจากการทดสอบกับ One จริง ต้องมี Client และบัญชีที่ได้รับอนุญาตจึงทดสอบ end-to-end ห้ามสร้างสิทธิ์หรือส่งข้อความให้บุคลากรจริงเพียงเพื่อทดสอบโดยไม่ได้รับคำสั่ง

13. สำรอง Deploy และสิ่งที่ต้องส่งมอบ

ก่อน deploy ทุกครั้งให้ commit/push source ไป private Git พร้อม backup tag และตรวจ remote SHA สำเร็จก่อน ถ้า backup ไม่สำเร็จหยุด deploy สำหรับ source ของ One ใช้ scripts/deploy.py ตาม AGENTS.md และ docs/BACKUP.md โปรแกรมปลายทางใช้ repo/ขั้นตอนสำรองที่กำหนดสำหรับโปรแกรมนั้น ไม่ push โค้ดปลายทางทับ repo ของ One

สำรองไฟล์ production และฐานข้อมูลก่อน migration ในพื้นที่ private แยกจาก Git ไม่เก็บ .env, secrets, ข้อมูลบุคลากร หรือ database dump ลง repository รักษา APP_KEY/keys ของแต่ละระบบ และทำ migration แบบไม่ลบข้อมูลโดยไม่จำเป็น

AI ต้องส่งมอบ: source patch, route/middleware ที่เพิ่ม, schema/mapping, ชื่อตัวแปรที่ต้องตั้ง (ไม่มีค่าจริง), callback ที่ต้องลงทะเบียน, tests และผล, deployment/rollback steps, backup commit/tag และข้อจำกัดที่ยังไม่ได้ทดสอบจริง ห้ามระบุว่าแอปรองรับ One แล้วจากการมีแค่ปุ่มลิงก์ไป One

ข้อกำหนดการบันทึก Log: ตั้ง access log/APM ของ callback ไม่ให้เก็บ query code/state และตั้ง HTTP client tracing ไม่ให้บันทึก body ที่มี Client Secret หรือ token ห้ามส่งข้อมูล callback เข้า analytics