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

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)