ปกป้องทรัพยากร API ระดับโกลบอล
ปกป้อง API ที่ใช้ทั่วทั้งผลิตภัณฑ์ของคุณด้วยการควบคุมการเข้าถึงตามบทบาท (RBAC) ใน Logto กำหนดบทบาทและสิทธิ์ระดับโกลบอลเพื่อควบคุมการเข้าถึงของผู้ใช้และไคลเอนต์ทั้งหมดในแอปพลิเคชันของคุณ
ทรัพยากร API ระดับโกลบอลคืออะไร?
ทรัพยากร API ระดับโกลบอล คือ endpoint หรือบริการในแอปพลิเคชันของคุณที่ผู้ใช้ทุกคนสามารถเข้าถึงได้ ไม่ว่าจะอยู่ในองค์กรหรือผู้เช่าใดก็ตาม โดยทั่วไปจะเป็น API ที่เปิดเผยต่อสาธารณะ, บริการหลักของผลิตภัณฑ์ หรือ endpoint ใด ๆ ที่ไม่ได้จำกัดขอบเขตกับองค์กรใดองค์กรหนึ่ง
กรณีการใช้งาน เช่น
- API สาธารณะ หรือ endpoint ที่ใช้ร่วมกันในกลุ่มผู้ใช้ของคุณ
- Microservices ที่ไม่ได้ผูกกับระบบหลายผู้เช่า (multi-tenancy)
- API หลักของแอปพลิเคชัน (เช่น
/api/users,/api/products) ที่ลูกค้าทุกคนใช้
Logto ช่วยให้คุณรักษาความปลอดภัย API เหล่านี้ด้วย OAuth 2.1 ร่วมกับการควบคุมการเข้าถึงตามบทบาทที่ยืดหยุ่น
วิธีการทำงานใน Logto
- ทรัพยากร API และสิทธิ์ถูกลงทะเบียนในระดับโกลบอล: แต่ละ API ที่คุณต้องการปกป้องจะถูกกำหนดด้วย resource indicator (URI) เฉพาะ พร้อมชุดสิทธิ์ (scopes) ที่ควบคุมการเข้าถึง
- การเข้าถูกควบคุมด้วยบทบาทระดับโกลบอล: คุณสามารถกำหนดสิทธิ์ให้กับบทบาท แล้วมอบหมายบทบาทเหล่านั้นให้กับผู้ใช้หรือไคลเอนต์
- แยกจากสิทธิ์ระดับองค์กร: ทรัพยากร API ระดับโกลบอลไม่มีบริบทขององค์กร อย่างไรก็ตาม สามารถใช้ร่วมกับบทบาทขององค์กรเพื่อเพิ่มชั้นบริบทได้หากต้องการ หากต้องการปกป้อง API ระดับองค์กร ดู ปกป้องทรัพยากร API ระดับองค์กร
ภาพรวมการนำไปใช้
- ลงทะเบียนทรัพยากร API ของคุณ และกำหนดสิทธิ์ใน Logto
- กำหนดบทบาท พร้อมสิทธิ์ที่จำเป็นสำหรับการเข้าถึง API
- มอบหมายบทบาท ให้กับผู้ใช้หรือไคลเอนต์
- ใช้ OAuth 2.0 authorization flows เพื่อขอรับโทเค็นการเข้าถึงสำหรับ API (ค่าพารามิเตอร์ resource ต้องตรงกับ API identifier ที่ลงทะเบียนไว้)
- ตรวจสอบโทเค็นการเข้าถึง ใน API ของคุณเพื่อบังคับใช้สิทธิ์
ทำความเข้าใจ resource indicator
Logto สร้างแบบจำลองทรัพยากร API ตาม RFC 8707: Resource Indicators for OAuth 2.0 โดย resource indicator คือ URI ที่ระบุ API หรือบริการเป้าหมายที่ร้องขออย่างเฉพาะเจาะจง
ประเด็นสำคัญ
- Resource indicator ต้องเป็น absolute URI (เช่น
https://api.example.com) - ไม่มี fragment component; หลีกเลี่ยงการใช้ query string หากเป็นไปได้
- Resource indicator ช่วยให้รองรับโทเค็นที่จำกัดผู้รับ (audience-restricted tokens) และสถาปัตยกรรม multi-API
ตัวอย่าง
- Management API:
https://my-tenant.logto.app/api - Custom global API:
https://api.yourapp.com
กระบวนการอนุญาต: การยืนยันตัวตนและปกป้อง API ของคุณ
กระบวนการด้านล่างนี้ใช้ได้ทั้งกรณีการยืนยันตัวตนของผู้ใช้แบบโต้ตอบ (browser / app) และกรณี backend เครื่องต่อเครื่อง (M2M)
โปรดทราบว่ากระบวนการนี้ไม่ได้ลงรายละเอียดพารามิเตอร์หรือ header ที่จำเป็นทั้งหมด แต่เน้นขั้นตอนหลัก อ่านต่อเพื่อดูตัวอย่างการทำงานจริง
การยืนยันตัวตนของผู้ใช้ = browser / app. M2M = บริการ backend หรือสคริปต์ที่ใช้ client credentials.
ค่าพารามิเตอร์ resource ต้องตรงกับ API identifier (resource indicator) ที่คุณลงทะเบียนใน Logto
ขั้นตอนการนำไปใช้
ลงทะเบียนทรัพยากร API ของคุณ
- ไปที่ Console → API resources
- สร้าง API resource ใหม่ (เช่น
https://api.yourapp.com/org) และกำหนดสิทธิ์ (scopes) ของมัน
สำหรับขั้นตอนการตั้งค่าแบบละเอียด ดู กำหนด API resources พร้อมสิทธิ์
ตั้งค่าบทบาทระดับโกลบอล
- ไปที่ Console → Roles
- สร้างบทบาทที่สอดคล้องกับสิทธิ์ของ API ของคุณ (เช่น
read:products,write:products) - มอบหมายบทบาทเหล่านี้ให้กับผู้ใช้หรือไคลเอนต์ที่ต้องการเข้าถึง API
สำหรับขั้นตอนการตั้งค่าแบบละเอียด ดู ใช้บทบาทระดับโกลบอล
ขอรับโทเค็นการเข้าถึงสำหรับทรัพยากร API ระดับโกลบอล
ก่อนเข้าถึงทรัพยากร API ระดับโกลบอล ไคลเอนต์ของคุณต้องขอโทเค็นการเข้าถึง Logto จะออก JSON Web Token (JWT) เป็นโทเค็นการเข้าถึงสำหรับทรัพยากร API ระดับโกลบอล โดยปกติจะใช้ OAuth 2.0 authorization code flow, refresh token flow หรือ client credentials flow
Authorization code หรือ refresh token flow
SDK อย่างเป็นทางการของ Logto ทั้งหมดรองรับการขอโทเค็นการเข้าถึงสำหรับทรัพยากร API ระดับโกลบอลด้วย refresh token flow ได้ทันที คุณยังสามารถใช้ไลบรารี OAuth 2.0 / OIDC client มาตรฐานเพื่อใช้งาน flow นี้ได้
- Logto SDK
- OAuth 2.0 / OIDC client library
เมื่อเริ่มต้น Logto client ให้เพิ่ม resource indicator ลงในพารามิเตอร์ resources (array) แล้วเพิ่มสิทธิ์ (scopes) ที่ต้องการลงในพารามิเตอร์ scopes
เมื่อผู้ใช้ได้รับการยืนยันตัวตนแล้ว ให้ส่ง resource indicator ในพารามิเตอร์ resource หรือพารามิเตอร์ที่มีชื่อคล้ายกันเมื่อขอโทเค็นการเข้าถึง (เช่น เรียก getAccessToken())
ดูรายละเอียดของแต่ละ SDK ได้ที่ Quick starts
เมื่อกำหนดค่า OAuth 2.0 client หรือเริ่มต้น authorization code flow ให้แน่ใจว่าคุณใส่พารามิเตอร์ resource และ scopes ที่ต้องการใน authorization request
ไลบรารีบางตัวอาจไม่รองรับพารามิเตอร์ resource โดยตรง แต่โดยทั่วไปจะอนุญาตให้ส่งพารามิเตอร์เพิ่มเติมใน authorization request ได้ ตรวจสอบเอกสารของไลบรารีของคุณสำหรับรายละเอียด
นี่คือตัวอย่าง authorization request ที่ไม่เป็นทางการโดยใช้พารามิเตอร์ resource และ scope:
GET /oidc/auth?response_type=code
&client_id=your-client-id
&redirect_uri=https://your-app.com/callback
&scope=openid profile offline_access read:products write:products
&resource=https://api.your-app.com
&code_challenge=abc123
&code_challenge_method=S256
&state=xyz
HTTP/1.1
Host: your.logto.endpoint
เมื่อผู้ใช้ได้รับการยืนยันตัวตนแล้ว คุณจะได้รับ authorization code นำ code นี้ไปแลกเป็น access token โดยส่ง POST request ไปที่ endpoint /oidc/token ของ Logto พร้อมพารามิเตอร์ resource ใน request body
นี่คือตัวอย่าง token request ที่ไม่เป็นทางการโดยใช้ grant type แบบ authorization code:
POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=authorization_code
&code=authorization-code-received
&redirect_uri=https://your-app.com/callback
&resource=https://api.your-app.com
คุณยังสามารถใช้ grant type แบบ refresh_token เพื่อขอโทเค็นการเข้าถึงใหม่โดยไม่ต้องมีการโต้ตอบของผู้ใช้ ตราบใดที่มีพารามิเตอร์ resource ใน request
นี่คือตัวอย่าง token request ที่ไม่เป็นทางการโดยใช้ grant type แบบ refresh token:
POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=refresh_token
&refresh_token=your-refresh-token
&resource=https://api.your-app.com
Client credentials flow
สำหรับกรณีเครื่องต่อเครื่อง (M2M) คุณสามารถใช้ client credentials flow เพื่อขอโทเค็นการเข้าถึงสำหรับทรัพยากร API ระดับโกลบอลของคุณ โดยส่ง POST request ไปที่ endpoint /oidc/token ของ Logto คุณสามารถขอโทเค็นการเข้าถึงโดยใช้ client ID และ secret ของคุณ
มีสองพารามิเตอร์สำคัญที่ต้องใส่ใน request:
resource: URI ของ resource indicator ของ API ที่คุณต้องการเข้าถึง (เช่นhttps://api.yourapp.com)scope: สิทธิ์ที่คุณต้องการร้องขอสำหรับ API (เช่นread:products write:products)
นี่คือตัวอย่าง token request ที่ไม่เป็นทางการโดยใช้ grant type แบบ client credentials:
POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=client_credentials
&resource=https://api.yourapp.com
&scope=read:products write:products
ตรวจสอบ JWT access token ใน API ของคุณ
JWT ที่ออกโดย Logto จะมีการอ้างสิทธิ์ (claims) ที่ API ของคุณสามารถใช้เพื่อบังคับใช้การอนุญาต
เมื่อ API ของคุณได้รับ request ที่มี access token จาก Logto คุณควร:
- ตรวจสอบลายเซ็นของโทเค็น (โดยใช้ JWKs ของ Logto)
- ยืนยันว่าโทเค็นยังไม่หมดอายุ (
expclaim) - ตรวจสอบว่า
iss(ผู้ออก) ตรงกับ endpoint Logto ของคุณ - ตรวจสอบว่า
aud(ผู้รับ) ตรงกับ resource identifier ของ API ที่คุณลงทะเบียน (เช่นhttps://api.yourapp.com) - แยก claim
scope(คั่นด้วยช่องว่าง) และตรวจสอบสิทธิ์ที่ต้องการ
สำหรับคู่มือแบบทีละขั้นตอนและเฉพาะภาษา ดู วิธีตรวจสอบ access token
Optional: Handle user permission change
User permissions can change at any time. Because Logto issues JWTs for RBAC, permission updates only appear in newly issued tokens, and never modify existing JWTs.
An access token can only include scopes that were requested in the original OAuth authorization flow. Even if a user gains new permissions, the token issued later can only contain a subset of the originally requested scopes. To access newly granted scopes that were not part of the initial request, the client must run a new authorization flow.
Downscoped permissions
When a user loses permissions:
- Newly issued tokens immediately reflect the reduced scopes.
- Existing JWTs keep the old scopes until they expire.
- Your API should always validate scopes and rely on short token lifetimes.
If you need faster reactions, implement your own signal that tells clients to refresh their tokens.
Enlarged permissions
For global API resources, when a user gains permissions, enlarged permissions will NOT show up through refresh. The client must perform a new OAuth authorization flow to obtain a token that includes the new scopes. This can happen silently if the user has an active Logto session.
Recommendations
- Validate scopes in your API on every call.
- Keep token expiration short.
- Add optional notifications if you need immediate permission-change propagation.
แนวปฏิบัติที่ดีและเคล็ดลับด้านความปลอดภัย
- กำหนดสิทธิ์ตามธุรกิจ: ใช้ชื่อที่ชัดเจนและสอดคล้องกับการกระทำจริง
- ตั้งอายุโทเค็นให้สั้น: ลดความเสี่ยงหากโทเค็นรั่วไหล
- จำกัด scope ที่ให้: ให้โทเค็นเฉพาะสิทธิ์ที่จำเป็นจริง ๆ
- ใช้การจำกัดผู้รับ (audience restriction): ตรวจสอบ claim
audเสมอเพื่อป้องกันการนำไปใช้ผิดวัตถุประสงค์
คำถามที่พบบ่อย
ถ้าไคลเอนต์ของฉันไม่รองรับพารามิเตอร์ resource ล่ะ?
ตั้งค่า API resource เริ่มต้นใน Logto Console โทเค็นจะใช้ audience นี้โดยอัตโนมัติเมื่อไม่มีการระบุ resource parameter ใน token request
ทำไมฉันถึงได้รับ 401 Unauthorized จาก API ของฉัน?
ตรวจสอบปัญหาทั่วไปดังต่อไปนี้:
- ลายเซ็นโทเค็น: ตรวจสอบว่า backend ของคุณดึง JWKs ที่ถูกต้องจาก Logto
- อายุโทเค็น: ตรวจสอบว่าโทเค็นยังไม่หมดอายุ (
expclaim) - ผู้รับ (Audience): ตรวจสอบว่า claim
audตรงกับ resource indicator ของ API ที่คุณลงทะเบียน - scope ที่ต้องการ: ตรวจสอบว่าโทเค็นมีสิทธิ์ที่จำเป็นใน claim
scope
จะทดสอบโดยไม่ต้องมีไคลเอนต์เต็มรูปแบบได้อย่างไร?
ใช้ personal access token เพื่อจำลองการเรียกแบบยืนยันตัวตน วิธีนี้ช่วยให้คุณทดสอบ endpoint ของ API ได้โดยไม่ต้องพัฒนา OAuth flow ครบถ้วนในแอปไคลเอนต์ของคุณ
ขอสิทธิ์โดยใช้ prefix หรือชื่อย่อของ scope ได้หรือไม่?
ไม่ได้ ชื่อ scope ต้อง ตรงกับ ชื่อสิทธิ์ที่กำหนดไว้ใน API resource ของคุณเท่านั้น ไม่สามารถใช้ prefix หรือชื่อย่อเป็น wildcard ได้
ตัวอย่าง:
ถ้า API resource ของคุณกำหนดไว้ว่า:
read:electionswrite:elections
คุณต้องร้องขอ:
scopes: ["read:elections", "write:elections"]
แบบนี้จะ ไม่ทำงาน:
scopes: ["read", "write"] // ❌ ไม่ตรงกับชื่อสิทธิ์
อ่านเพิ่มเติม
วิธีตรวจสอบ access tokenRBAC ในทางปฏิบัติ: การนำการอนุญาตที่ปลอดภัยไปใช้กับแอปของคุณ
ปรับแต่ง token claims RFC 8707: Resource Indicators