แนวคิดหลัก

แนวคิดหลัก

คู่มือนี้จะช่วยให้นักพัฒนาเข้าใจว่า: คุณอยู่ในแอปส่วนขยายชั้นใด, ใช้โหมดการเชื่อมต่อแบบไหน, ในโทเค็น wsa มีอะไร และคุณต้องการ「ใช้ถึงระดับไหน」

สองโหมดการเชื่อมต่อ: Push vs Pull

แพลตฟอร์มส่งมอบตัวตนให้คุณได้สองเส้นทาง สัญญา wsa ใบเดียวกัน ต่างกันแค่「คุณรับข้อมูลยืนยันตัวตนมาอย่างไร」

Push handoff (แบบผลัก) — ดู 03

ผู้ใช้คลิกเปิดแอปของคุณในหน้า「ส่วนขยาย」ของพื้นที่ทำงาน แพลตฟอร์มจะต่อ wsa เข้ากับ URL หน้า Landing ของคุณและผลักมาให้:

https://app.example.com/landing?wsa=<JWT>
                      
                      https://app.example.com/landing?wsa=<JWT>

                    
บล็อกโค้ดนี้ในหน้าต่างลอย
  • ทางเข้าอยู่ภายในพื้นที่ทำงาน
  • นักพัฒนาเพียงบริโภค ?wsa= ที่หน้า Landing ง่ายที่สุด
  • เหมาะกับ: การเป็น「แอปฝังตัว」ในแถบด้านข้างของพื้นที่ทำงาน

Pull / M-Auth (แบบดึง) — ดู 04

แอปส่วนขยายของนักพัฒนาวางปุ่ม「Login with Workspace」ด้วยตัวเอง ผู้ใช้คลิกแล้วเข้าสู่การล็อกอิน GPTBots ➡️ เลือกพื้นที่ทำงาน ➡️ แล้วนำสถานะล็อกอินกลับมา ใช้ OAuth2 authorization code + PKCE:

  • ทางเข้าอยู่ที่หน้าล็อกอินของแอปส่วนขยายของนักพัฒนา
  • เบราว์เซอร์ได้แค่ code แบบใช้ครั้งเดียว ส่วน wsa ตัวจริงแบ็กเอนด์ของคุณเป็นผู้แลกด้วย code + PKCE และไม่มีวันเข้าไปใน URL ของเบราว์เซอร์
  • เหมาะกับ: แอปส่วนขยายของนักพัฒนาที่เป็นเว็บไซต์อิสระ ต้องการให้บริการ「ล็อกอินด้วยบัญชีพื้นที่ทำงาน GPTBots」
Push (แบบผลัก) Pull (M-Auth, แบบดึง)
ทางเข้าล็อกอิน หน้า「ส่วนขยาย」ของพื้นที่ทำงาน หน้าแอปของคุณ(ปุ่มล็อกอิน)
โทเค็นมาถึงมือคุณอย่างไร URL ?wsa= ผลักตรงไปที่หน้า Landing ฟรอนต์เอนด์รับ code, แบ็กเอนด์แลก wsa
เบราว์เซอร์เคยเห็น wsa ไหม เคย(หลัง Landing ต้องลบทันที) ไม่เคย(ปลอดภัยกว่า)
ต้องใช้ PKCE ไหม ไม่ ใช่(บังคับ S256
เมธอดฟรอนต์เอนด์ของ SDK consumeHandoff startWorkspaceLogin + completeWorkspaceLogin

คู่มือการใช้ข้อมูลยืนยันตัวตน

แพลตฟอร์มรับผิดชอบเพียง「ส่งมอบตัวตน」ส่วนการใช้หรือไม่ใช้ นักพัฒนาตัดสินใจเองอย่างอิสระ:

ระดับ ความหมาย สิ่งที่นักพัฒนาต้องทำ
use ตรวจลายเซ็น + สร้างเซสชัน + ควบคุมสิทธิ์ฟังก์ชันตาม role consumeHandoff / completeWorkspaceLogin, แบ็กเอนด์ verifyWsa
receive-only อ่านตัวตนเพื่อแสดงผล/เก็บสถิติ แต่ไม่สร้างเซสชัน ไม่ควบคุมสิทธิ์ ยังใช้การยืนยันตัวตนของตัวเองหรือแบบไม่ระบุตัวตน เพียง readHandoffToken()(ฟังก์ชันบริสุทธิ์ ไม่มีผลข้างเคียง)
ignore ไม่อ่านเลย เทียบเท่า auth_mode=none คือลิงก์ภายนอกธรรมดา ไม่ต้องทำอะไร

verifyWsa / readHandoffToken ล้วนเป็นฟังก์ชันบริสุทธิ์ ดังนั้น「รับแต่ไม่ใช้」จึงไม่มีต้นทุน

สอดคล้องกับ auth_mode ตอนลงทะเบียน:

  • auth_mode = workspace_account: แพลตฟอร์มจะลงลายเซ็น wsa แล้วต่อเข้ากับ URL(Push)/ รองรับ M-Auth(Pull)คุณจึงรับตัวตนได้
  • auth_mode = none: แพลตฟอร์มเปลี่ยนเส้นทางตรง URL ไม่พกข้อมูลยืนยันตัวตนใด ๆ คุณจะไม่ได้รับตัวตน(สอดคล้องกับ ignore

สัญญาโทเค็น wsa(JWT)

wsa เป็น JWT ที่ลงลายเซ็นแบบ HS256(HMAC-SHA256)มีอายุ 5 นาทีexp = iat + 300

Claim มาตรฐาน

Claim ประเภท คำอธิบาย
iss string คงที่เป็น gptbots-workspace, ต้องตรวจ
aud string host ของแอปส่วนขยายของนักพัฒนา(เช่น app.example.com)แยกมาจาก URL ลงทะเบียน, ต้องตรวจ
sub string accountId ของผู้ใช้พื้นที่ทำงาน ไม่ซ้ำทั่วโลก ใช้เป็นคีย์หลักของ user ID ฝั่งนักพัฒนาได้
iat number(วินาที) เวลาที่ออกโทเค็น
exp number(วินาที) เวลาหมดอายุ คงที่เป็น iat + 300, ต้องตรวจ

Claim ทางธุรกิจ

Claim ประเภท คำอธิบาย
role string OWNER / ADMIN / MEMBER — บทบาทของผู้ใช้ในพื้นที่ทำงานนั้น
workspace_id string ID พื้นที่ทำงาน(คือ projectId), คีย์แยกผู้เช่าหลายราย
username string ชื่อเล่นผู้ใช้(อาจไม่มี)
email string อีเมลผู้ใช้(อาจไม่มี)
avatar string URL รูปโปรไฟล์(อาจไม่มี)
app_name string ชื่อแอปส่วนขยายที่สอดคล้องกับการเปลี่ยนเส้นทางครั้งนั้น(เพื่อการตรวจสอบ, อาจไม่มี)

ฟิลด์ที่อาจไม่มี: username / email / avatar / app_name เมื่อข้อมูลต้นทางว่างเปล่าจะไม่ปรากฏใน payload โปรดจัดการค่าว่างเสมอ อย่าสมมติว่ามันจะมีอยู่แน่นอน

ตัวอย่าง payload

{ "iss": "gptbots-workspace", "aud": "app.example.com", "sub": "65f7c8a1d8f3a40012345678", "iat": 1730000000, "exp": 1730000300, "username": "张三", "email": "zhangsan@example.com", "avatar": "https://cdn.example.com/avatar/u123.png", "role": "ADMIN", "workspace_id": "65a0000000000000000abcde", "app_name": "合同审核系统" }
                      
                      {
  "iss": "gptbots-workspace",
  "aud": "app.example.com",
  "sub": "65f7c8a1d8f3a40012345678",
  "iat": 1730000000,
  "exp": 1730000300,
  "username": "张三",
  "email": "zhangsan@example.com",
  "avatar": "https://cdn.example.com/avatar/u123.png",
  "role": "ADMIN",
  "workspace_id": "65a0000000000000000abcde",
  "app_name": "合同审核系统"
}

                    
บล็อกโค้ดนี้ในหน้าต่างลอย

role ≠ สิทธิ์ภายในแอปของคุณ role สะท้อนเพียงบทบาทของผู้ใช้ในพื้นที่ทำงานนั้น แนะนำให้ถือว่ามันเป็น「การแมปสิทธิ์เริ่มต้นตอน Landing ครั้งแรก」ส่วนแอปของคุณดูแลโมเดลสิทธิ์ของตัวเอง

ขั้นถัดไป: อ่านตามโหมดที่คุณเลือก 03-การเชื่อมต่อแบบ Push หรือ 04-การเข้าสู่ระบบแบบ Pull; ไม่ว่าแบบใด โปรดอ่าน 05-การตรวจสอบโทเค็นและความปลอดภัย