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

Device flow: Auth กับ Logto

บันทึก:

คู่มือนี้สมมติว่าคุณได้สร้างแอปพลิเคชันประเภท "Native" ที่ใช้ device flow เป็น authorization flow ใน Logto Console แล้ว

บทนำ

OAuth 2.0 device authorization grant (device flow) ถูกออกแบบมาสำหรับอุปกรณ์ที่มีข้อจำกัดด้านการป้อนข้อมูล เช่น สมาร์ททีวี, เครื่องเกม, เครื่องมือ CLI, และอุปกรณ์ IoT โดยช่วยให้ผู้ใช้เริ่มกระบวนการลงชื่อเข้าใช้บนอุปกรณ์นั้น แต่ดำเนินการยืนยันตัวตนให้เสร็จสมบูรณ์บนอุปกรณ์อื่นที่มีเบราว์เซอร์ เช่น โทรศัพท์หรือแล็ปท็อป

เนื่องจากตัวอุปกรณ์ไม่สามารถจัดการ flow การลงชื่อเข้าใช้ผ่านเบราว์เซอร์ได้ อุปกรณ์จะแสดงรหัสสั้น ๆ และ URL ให้ผู้ใช้ ผู้ใช้จะไปที่ URL นั้นบนอุปกรณ์อื่น กรอกรหัส และลงชื่อเข้าใช้ ในขณะเดียวกัน อุปกรณ์ต้นทางจะ poll ไปที่ Logto จนกว่าการอนุญาตจะเสร็จสมบูรณ์

รับข้อมูลประจำตัวแอปพลิเคชัน

ใน Logto Console ของคุณ ไปที่หน้ารายละเอียดแอปพลิเคชันเพื่อรับข้อมูลประจำตัวดังต่อไปนี้:

  • App ID: ตัวระบุเฉพาะของแอปพลิเคชันของคุณ (หรือที่รู้จักในชื่อ client_id)
  • Logto endpoint: จุดเชื่อมต่อเซิร์ฟเวอร์ authorization ของ Logto คุณสามารถดูได้ใน Logto Console ที่ "Application details"

สำหรับ Logto Cloud, endpoint คือ https://{your-tenant-id}.logto.app

บันทึก:

แอป device flow เป็น public client จึงไม่ต้องใช้ App Secret

ขอ device code

เริ่ม device flow โดยส่งคำขอ POST ไปยัง device authorization endpoint:

curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access profile'

ผลลัพธ์ที่ได้รับประกอบด้วย:

FieldDescription
device_codeโค้ดเฉพาะสำหรับแอปของคุณใช้ในการ poll ไปที่ token endpoint
user_codeโค้ดสั้น ๆ สำหรับแสดงให้ผู้ใช้กรอกในเบราว์เซอร์
verification_uriURL ที่ผู้ใช้จะกรอก user_code
verification_uri_completeURL ที่มี user_code เติมไว้ล่วงหน้าแล้ว ผู้ใช้สามารถไปที่ URL นี้โดยตรงเพื่อข้ามการกรอกรหัสเอง — คุณสามารถนำเสนอเป็น QR code, ลิงก์ หรือวิธีอื่น ๆ ก็ได้
expires_inอายุการใช้งาน (วินาที) ของ device_code และ user_code ให้หยุด polling เมื่อหมดอายุ

แสดง URL สำหรับยืนยันตัวตนให้ผู้ใช้

แสดง user_code และ verification_uri บนหน้าจออุปกรณ์ของคุณ

หรือจะใช้ verification_uri_complete ที่มีโค้ดเติมไว้ล่วงหน้าแล้วก็ได้ — ผู้ใช้เพียงแค่ยืนยัน วิธีนำเสนอขึ้นอยู่กับคุณ: QR code, ลิงก์ ฯลฯ

Poll สำหรับโทเค็น

ขณะที่ผู้ใช้ดำเนินการยืนยันตัวตนในเบราว์เซอร์ อุปกรณ์ของคุณควร poll ไปที่ token endpoint โดยแอปของคุณควรรออย่างน้อย 5 วินาที ระหว่างแต่ละ polling:

curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
--data-urlencode 'device_code=DEVICE_CODE'

แทนที่ DEVICE_CODE ด้วยค่าจาก device authorization response

หยุด polling เมื่อ:

  • คุณได้รับ token response ที่สำเร็จ
  • เวลาจาก expires_in ใน device code response หมดอายุ
  • คุณได้รับ error ที่ไม่ควร retry เช่น expired_token หรือ access_denied

การตอบกลับโทเค็น

หลังจากผู้ใช้อนุมัติแล้ว ผลลัพธ์จะมี:

FieldDescription
access_tokenโทเค็นการเข้าถึง (Access token) โดยปกติเป็นสตริงทึบ; หากมีการร้องขอ resource จะเป็น JWT ที่ aud ถูกตั้งเป็น resource URI
id_tokenโทเค็น ID (ID token) ที่มีการอ้างสิทธิ์ของผู้ใช้ มีเฉพาะเมื่อร้องขอ scope openid
refresh_tokenใช้เพื่อขอโทเค็นใหม่โดยไม่ต้องยืนยันตัวตนซ้ำ มีเฉพาะเมื่อร้องขอ scope offline_access
token_typeเป็น Bearer เสมอ
expires_inอายุการใช้งานของโทเค็น (วินาที)
scopeขอบเขต (scopes) ที่ authorization server อนุมัติ

Checkpoint: ทดสอบ device flow ของคุณ

ตอนนี้ ทดสอบการเชื่อมต่อ device flow ของคุณ:

  1. รันแอปของคุณและเรียก device flow เพื่อรับ device_code และ user_code
  2. เปิด verification_uri ในเบราว์เซอร์และกรอก user_code หรือใช้ verification_uri_complete เพื่อข้ามการกรอกรหัส
  3. ดำเนินการลงชื่อเข้าใช้ในเบราว์เซอร์ให้เสร็จสมบูรณ์
  4. ตรวจสอบว่าแอปของคุณได้รับโทเค็นหลังจาก polling

รับข้อมูลผู้ใช้

ถอดรหัสการอ้างสิทธิ์ใน ID token

id_token ที่ได้จาก token response เป็น JSON Web Token (JWT) มาตรฐาน คุณสามารถถอดรหัส payload ที่ถูกเข้ารหัสแบบ Base64URL (ส่วนที่สองของ JWT คั่นด้วย .) เพื่อเข้าถึงการอ้างสิทธิ์พื้นฐานของผู้ใช้โดยไม่ต้องร้องขอเครือข่ายเพิ่มเติม

payload ที่ถอดรหัสจะมีการอ้างสิทธิ์ เช่น sub (user ID), name, email ฯลฯ ขึ้นอยู่กับ scopes ที่ร้องขอ

เคล็ดลับ:

สำหรับการใช้งานจริง ควรตรวจสอบลายเซ็นของ JWT ก่อนเชื่อถือการอ้างสิทธิ์ ใช้ JWKS จาก Logto endpoint ของคุณ (https://your.logto.endpoint/oidc/jwks) เพื่อตรวจสอบโทเค็น

ดึงข้อมูลจาก userinfo endpoint

ID token จะมีการอ้างสิทธิ์พื้นฐานตาม scopes ที่ร้องขอ การอ้างสิทธิ์เพิ่มเติมบางอย่าง (เช่น custom_data, identities) จะมีเฉพาะผ่าน OIDC UserInfo endpoint:

curl --request GET 'https://your.logto.endpoint/oidc/me' \
--header 'Authorization: Bearer ACCESS_TOKEN'

แทนที่ ACCESS_TOKEN ด้วย access token ทึบ (ไม่ใช่ JWT resource token) ที่ได้จาก token response ผลลัพธ์จะเป็น JSON object ที่มีการอ้างสิทธิ์ของผู้ใช้ตาม scopes ที่ได้รับอนุมัติ

ขอการอ้างสิทธิ์เพิ่มเติม

คุณอาจพบว่าข้อมูลผู้ใช้บางอย่างไม่มีใน ID token นี่เป็นเพราะ OAuth 2.0 และ OpenID Connect (OIDC) ถูกออกแบบให้ยึดหลัก least privilege (PoLP) และ Logto ก็สร้างบนมาตรฐานเหล่านี้

โดยปกติแล้ว จะมีการส่งคืนการอ้างสิทธิ์ (claim) แบบจำกัด หากคุณต้องการข้อมูลเพิ่มเติม คุณสามารถร้องขอขอบเขต (scope) เพิ่มเติมเพื่อเข้าถึงการอ้างสิทธิ์ (claim) ที่มากขึ้นได้

ข้อมูล:

"การอ้างสิทธิ์ (Claim)" คือการยืนยันข้อมูลบางอย่างเกี่ยวกับผู้ถูกอ้างถึง (subject); "ขอบเขต (Scope)" คือกลุ่มของการอ้างสิทธิ์ (claim) ในกรณีนี้ การอ้างสิทธิ์ (claim) คือข้อมูลบางอย่างเกี่ยวกับผู้ใช้

ตัวอย่างที่ไม่เป็นทางการของความสัมพันธ์ระหว่างขอบเขต (scope) กับการอ้างสิทธิ์ (claim) มีดังนี้:

เคล็ดลับ:

การอ้างสิทธิ์ (claim) "sub" หมายถึง "ผู้ถูกอ้างถึง (subject)" ซึ่งคือตัวระบุที่ไม่ซ้ำของผู้ใช้ (เช่น user ID)

Logto SDK จะร้องขอขอบเขต (scope) สามรายการเสมอ ได้แก่ openid, profile และ offline_access

หากต้องการขอ scopes เพิ่มเติม ให้ใส่ไว้ในพารามิเตอร์ scope ของ device authorization request เช่น หากต้องการขออีเมลและเบอร์โทรศัพท์ของผู้ใช้:

curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access profile email phone'

Scopes และ claims

ต่อไปนี้คือรายการขอบเขต (Scopes) ที่รองรับและการอ้างสิทธิ์ (Claims) ที่เกี่ยวข้อง:

ขอบเขต OIDC มาตรฐาน

openid (ค่าเริ่มต้น)

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
substringตัวระบุที่ไม่ซ้ำของผู้ใช้

profile (ค่าเริ่มต้น)

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
namestringชื่อเต็มของผู้ใช้
usernamestringชื่อผู้ใช้ของผู้ใช้
picturestringURL ของรูปโปรไฟล์ผู้ใช้ปลายทาง (End-User) URL นี้ต้องอ้างถึงไฟล์รูปภาพ (เช่น PNG, JPEG, หรือ GIF) ไม่ใช่หน้าเว็บที่มีรูปภาพ โปรดทราบว่า URL นี้ควรอ้างอิงถึงรูปโปรไฟล์ของผู้ใช้ปลายทางโดยเฉพาะ เหมาะสำหรับแสดงเมื่ออธิบายผู้ใช้ปลายทาง ไม่ใช่รูปภาพใด ๆ ที่ผู้ใช้ถ่ายมาโดยพลการ
created_atnumberเวลาที่สร้างผู้ใช้ปลายทาง เวลานี้แสดงเป็นจำนวนมิลลิวินาทีตั้งแต่ Unix epoch (1970-01-01T00:00:00Z)
updated_atnumberเวลาที่ข้อมูลของผู้ใช้ปลายทางถูกอัปเดตล่าสุด เวลานี้แสดงเป็นจำนวนมิลลิวินาทีตั้งแต่ Unix epoch (1970-01-01T00:00:00Z)

การอ้างสิทธิ์มาตรฐาน อื่น ๆ เช่น family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo, และ locale จะถูกรวมอยู่ในขอบเขต profile ด้วยโดยไม่จำเป็นต้องร้องขอ endpoint userinfo ความแตกต่างเมื่อเทียบกับการอ้างสิทธิ์ข้างต้นคือ การอ้างสิทธิ์เหล่านี้จะถูกส่งกลับเมื่อค่าของมันไม่ว่างเปล่าเท่านั้น ในขณะที่การอ้างสิทธิ์ข้างต้นจะคืนค่า null หากค่าว่างเปล่า

บันทึก:

ต่างจากการอ้างสิทธิ์มาตรฐาน การอ้างสิทธิ์ created_at และ updated_at ใช้หน่วยเป็นมิลลิวินาทีแทนที่จะเป็นวินาที

email

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
emailstringอีเมลของผู้ใช้
email_verifiedbooleanอีเมลได้รับการยืนยันแล้วหรือไม่

phone

ชื่อการอ้างสิทธิ์ประเภทคำอธิบาย
phone_numberstringเบอร์โทรศัพท์ของผู้ใช้
phone_number_verifiedbooleanเบอร์โทรศัพท์ได้รับการยืนยันแล้วหรือไม่

address

โปรดดูรายละเอียดของการอ้างสิทธิ์ที่อยู่ได้ที่ OpenID Connect Core 1.0

ข้อมูล:

ขอบเขตที่มีเครื่องหมาย (ค่าเริ่มต้น) จะถูกร้องขอเสมอโดย Logto SDK การอ้างสิทธิ์ภายใต้ขอบเขต OIDC มาตรฐานจะถูกรวมอยู่ในโทเค็น ID เสมอเมื่อมีการร้องขอขอบเขตที่เกี่ยวข้อง — ไม่สามารถปิดได้

ขอบเขตเพิ่มเติม

ขอบเขตต่อไปนี้เป็นขอบเขตที่ Logto ขยายขึ้นและจะคืนค่าการอ้างสิทธิ์ผ่าน userinfo endpoint การอ้างสิทธิ์เหล่านี้ยังสามารถตั้งค่าให้ถูกรวมอยู่ในโทเค็น ID ได้โดยตรงผ่าน Console > Custom JWT ดู Custom ID token สำหรับรายละเอียดเพิ่มเติม

custom_data

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
custom_dataobjectข้อมูลกำหนดเองของผู้ใช้

identities

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
identitiesobjectข้อมูลตัวตนที่เชื่อมโยงของผู้ใช้
sso_identitiesarrayข้อมูล SSO ที่เชื่อมโยงของผู้ใช้

roles

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
rolesstring[]บทบาท (Role) ของผู้ใช้

urn:logto:scope:organizations

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
organizationsstring[]รหัสองค์กรที่ผู้ใช้สังกัด
organization_dataobject[]ข้อมูลองค์กรที่ผู้ใช้สังกัด
บันทึก:

การอ้างสิทธิ์ขององค์กรเหล่านี้สามารถดึงได้ผ่าน userinfo endpoint เมื่อใช้ โทเค็นทึบ (Opaque token) อย่างไรก็ตาม โทเค็นทึบไม่สามารถใช้เป็นโทเค็นองค์กรสำหรับเข้าถึงทรัพยากรเฉพาะองค์กร ดู โทเค็นทึบและองค์กร สำหรับรายละเอียดเพิ่มเติม

urn:logto:scope:organization_roles

ชื่อการอ้างสิทธิ์ประเภทคำอธิบายรวมในโทเค็น ID โดยค่าเริ่มต้น
organization_rolesstring[]บทบาทขององค์กรที่ผู้ใช้สังกัดในรูปแบบ <organization_id>:<role_name>

ทรัพยากร API และองค์กร

เราแนะนำให้อ่าน 🔐 การควบคุมการเข้าถึงตามบทบาท (RBAC) ก่อน เพื่อทำความเข้าใจแนวคิดพื้นฐานของ RBAC ใน Logto และวิธีตั้งค่าทรัพยากร API อย่างถูกต้อง

ขอสิทธิ์เข้าถึงทรัพยากร API

หากต้องการเข้าถึง API resource เฉพาะ ให้ใส่พารามิเตอร์ resource ใน device authorization request:

curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access' \
--data-urlencode 'resource=https://your-api-resource-indicator'

เมื่อผู้ใช้อนุญาตเสร็จและคุณได้รับ refresh token แล้ว คุณสามารถขอโทเค็นการเข้าถึงแบบ JWT สำหรับ API resource ได้:

curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'resource=https://your-api-resource-indicator'

ผลลัพธ์จะมี JWT access_token ที่ aud ถูกตั้งเป็น API resource indicator ของคุณ

บันทึก:

refresh_token จะมีเฉพาะเมื่อมี scope offline_access ใน device authorization request แรกเสมอ เก็บและใช้ refresh_token ล่าสุดเสมอ เพราะ Logto ใช้ token rotation

ดึงโทเค็นองค์กร

หาก องค์กร เป็นเรื่องใหม่สำหรับคุณ โปรดอ่าน 🏢 องค์กร (Multi-tenancy) เพื่อเริ่มต้น

หากต้องการขอข้อมูลที่เกี่ยวข้องกับองค์กร ให้เพิ่ม scope urn:logto:scope:organizations ใน device authorization request:

curl --request POST 'https://your.logto.endpoint/oidc/device/auth' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'scope=openid offline_access urn:logto:scope:organizations' \
--data-urlencode 'resource=urn:logto:resource:organizations'

เมื่อผู้ใช้ลงชื่อเข้าใช้แล้ว คุณสามารถดึงโทเค็นองค์กรโดยใช้ refresh token ได้:

curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'organization_id=your-organization-id'

ผลลัพธ์จะมี access token ที่ถูกจำกัดขอบเขตสำหรับองค์กรที่ระบุ

ทรัพยากร API ขององค์กร

หากต้องการขอโทเค็นการเข้าถึงสำหรับ API resource ภายในองค์กร ให้ใส่ทั้งพารามิเตอร์ resource และ organization_id:

curl --request POST 'https://your.logto.endpoint/oidc/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your-application-id' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=REFRESH_TOKEN' \
--data-urlencode 'organization_id=your-organization-id' \
--data-urlencode 'resource=https://your-api-resource-indicator'

อ่านเพิ่มเติม

กระบวนการสำหรับผู้ใช้ปลายทาง: กระบวนการยืนยันตัวตน, กระบวนการบัญชี, และกระบวนการองค์กร ตั้งค่าตัวเชื่อมต่อ การอนุญาต (Authorization)