این مقاله قسمت دوم از سری مقالات آشنایی با OAuth2 است. بنابراین اگر اطلاعات اولیه درمورد OAuth2 ندارید و هنوز قسمت اول رو مطالعه نکردید، پیشنهاد میکنم از لینک زیر استفاده کنید.
در قسمت قبل درمورد روش هایی که قبل از معرفی OAuth استفاده میشد و مزایا و معایب هرکدوم به تفسیر صحبت کردیم و در انتها بهترین و آخرین روش یعنی OAuth2 رو کمی معرفی کردیم. در این مقاله قصد داریم بیشتر درمورد OAuth2، فرآیندها، کامپوننت ها و توکن های این پروتکل صحبت کنیم.
پروتکل OAuth2 یک پروتکل امنیتی است که به عنوان Authorization Protocol هم معرفی میشه. هدف اصلی این استاندارد اینه که Resource Owner (کاربر) مجوزی برای دسترسی به یک سری منابع محدود (Protected Resource) به یک کلاینت اعطا کند.
با توجه به اینکه اساس این پروتکل اعطا کردن مجوز دسترسی به یک Client application است، این پروتکل رو با نام Delegation Protocol هم معرفی میکنند.
این نکته رو فراموش نکنید که کلاینت ها باید از قبل در Authorization Server ثبت نام کنند. (یعنی سایتی که ما در قسمت اول پیاده سازیش رو استارت زدیم ;) ابتدا باید در Authorization Server اینستاگرام ثبت نام کرده باشه و یک شناسه ای تحت عنوان client_id دریافت کنه.) اما این به این معنی نیست که کلاینت میتونه با داشتن client_id در سیستم Authorized بشه. درواقع این کاربر یا همون Resource Owner هست که یک کلاینت رو برای بخشی از Protected Resource های خودش Authorize میکنه.
به عبارت دیگه مجوز از طرف یک کاربر مشخص به یک کلاینت مشخص اعطا میشه. بنابراین زمانی که کلاینت درخواست دسترسی به منابع یک کاربر رو ارسال میکنه، کلاینت باید از قبل توسط همان کاربر Authorize شده باشه. (تصمیم گیرنده اصلی کاربر است)
این استاندارد از چندین کامپوننت اصلی تشکیل شده که ارتباط این کامپوننت ها با همدیگه منجر به ایجاد یک OAuth2 Transaction (فرآیند OAuth) میشه.
به طور خلاصه OAuth2 در دو مرحله خلاصه میشه:
- چطور یک توکن رو از Authorization Server بگیریم؟
- چطور از توکن به دست آمده برای دسترسی به منابع Protected استفاده کنیم؟
همانطور که در قسمت قبل اشاره کردیم، چهار نقش اصلی در پروتکل OAuth2 وجود داره:
هر نقش وظایف متفاوتی رو برعهده داره، اما در نهایت تعامل این نقش ها با همدیگه باعث میشه که پروتکل OAuth2 کار کنه. در این قسمت قصد داریم جزئیات بیشتری از هرکدوم ارائه بدیم:
کلاینت یک اپلیکیشن موبایل یا وب است که قصد داره از طرف یک Resource Owner به یک Protected Resource دسترسی داشته باشه. کلاینت از پروتکل OAuth2 برای به دست آوردن این دسترسی استفاده میکنه.
کلاینت کمترین وظیفه رو در فرآیند OAuth2 برعهده داره. تنها کاری که یک کلاینت باید انجام بده ارسال درخواست برای گرفتن Access Token و سپس استفاده از این توکن در درخواست های Protected Resource های کاربر هست. درواقع کلاینت اصلا درجریان نحوه گرفتن مجوز از کاربر، تولید توکن و اعتبارسنجی آن نیست. کلاینت حتی نیازی نداره که درمورد محتوای توکن چیزی بدونه. میشه گفت کلاینت با Access Token مثل یه رشته ثابت برخورد میکنه که باید در تمام درخواست های Protected Resource ارسال بشه.
درمورد منابع در قسمت قبل توضیح مفصلی دادیم. مجددا این نکته را یادآوری می کنیم که Resource ها منابعی هستند که از طریق پروتکل HTTP دردسترس هستند. اما Protected Resource ها منابعی هستند که برای دسترسی به آنها نیاز به اعتبارسنجی داریم. در OAuth2 منظور از اعتبارسنجی همان Access Token هست. زمانی که کلاینت درخواستی رو به یک Protected Resource ارسال میکنه، اعتبار توکن با کمک Authorization Server بررسی میشه و اگه توکن معتبری همراه با درخواست فرستاده شده باشه، Protected Resource اطلاعات موردنیاز کلاینت رو پردازش و ارسال میکند.
کاربر همان موجودیتی است که به یک Protected Resource دسترسی داره و قصد داره این دسترسی رو به یک کلاینت اعطا کنه. در بیشتر مواقع (همچنین در سناریوی ما) کاربر یک انسان است، اما این رو هم درنظر بگیرید که Resource Owner میتواند یک کلاینت دیگر باشد.
کاربر با دو نقش Client و Authorization Server در ارتباط است. در وهله اول کاربر به کلاینت میگه که یک سری از کنترل ها رو میخواد به اون بسپاره (دسترسی به Protected Resource) و بعد به Authorization Server اطمینان میده که با این درخواست دسترسی کلاینت موافق هست. (این دریافت مجوز عمدتا از طریق یک صفحه وب انجام میشه که در زیر میتونید نمونه اشو ببینید.)
اگر به تصویر دقت کنید در ابتدا نوشته شده که کلاینت My Site Feed قصد گرفتن مجوزهای زیر رو داره و در ادامه مجوزهای موردنیاز لیست شده. به این صفحه اصطلاحا صفحه رضایت نامه کاربر هم گفته میشه. Resource Owner رضایت خودش رو از این اعطای مجوز اعلام میکنه.
همانطور که در ابتدای مقاله هم گفته شد در OAuth2 تصمیم گیرنده اصلی Resource Owner است.
اصلی ترین نقش در پروتکل OAuth2 متعلق به Authorization Server است. وظایف این کامپوننت به شرح زیر است:
موارد ذکر شده اصلی ترین وظایف Authorization Server است و بسته به سیاست های کاری شرکت میتواند گسترده تر هم شود.
تا اینجا متوجه شدیم که توکن نقش اصلی رو در اعتبارسنجی برعهده داره، درواقع تمام فرآیند OAuth2 در دو مرحله زیر در ارتباط مستقیم با توکن است:
اما Access Token تنها توکن موجود در OAuth2 نیست. در این بخش بیشتر در این خصوص صحبت خواهیم کرد.
توکن Access توسط Authorization Server برای کلاینت صادر میشه و نشان دهنده دسترسی هایی است که از طرف Resource Owner به کلاینت واگذار شده.
پروتکل OAuth فرمتی برای توکن ها تعیین نکرده، بنابرین این وظیفه OAuth Provider (مثل اینستاگرام) است که براساس سیستم خود، ساختار و محتوای توکن رو تعیین کند.
همانطور که قبلا هم اشاره شد، کلاینت چیزی درمورد محتوا و ساختار توکن ها نمیداند، اصلا نیازی به دانستن آن ندارد. تنها کاری که کلاینت با توکن دارد، درخواست دریافت توکن و ارسال توکن در هر درخواست به Protected Resource است.
اما از آنجایی که Authorization Server صادر کننده توکن و Protected Resource دریافت کننده توکن است، باید مشترکا درمورد ساختار، محتوا و نحوه پارس کردن آن اطلاعات کافی داشته باشند.
توکنی که کلاینت به نام Access Token دریافت میکنه، بعد از مدتی منقضی میشه، یعنی اگه کلاینت اون Access Token رو در ریکویست به Protected Resource ارسال کنه، با این ارور مواجه میشه که توکن فرستاده شده معتبر نیست و باید توکن جدید گرفته بشه. پس ما مجددا باید فرآیند OAuth رو تکرار کنیم که با فرستادن کاربر به Authorization Server و تایید کردن مجوزها توسط Resource Owner شروع میشه.
در اکثر OAuth2 Provider ها میزان اعتبار Access Token یک ساعته، یعنی کلاینت هر یک ساعت یکبار باید کاربر رو به Authorization Server بفرسته تا بتونه Access Token جدید بگیره. کاملا مشخصه که این رفت و آمدها از حوصله کاربر خارجه. روش جایگزین استفاده از Refresh Token است.
توکن Refresh مانند Access Token توسط Authorization Server برای کلاینت صادر میشه. مشخصات اصلی Refresh Token کاملا شبیه Access Token است.
تنها تفاوت Refresh Token با Access Token در این است که Refresh Token برای Protected Resource ارسال نمی شود. بلکه هر زمان که اعتبار Access Token از بین رفت (مثلا هر یک ساعت یکبار) کلاینت درخواست دریافت توکن جدید رو به Authorization Server ارسال میکنه و این درخواست باید شامل Refresh Token معتبر باشه.
مدت اعتبار Refresh Token هم مانند Access Token در میان Provider ها مشترک نیست. اما میانگین میتوان 30 روز را درنظر گرفت.
درنتیجه هر زمان که اعتبار Access Token تمام شد، کلاینت باید درخواستی برای گرفتن توکن جدید ارسال کند و این فرآیند بدون دخالت Resource Owner انجام میشه. البته این به شرطی است که کلاینت Refresh Token معتبر داشته باشد. اگر اعتبار Refresh Token هم تمام شده باشد، چاره ای به جز تکرار کردن فرآیند اولیه OAuth2 نداریم.
نمودار زیر رو درنظر بگیرید:
دامنه دسترسی (Scope) را همان Permission در یک سیستم ACL درنظر بگیرید. زمانی که کلاینت درخواست Authorization رو به Authorization Server ارسال میکنه، Scope های موردنیاز رو تعیین میکنه. Authorization Server این Scope های درخواستی را به کاربر نمایش میده و به ازای آن ها از کاربر میخواد که کلاینت را Authorize کند.
پروتکل OAuth تنها مفهوم و یک سری از شرایط تعریف Scope را تعیین کرده است و وظیفه تعریف کردن Scope ها به عهده Protected Resource هست. برای مثال اینستاگرام می تواند Scope های زیر را برای دسترسی به API خود تعریف کند.
فرض کنید کلاینتی با دو اسکوپ read_profile و public_resources درخواستی برای گرفتن Access Token ارسال کرده است. در این صورت کلاینت تنها میتواند به این دو بخش از API دسترسی داشته باشد. برای مثال اگر کلاینت درخواستی برای ویرایش پروفایل کاربر ارسال کند، Protected Resource پس از پارس کردن Access Token و بررسی Scope های آن متوجه می شود که کلاینت مجوز دسترسی به این بخش را ندارد در نتیجه پاسخ 403 برمیگرداند.
OAuth2 in Action 1st edition. Manning Publications Co.