ข้ามไปยังเนื้อหาหลัก

การยืนยันตัวตนแบบ Bearer ของ Okta API

ยืนยันตัวตนการเข้าถึง Halo API แบบโปรแกรมโดยใช้โทเค็น OAuth 2.0 Bearer ที่ออกโดย Okta.

ภาพรวม

Halo เปิดเผย REST API ผ่านบริการ API-Access คำขอ API ทั้งหมดต้องมีโทเค็น Bearer ที่ถูกต้องในส่วนหัว Authorization โทเค็นจะได้รับจาก Okta โดยใช้โฟลว์ OAuth 2.0 Client Credentials (machine-to-machine).

คู่มือนี้จะแนะนำการกำหนดค่า Okta ให้เป็นผู้ให้บริการข้อมูลประจำตัวสำหรับบริการ Halo API-Access จากนั้นทดสอบการผสานรวมด้วยการยืนยันตัวตนด้วยโทเค็น Bearer.

ข้อกำหนดเบื้องต้น

  • การติดตั้งใช้งาน Halo ที่กำลังทำงานอยู่พร้อมกำหนดค่าบริการ API-Access แล้ว
  • องค์กร Okta ที่มีสิทธิ์เข้าถึงระดับผู้ดูแลระบบ
  • เซิร์ฟเวอร์การให้สิทธิ์ Okta ที่กำหนดค่าสำหรับ Halo แล้ว (ดู Okta Authorization Server)
  • การเข้าถึงเครือข่ายจาก API client ไปยังทั้ง Okta และ Halo API endpoint

การตั้งค่า

ลงทะเบียน API client ใน Okta

สร้างแอปพลิเคชันแบบ machine-to-machine

  1. เข้าสู่ระบบ Okta Admin Console
  2. ไปที่ Applications -> Applications -> Create App Integration -> API Services.

Screenshot: Create API Services application in Okta

  1. ระบุชื่อ App integration ที่เหมาะสม เช่น Glasswall Halo API

Screenshot: API service app name in Okta

ปิดใช้งาน DPoP (proof of possession)

  1. ไปที่แท็บ General ของแอปพลิเคชัน -> ส่วน General Settings -> คลิก Edit.
  2. ภายใต้ Proof of possession ให้เอาเครื่องหมายถูกออกจาก Require Demonstrating Proof of Possession (DPoP) header in token requests.
  3. บันทึก

หมายเหตุ: Okta เปิดใช้งาน DPoP เป็นค่าเริ่มต้นสำหรับแอปพลิเคชัน API Services โดย DPoP จะผูกโทเค็นเข้ากับคีย์เข้ารหัสของ client เพื่อป้องกันการโจมตีแบบนำโทเค็นกลับมาใช้ซ้ำ อย่างไรก็ตาม บริการ Halo API-Access ยังไม่รองรับการตรวจสอบความถูกต้องของโทเค็น DPoP ในขณะนี้ ดังนั้นจึงต้องปิดใช้งานฟีเจอร์นี้เพื่อให้การยืนยันตัวตนด้วย Bearer token ทำงานได้

Screenshot: Disable DPoP in Okta application settings

กำหนดค่า client credentials

  1. จดบันทึก Client ID และสร้าง Client Secret.

    export CLIENT_ID="<your-client-id>"
    export CLIENT_SECRET="<your-client-secret>"

หมายเหตุด้านความปลอดภัย: จัดเก็บ client secret อย่างปลอดภัยโดยใช้ secrets manager (เช่น Azure KeyVault) ห้าม commit secrets ลงใน source control โดยเด็ดขาด

Screenshot: Client ID and secret from Okta application

กำหนดค่า roles (ไม่บังคับ)

  1. หาก API client ของคุณต้องการสิทธิ์เขียนไปยัง endpoints การจัดการไลเซนส์ โปรดตรวจสอบให้แน่ใจว่าได้กำหนดค่า claim role บน authorization server โดยแมปค่า Admin ไปยัง client ของคุณ (ดู API Roles)

หมายเหตุ: หากไม่มี claim role API จะใช้ role User เป็นค่าเริ่มต้น ดู API Roles to Action Mapping สำหรับรายละเอียดเกี่ยวกับสิ่งที่แต่ละ role สามารถเข้าถึงได้

จดบันทึก issuer URI และ audience

  1. จาก authorization server ที่กำหนดค่าไว้ในขั้นตอนข้อกำหนดเบื้องต้น:

    export OKTA_ISSUER_URI="https://<your-okta-domain>/oauth2/<authorization-server-id>"
    export VALID_AUDIENCE="api://halo"

เพิ่ม access policy สำหรับ API client

  1. ไปที่แท็บ Access Policies ของ authorization server (Security -> API -> เลือก authorization server ของคุณ -> Access Policies)
  2. Add a new access policy:
    • ชื่อ: เช่น API Client Access
    • คำอธิบาย: เช่น Access policy for Halo API clients
    • กำหนดให้กับ: API Services client ที่สร้างไว้ด้านบน (ค้นหาด้วยชื่อแอปพลิเคชัน glasswall-halo-api จากขั้นตอนที่ 2)
  3. Add a rule:
    • ชื่อ: เช่น Allow API Clients
    • ประเภทการให้สิทธิ์: Client Credentials
    • ปล่อยการตั้งค่าอื่น ๆ ไว้เป็นค่าเริ่มต้น หรือปรับอายุการใช้งานของโทเค็นตามต้องการ

หมายเหตุ: access policies สำหรับ grant แบบ Client Credentials ใช้ควบคุมว่า clients ใด (ตาม client_id) ที่สามารถขอโทเค็นได้ การเป็นสมาชิกกลุ่มไม่มีผล เนื่องจากไม่มีบริบทของผู้ใช้ใน flow นี้ รักษาความปลอดภัยในการเข้าถึง API โดยจำกัดผู้ที่มี client_id และ client_secret ผ่าน secrets manager ของคุณ

Screenshot: API access policy on authorization server

กำหนดค่า service API-Access สำหรับ Okta

ต้องกำหนดค่า Helm chart cdrplatform-api-access เพื่อให้ตรวจสอบความถูกต้องของ Bearer tokens ที่ออกโดย authorization server ของ Okta ของคุณ chart นี้เปิดเผยการตั้งค่าการยืนยันตัวตนภายใต้คีย์ values configuration

ปรับใช้การกำหนดค่า

หมายเหตุ: ต้องตั้งค่า Authority และ ValidIssuer ให้เป็น Okta issuer URI ทั้งคู่ บริการ API-Access ใช้ Authority เพื่อค้นหา JWKS (JSON Web Key Set) สำหรับการตรวจสอบลายเซ็นของโทเค็น และใช้ ValidIssuer เพื่อตรวจสอบ claim iss ในโทเค็น

export HALO_DOMAIN=<your-halo-domain>
helm upgrade --install cdrplatform-api-access cdrplatform-api-access --reuse-values \
--set configuration.AuthenticationScheme="Bearer" \
--set configuration.Authentication__Schemes__Bearer__Authority="${OKTA_ISSUER_URI:?}" \
--set configuration.Authentication__Schemes__Bearer__ValidIssuer="${OKTA_ISSUER_URI:?}" \
--set configuration.Authentication__Schemes__Bearer__ValidAudiences__0="${VALID_AUDIENCE:?}" \
--set strategy.type="Recreate" \
--set ingress.enabled=true \
--set ingress.tls.enabled=true \
--set ingress.tls.domain="${HALO_DOMAIN:?}" \
--atomic

หลาย audience (ไม่บังคับ)

หาก API client หรือแอปพลิเคชันหลายรายการต้องเข้าถึง Halo API ด้วย audience ที่แตกต่างกัน ให้เพิ่มรายการ ValidAudiences เพิ่มเติม:

  --set configuration.Authentication__Schemes__Bearer__ValidAudiences__0="api://halo-api" \
--set configuration.Authentication__Schemes__Bearer__ValidAudiences__1="<second-client-id>" \
--set configuration.Authentication__Schemes__Bearer__ValidAudiences__2="<third-client-id>"

การใช้งาน Halo API

รับ bearer token

Client Credentials flow (machine-to-machine)

ใช้ flow นี้สำหรับระบบอัตโนมัติ, ไปป์ไลน์ CI/CD และการเชื่อมต่อแบบ service-to-service ที่ไม่ต้องมีการโต้ตอบจากผู้ใช้

export TOKEN_ENDPOINT="${OKTA_ISSUER_URI}/v1/token"

ขอโทเค็น:

curl -s -X POST "${TOKEN_ENDPOINT}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "scope=halo.api"

ตัวอย่างการตอบกลับ:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "halo.api"
}

แยกโทเค็น:

export ACCESS_TOKEN=$(curl -s -X POST "${TOKEN_ENDPOINT}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "scope=halo.api" | jq -r '.access_token')

ยืนยันตัวตนคำขอ API

ใส่ Bearer token ในส่วนหัว Authorization ของทุกคำขอ API:

export HALO_API_URL="https://<your-halo-domain>"

ตรวจสอบการยืนยันตัวตน

ทดสอบด้วย endpoint ที่มีการป้องกัน คำขอที่ไม่มีโทเค็นควรส่งกลับ 401 และคำขอที่มีโทเค็นที่ถูกต้องควรส่งกลับ 200:

# Without token - expect 401
curl -s -o /dev/null -w "%{http_code}" \
"${HALO_API_URL}/api/v1/policies"

# With token - expect 200
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${HALO_API_URL}/api/v1/policies"

ตัวอย่าง: ส่งไฟล์เพื่อประมวลผล

curl -s -X POST \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-F "file=@/path/to/document.pdf" \
"${HALO_API_URL}/api/v1/rebuild/file" \
--output rebuilt_document.pdf

การแก้ไขปัญหา

อาการสาเหตุวิธีแก้ไข
401 Unauthorizedโทเค็นหมดอายุหรือไม่ถูกต้องขอโทเค็นใหม่ ตรวจสอบว่า CLIENT_ID และ CLIENT_SECRET ถูกต้อง
401 Unauthorized พร้อมโทเค็นที่ถูกต้องAudience ไม่ตรงกันตรวจสอบให้แน่ใจว่า ValidAudiences ใน API-Access ตรงกับเคลม aud ในโทเค็น
403 Forbidden พร้อม AdminRoleMissingไม่มีบทบาท Admin ในโทเค็นกำหนดค่าเคลม role บน authorization server (ดู API Roles) จำเป็นสำหรับการดำเนินการเขียนของการจัดการไลเซนส์
คำขอโทเค็นล้มเหลวURL ของ token endpoint ไม่ถูกต้องตรวจสอบ ID ของ authorization server และโดเมน Okta ตรวจสอบ /.well-known/openid-configuration
ข้อผิดพลาด invalid_scopeใช้ OIDC scopes กับ Client Credentialsใช้ scope แบบกำหนดเอง halo.api แทน openid, profile หรือ email
ข้อผิดพลาด invalid_dpop_proofไม่ได้ปิดใช้งาน DPoPปิดใช้งาน DPoP บนแอปพลิเคชัน API Services (ดู Disable DPoP)
หมดเวลาการเชื่อมต่อเครือข่ายไฟร์วอลล์หรือพร็อกซีบล็อกอยู่ตรวจสอบให้แน่ใจว่าไคลเอนต์ API สามารถเข้าถึงได้ทั้ง Okta token endpoint และ Halo API endpoint