สารบัญ
OAuth PKCE
OAuth PKCE
OAuth 2.0 PKCE (Proof Key for Code Exchange) ช่วยให้แอปไคลเอ็นต์สาธารณะ (SP ของเบราว์เซอร์ แอปบนอุปกรณ์เคลื่อนที่) ทำการโทร API ในนามของผู้ใช้แต่ละรายโดยไม่ต้องจัดเก็บเซิร์ฟเวอร์ลับฝั่งไคลเอ็นต์ที่มีอายุยาวนาน
เมื่อใดควรใช้ OAuth PKCE
- การสร้างเบราว์เซอร์ SPA หรือแอปมือถือที่ต้องการการเรียกเก็บเงินต่อผู้ใช้
- SaaS ผู้เช่าหลายราย — ผู้ใช้แต่ละรายชำระค่าใช้งาน API ของตนเอง
- You ไม่สามารถจัดเก็บฝั่งไคลเอ็นต์ลับที่แบ่งใช้ (ไคลเอ็นต์สาธารณะ)
- คุณต้องการคีย์แยกต่างหากที่เพิกถอนได้สำหรับผู้ใช้แต่ละราย (ใช้ได้จนกว่าผู้ใช้จะเพิกถอน) แทนที่จะใช้คีย์ API ร่วมกันเพียงคีย์เดียว
สิ่งที่ผู้ใช้ของคุณจะเห็น
อธิบายขั้นตอนเหล่านี้บนหน้าจอลงชื่อเข้าใช้ของคุณเอง:
- ในแอปของคุณ ผู้ใช้เลือก "ลงชื่อเข้าใช้ด้วย BazaarLink" (หรือชื่อปุ่มอื่นที่คุณตั้ง)
- เบราว์เซอร์เปิดหน้าอนุญาตของ BazaarLink หากยังไม่ได้ลงชื่อเข้าใช้ ผู้ใช้จะลงชื่อเข้าใช้ก่อนแล้วกลับมาที่หน้านี้โดยอัตโนมัติ
- หน้าจะแสดงที่อยู่แอปของคุณและสิ่งที่จะเกิดขึ้นหากอนุญาต: ระบบสร้างคีย์ API ใหม่สำหรับแอป การใช้งานถูกเรียกเก็บจากยอดคงเหลือ BazaarLink ของผู้ใช้ และผู้ใช้เพิกถอนคีย์ได้ทุกเมื่อ ผู้ใช้ตั้งชื่อคีย์และกำหนดวงเงินใช้จ่ายรายเดือนได้ (ไม่บังคับทั้งสองอย่าง)
- ผู้ใช้คลิก “อนุญาต” แล้วถูกส่งกลับไปที่แอปของคุณ หากคลิก “ปฏิเสธ” ระบบจะไม่สร้างคีย์ แอปของคุณจะไม่ได้รับแจ้ง และผู้ใช้จะเห็นหน้า “ปฏิเสธการเข้าถึงแล้ว”
- หากต้องการเพิกถอนการเข้าถึงภายหลัง ผู้ใช้เปิดหน้า “คีย์ API” (https://bazaarlink.ai/keys) แล้วปิดใช้งานหรือลบคีย์ที่ตั้งชื่อตามแอปของคุณ
วิธีการทำงาน
ขั้นตอนที่ 1 — เริ่มต้นการตรวจสอบสิทธิ์ — สร้าง code_verifier แบบสุ่ม (สตริงสุ่มแบบยาว) และแฮช SHA-256 เป็น code_challenge จากนั้นเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าการรับรองความถูกต้อง BazaarLink
https://bazaarlink.ai/auth?callback_url=https://yourapp.com/callback&code_challenge=CODE_CHALLENGE&code_challenge_method=S256พารามิเตอร์ของ URL การอนุญาต
- callback_url (จำเป็น) — ที่ที่ผู้ใช้จะกลับมาหลังอนุญาต ดูกฎด้านล่าง
- code_challenge (จำเป็น) — SHA-256 ของ code_verifier ที่เข้ารหัสแบบ base64url (43 อักขระ ไม่มี padding)
- code_challenge_method (จำเป็น) — ต้องเป็น S256
- state (ไม่บังคับ) — ค่า CSRF แบบทึบแสงของคุณเอง ความยาว 1 ถึง 256 อักขระ ASCII ที่พิมพ์ได้ BazaarLink จะส่งคืนตามเดิมเป็น &state=… ต่อท้าย code ทันที หาก state มีรูปแบบไม่ถูกต้อง หน้าอนุญาตจะแสดง "คำขออนุญาตไม่ถูกต้อง"
- key_label (ไม่บังคับ) — ไม่เกิน 100 อักขระ ใช้กรอกชื่อคีย์ในหน้าขอความยินยอมไว้ล่วงหน้า (ผู้ใช้ยังแก้ไขได้) ป้ายชื่อที่ยาวเกินไปหรือว่างเปล่าจะถูกละเว้น
- Headless tools (CLI / desktop, no callback_url) — omit callback_url. After the user allows, the page shows a one-time code (valid 5 minutes, single use) for them to enter into your tool; exchange it exactly like a redirected code. The page cannot show which app is asking, so tell users to enter the code only in a tool they started themselves.
ไม่รองรับ
- workspace_id และ required_workspace_id — ไม่รองรับ คีย์เป็นของบัญชีผู้ใช้เองเสมอ
- code_challenge_method=plain — ไม่รองรับ (เฉพาะ S256)
กฎของ callback_url
- ต้องเป็น https:// ส่วน http:// รับเฉพาะ localhost, 127.0.0.1 และ [::1] (พอร์ตใดก็ได้) โดยหน้าขอความยินยอมจะแสดงคำเตือนการพัฒนาในเครื่อง
- ห้ามมี fragment (#) ห้ามมีชื่อผู้ใช้หรือรหัสผ่านใน URL และยาวไม่เกิน 2048 อักขระ
- หน้าขอความยินยอมจะแสดงชื่อโฮสต์ callback ของคุณ เพื่อให้ผู้ใช้เห็นว่าแอปใดเป็นผู้ขอ
- หลังผู้ใช้อนุญาต เบราว์เซอร์จะถูกส่งไปยัง callback_url ของคุณพร้อมต่อท้าย code=… (และ state=… หากคุณส่งมา โดยสตริงคิวรีเดิมจะถูกคงไว้) code ใช้ได้ 10 นาทีและใช้ได้เพียงครั้งเดียว
ขั้นตอนที่ 2 — แลกรหัสสำหรับคีย์ API — หลังจากที่ผู้ใช้อนุญาตคำขอแล้ว BazaarLink จะเปลี่ยนเส้นทางไปยัง callback_url ของคุณพร้อม code แบบใช้ครั้งเดียว code ใช้ได้ 10 นาทีและใช้ได้เพียงครั้งเดียว หาก code_verifier ผิด code จะถูกทำลาย POST code, code_verifier และ code_challenge_method (ต้องมีทั้งสามค่า) เพื่อรับคีย์ API ของผู้ใช้
ขั้นตอนที่ 3 — ใช้คีย์กำหนดขอบเขตผู้ใช้ — คีย์ที่ส่งคืนคือคีย์ BazaarLink API ปกติที่เป็นของผู้ใช้ที่อนุญาต — การใช้งานจะถูกเรียกเก็บจากยอดคงเหลือของผู้ใช้รายนั้น ไม่ใช่ของคุณ
curl https://bazaarlink.ai/api/v1/chat/completions \
-H "Authorization: Bearer sk-bl-..." \
-H "Content-Type: application/json" \
-d '{"model": "google/gemini-3.5-flash", "messages": [{"role": "user", "content": "Hello"}]}'ตัวอย่าง JavaScript (เบราว์เซอร์)
หน้า /auth และ POST /api/v1/auth/keys ให้บริการจาก https://bazaarlink.ai (ไม่ใช่ api.bazaarlink.ai) คีย์ที่คุณได้รับใช้ได้กับ base URL ทั้งสอง: https://bazaarlink.ai/api/v1 และ https://api.bazaarlink.ai/v1
หากผู้ใช้ตั้งวงเงินใช้จ่ายตอนอนุญาต วงเงินนั้นเป็นวงเงินรายเดือนและจะรีเซ็ตตามรอบเดือนของบัญชี
ข้อผิดพลาด
ข้อผิดพลาดใช้รูปแบบแบบ OpenAI {"error":{"message","type","code"}} POST /api/v1/auth/keys อาจส่งคืน:
- 400 invalid_code_challenge_method — ไม่มี code_challenge_method เป็น plain หรือเป็นค่าอื่นที่ไม่ใช่ S256
- 400 — JSON body ไม่ถูกต้อง หรือไม่มี code / code_verifier
- 403 invalid_code — ไม่รู้จัก code, code หมดอายุหรือถูกใช้แล้ว, code_verifier ผิด หรือบัญชีไม่ได้รับอนุญาตอีกต่อไป ทุกกรณีนี้ตั้งใจส่งข้อความเดียวกัน เพื่อไม่ให้ผู้เรียกแยกแยะได้ code_verifier ที่ผิดจะทำให้ code ถูกทำลายด้วย: ให้ผู้ใช้อนุญาตใหม่อีกครั้ง
- 429 rate_limited — พยายามแลกเปลี่ยนเกิน 30 ครั้งใน 10 นาทีจาก IP เดียว (ดูเฮดเดอร์ Retry-After)
- 429 key_total_cap — บัญชีมีคีย์ API ครบจำนวนสูงสุด 200 คีย์แล้ว
- 405 — รับเฉพาะ POST
สร้างโค้ดจากเซิร์ฟเวอร์ของคุณ (คีย์การจัดการ)
เจ้าของคีย์การจัดการ (Management Key) ส่วนบุคคลสามารถสร้างโค้ดการอนุญาตได้โดยตรงด้วย POST /api/v1/auth/keys/code โดยไม่ต้องพาผู้ใช้ผ่านหน้าเบราว์เซอร์ (เข้ากันได้กับ OpenRouter) โค้ดจะผูกกับเจ้าของคีย์การจัดการ ดังนั้นคีย์ที่แลกได้จึงเป็นคีย์มาตรฐานในบัญชีของเจ้าของรายนั้น โดยวงเงิน รอบเวลา วันหมดอายุ และชื่อจะเป็นไปตามที่กำหนดไว้ที่นี่ ใช้เมื่อเครื่องมือของคุณเองมีคีย์การจัดการอยู่แล้วและต้องการมอบคีย์ที่จำกัดสิทธิ์ให้แอป ขั้นตอนการแลก (POST /api/v1/auth/keys) เหมือนด้านบน
- callback_url (จำเป็น) และ code_challenge + code_challenge_method=S256 (จำเป็น) — กฎเดียวกับ URL การอนุญาต
- key_label (ไม่บังคับ) — ยาวได้ไม่เกิน 100 ตัวอักษร เป็นชื่อของคีย์ ค่าเริ่มต้น: "App: <โฮสต์ callback ของคุณ>"
- limit (ไม่บังคับ) — วงเงินการใช้จ่ายเป็น USD ตั้งแต่ 0 ขึ้นไป ถ้าเป็น 0 หรือไม่ระบุ หมายถึงไม่จำกัด
- usage_limit_type (ไม่บังคับ) — daily, weekly หรือ monthly: วงเงินรีเซ็ตบ่อยแค่ไหน ใช้ร่วมกับ limit เท่านั้น ค่าเริ่มต้นคือ monthly
- expires_at (ไม่บังคับ) — เวลาที่คีย์หมดอายุ: เวลา ISO 8601 UTC ในอนาคตที่มีวินาที เช่น 2026-12-31T23:59:59Z ค่าที่ละเอียดแค่ระดับนาทีจะถูกปฏิเสธ หากไม่ระบุ คีย์จะยังใช้งานได้จนกว่าจะถูกเพิกถอน
- workspace_id — ไม่รองรับ (400) spawn_agent และ spawn_cloud จะถูกรับแต่ไม่นำมาใช้
การตอบกลับ: { "data": { "id", "app_id", "created_at" } } id คือโค้ดใช้ครั้งเดียวสำหรับนำไปแลก (ใช้ได้ 10 นาที และใช้ได้ครั้งเดียว) BazaarLink ไม่มีระบบลงทะเบียนแอป ดังนั้น app_id จึงเป็นจำนวนเต็มคงที่ที่คำนวณจากที่อยู่ callback ของคุณ: ที่อยู่เดิมจะได้ app_id เดิมเสมอ
- 401 unauthorized — ไม่มีคีย์ Bearer หรือไม่รู้จักคีย์นั้น
- 403 management_key_required — คีย์ไม่ใช่คีย์การจัดการส่วนบุคคล (คีย์มาตรฐานและคีย์การจัดการขององค์กรจะถูกปฏิเสธ)
- 403 account_not_allowed — เจ้าของคีย์ถูกระงับหรือถูกลบ
- 400 — invalid_callback_url, invalid_code_challenge_method, invalid_code_challenge, invalid_expires_at, workspace_not_supported หรือเนื้อหาคำขอผิดรูปแบบ
- 429 rate_limited — สร้างโค้ดเกิน 30 ครั้งต่อชั่วโมงสำหรับเจ้าของรายเดียว หรือเกิน 120 ครั้งต่อชั่วโมงจาก IP เดียว (ดู Retry-After)
คีย์ที่คุณจะได้รับ
- คีย์ BazaarLink API มาตรฐาน (sk-bl-…) ชนิดเดียวกับคีย์ที่สร้างในหน้า “คีย์ API” และใช้ได้จนกว่าผู้ใช้จะเพิกถอน
- การใช้งานถูกเรียกเก็บจากยอดคงเหลือ BazaarLink ของผู้ใช้ หากผู้ใช้ตั้งวงเงินใช้จ่ายในหน้าขอความยินยอม วงเงินนั้นเป็นวงเงินรายเดือน
- ใช้ได้กับ base URL ทั้งสอง: https://bazaarlink.ai/api/v1 และ https://api.bazaarlink.ai/v1
- นับรวมในขีดจำกัด 200 คีย์ของบัญชี และแสดงในรายการ “คีย์ API” ของผู้ใช้ ซึ่งผู้ใช้ปิดใช้งานหรือลบได้ทุกเมื่อ
- บัญชีที่ถูกระงับหรือถูกลบไม่สามารถอนุญาตแอปได้ และ code ที่ออกก่อนการระงับจะถูกปฏิเสธเมื่อแลกเปลี่ยน (403 invalid_code)
สิ่งที่คุณจะได้รับ
- Authorization Code + PKCE flow สำหรับแอปพลิเคชันไคลเอ็นต์สาธารณะ
- การเรียกเก็บเงินต่อผู้ใช้: ผู้ใช้แต่ละรายจ่ายค่าใช้งานของตนเองจากยอดคงเหลือของตนเอง
- คีย์แยกต่างหากสำหรับผู้ใช้แต่ละราย แสดงในหน้า “คีย์ API” ของผู้ใช้ ซึ่งผู้ใช้เพิกถอนได้