روند Device Code در Oauth 2.0: احراز هویت در دستگاه‌های بدون مرورگر

فرض کنید دستگاهی ساخته‌اید که مرورگر ندارد یا مروگر دارد ولی ورودی آن از طریق کیبرد محدود است (مثلا از ریموت کنترل استفاده می‌کند) و به راحتی نمیتوان نام کاربری و پسورد را از طریقِ کنترل آن وارد کرد. روند Device Code در Oauth 2.0 برای احراز هویت چنین دستگاه‌هایی طراحی شده است. این روند به طور رسمی در RFC 8628 تعریف شده است و یک مکانیزم ساده برای دستگاه‌هایی فراهم می‌کند که توانایی اجرای مرورگر وب را ندارند یا ورودی متن آن‌ها دشوار است.

مثلا دستگاهی مانند A.p.p.l.e TV را در نظر بگیرید. این دستگاه مرورگر ندارد و در واقع این دستگاه نمیتواند به صورت معمول روند Oauth را طی کرده و در سامانه‌ی احراز هویت شرکت A.p.p.l.e لاگین کند. چرا که روند Oauth به طور معمول نیازمند یک مرورگر است. همچنین وارد کردن نام کاربری و رمز عبور در چنین دستگاهی از طریق ریموت کنترل آن هم حرف‌به‌حرف دشوار است.

در واقعیت وقتی که شما در دستگاهی مشابه A.p.p.l.e TV لاگین می‌کنید. صفحه‌ای مانند صفحه زیر را مشاهده خواهید کرد.

صفحه لاگین
صفحه لاگین

در این صفحه از کاربر درخواست شده است که URL نشان داده شده در صفحه را در یک دستگاه دیگردر مروگر باز کند و کد نشان داده شده (در این جا ‍NKLDD5D) را در صفحه باز شده وارد کند. معمولا کاربران از طریق موبایلشان این کار را انجام می‌دهند.

چنین روندی چند خوبی دارد، نخست این که نیازی نیست روی خود دستگاه مرورگر وجود داشته باشد. همچنین کاربر در وارد کردن انواع متن روی صفحه‌های این دستگاه‌ها با دشواری مواجه نمی‌شود. همچنین اگر کاربر قبلا در تلفن‌همراهش لاگین کرده باشد حتی نیازی به لاگین در آنجا هم ندارد و نیازی نیست که زیاد تایپ کند.

این روند همچنین روی برخی دیگر از دستگاه‌‌ها مانند کد‌کننده‌های ویدئو که در تصویر زیر نیز می‌توانید نمونه آن را ببینید به همین صورت وجود دارد.

کدکننده همزمان ویدیو
کدکننده همزمان ویدیو

این دستگاه‌ها نه مروگر دارند نه حتی ریموت کنترل بلکه تنها یک صفحه نمایش بسیار ساده‌ی پیکسلی دارند. با این حال دستگاه‌های بسیار قوی و کاربردی‌ای هستند. آن‌ها را از طریق یک کابل HDMI‌ به یک دوربین متصل می‌کنند و این دستگاه می‌تواند تصویر دوربین را به صورت لایو استریم روی یوتیوب یا فیس‌بوک پخش کند.

تا این جا متوجه شدیم که روند Device Code در Oauth 2.0 به چه کاری می‌آید و در کجا استفاده می‌شود. حال بررسی می‌کنیم این روند به صورت فنی چگونه اتفاق می‌افتد.

روند Device Code در Oauth 2.0 چگونه کار می‌کند؟

روند Device Code کاملا متفاوت از سایر روند‌های Oauth کار می‌کند چرا که در این روند ما هیچ ریداریکتی(Redirect) روی مرورگر دستگاه نداریم (به یاد بیاورید که دستگاه مرورگر نداشت) در این روند هنگامی که کاربر اقدام به لاگین می‌کند. دستگاه روند را با ارسال یک درخواست POST آغاز می‌کند. این درخواست شامل یک client_id است.(چنین دستگاه‌هایی را اصطلاحا Public Client یا کلاینت عمومی می‌گویند. چون دستگاه نمی‌تواند client_secret را به صورت امن ذخیره کند، به عنوان یک کلاینت عمومی شناخته می‌شود.)

نمودار روند Device Code
نمودار روند Device Code

درخواست POST مشابه زیر به یک endpoint خاص منظور برای روند Device Code ارسال می‌شود.

POST https://authorization-server.com/devic

client_id={CLIENT_ID}

سرور در پاسخ اطلاعاتی را در قالب JSON برای دستگاه ارسال می‌کند:

{
  "device_code": "NGU4QWFiNjQ5YmQwNG3YTdmZMEyNzQ3YzQ1YSA",
  "verification_uri": "https://example.com/device",
  "user_code": "BDSD-HQMK",
  "expires_in": 1800,
  "interval": 5
}

داده‌های موجود در پاسخ را به صورت زیر هستند:

  • مقدار device_code: یک رشته‌ طولانی از کاراکتر‌هاست که دستگاه در نهایت برای دریافت توکن دسترسی با سرور مبادله می‌کند. ( چیزی شبیه به client_secret‌ موقت)

  • مقدار verification_uri: این URLی است که کاربر باید در موبایلش وارد کند و روند لاگین را آغاز نماید.

  • مقدار user_code: این کدی‌ است که دستگاه روی صفحه نشان می‌دهد و کاربر باید در URL باز شده روی موبایلش وارد کند.

  • مقدار expires_in: نشان دهنده مقدار زمانی(به ثانیه) است که داده‌ها اعتبار دارند. پس از گذشت این زمان مقدار device_code و user_code منقضی می‌شوند و دستگاه لازم است روند را از نو آغاز کند.

  • مقدار interval: نشان می‌دهد دستگاه هر چند ثانیه یک بار باید بررسی کند که آیا کاربر فرایند لاگین‌ را به پایان رسانده یا خیر. به این مقدار اصطلاحا Polling Interval گفته می‌شود. نکته قابل توجه در مورد Polling Interval این است که این روش برخلاف سایر روندها که بر اساس Redirect یا Push هستند، نیازمند ارسال درخواست‌های مکرر از سمت دستگاه به سرور است. این امر می‌تواند بار اضافی روی سرور احراز هویت ایجاد کند و به همین دلیل Interval باید بهینه انتخاب شود. (بهتر بود مکانیزم انتظار با استفاده از روش‌هایی، مانند Webhook یا Push Notification پیاده سازی شود.)

پس از مرحله اول حالا دستگاه باید از طریقی URL و User Code را به کاربر نشان دهد تا کاربر مراحل لاگین را پیش ببرد.(مثلا روی تلویزیون یا صفحه نمایش دستگاه). زمانی که دستگاه منتظر است که کاربر URL را باز کرده کد را وارد کرده و لاگین کند در همین حین هر پنج ثانیه (همانطور که در مقدار interval نشان داده شده بود) یک درخواست POST می‌فرستد. این درخواست POST به endpoint توکن با مقدار grant type خاص device_code ارسال می‌شود.

POST https://authorization-server.com/token

grant_type=urn:ietf:params:oauth:grant-type:device_code
&client_id=CLIENT_ID
&device_code=NGU4QWFiNjQ5YmQwNG3YTdmZMEyNzQ3YzQ1YSA

زمانی که کاربر هنوز مشغول لاگین روی موبایلش است، endpoit توکن خطای زیر را برمیگرداند:

{
  "error": "authorization_pending"
}

این پیام خطا بیانگر آن است که کاربر هنوز روند Login را به اتمام نرسانده ولی کد هم هنوز منقضی نشده است. دستگاه باید پس از گذشت مقدار زمان مشخصی دوباره این درخواست را ارسال کند. در همین حین کاربر در حال Login مثلا در یوتیوب است. همانطور که در عکس زیر میبینید:

پس از آن که کاربر با موفقیت Login کرد و در گوشی‌اش پیام «اتصال موفق دستگاه» را دریافت نمود. در نوبت بعدی که دستگاه درخواست توکن را ارسال می‌کند پاسخ زیر را از سرور دریافت خواهد کرد:

{
  "access_token": "MsQ50jbzRn43NzqNLgV3Ia",
  "expires_in": 3600,
  "refresh_token": "b7aab34e37298a160e0ede5b43ed1f70a8"
}

در این پاسخ access_token ، زمان انقضای آن و refresh_token برای دریافت access_token جدید به دستگاه داده شده است. به این ترتیب روند احراز هویت کامل میشود و پس از آن دستگاه می‌تواند از ‍access_token برای ارتباط با API استفاده کند.

مزایا و معایب روند Device Code

مزایا:

  • احراز هویت بدون مرورگر: امکان لاگین در دستگاه‌هایی که مرورگر ندارند یا محیط مرورگر کامل ندارند.

  • تجربه‌ی کاربری بهبودیافته: کاربر تنها چند کاراکتر (کد) را روی دستگاه دیگر وارد می‌کند و نیازی به وارد کردن نام کاربری و رمز عبور طولانی روی دستگاه اصلی با ورودی محدود نیست. همچنین Privacy در وارد کردن رمز عبور حفظ می‌شود.

  • افزایش امنیت: رمز عبور اصلی کاربر هرگز روی دستگاه عمومی وارد یا ذخیره نمی‌شود. لاگین از طریق یک دستگاه امن (مانند موبایل) انجام می‌شود.

معایب:

  • وابستگی به دستگاه دوم: کاربر حتماً به یک دستگاه دوم با مرورگر (معمولاً موبایل یا کامپیوتر) نیاز دارد.

  • مکانیزم Polling (مصرف منابع): نیاز به ارسال درخواست‌های مکرر (Polling) از طرف دستگاه برای بررسی وضعیت لاگین، که می‌تواند باعث ایجاد بار روی سرور احراز هویت شود.

  • کد قابل مشاهده: user_code باید روی دستگاه نمایش داده شود و اگر در محیط عمومی نمایش داده شود، ممکن است شخص دیگری آن را ببیند و روند را مختل کند (هرچند که کد به سرعت منقضی می‌شود).

پی‌نوشت:

منبع نوشته این مقاله از شرکت OKTA است. ولی متن به صورت تحلیلی و بدون استفاده از AI نوشته شده. در واقع به متن انگلیسی توضیحاتی برای فهم بهتر روند اضافه شده است و صرفا ترجمه‌ نیست. عکس‌ها غیر از نمودار روند(که خودم درست کرده‌ام) برای مقاله‌‌ی اصلی است.