مجوزی که در این بخش به معرفی آن خواهیم پرداخت Authorization Code میباشد که از رایجترین Grant ها در پروتکلOAuth میباشد. این Grant توسط برنامههای وب و بومی (native application) برای به دست آوردن Access Token به کار میرود. زمانی که یک کاربر، دسترسی برنامه به اطلاعات را تایید کند، Access Token صادر خواهد شد. شکل زیر روند Authorization Code را نشان میدهد. برای روشن شدن موضوع، شکل را بر اساس یک مثال شرح میدهیم.
1- فرض کنید یک کاربر از طریق مرورگر میخواهد در یک برنامه لاگین کند که این برنامه همان کلاینت میباشد.
2- برای لاگین، علاوه بر امکان لاگین خود برنامه کلاینت، گزینهی login with google نیز وجود داشته و کاربر امکان انتخاب دارد. کاربر با انتخاب این گزینه به سرور اصلی OAuth هدایت شده و در حقیقت کلاینت درخواست خود را برای دسترسی به اطلاعات کاربر، به Authorization Server ارسال میکند. در این حالت پنجره جدیدی باز میشود تا کاربر در آن لاگین کند.
3- سپس کاربر در Authorization Server لاگین کرده و درخواست کلاینت را تایید میکند.
4- کاربر به همراه مقدار Authorization Code دوباره به کلاینت هدایت میشود.
5- بعد از دریافت Authorization Code توسط کلاینت، آن را در درخواست Access Token بهAuthorization Server میفرستد.
6- در انتها Authorization Server، بر اساس Authorization Code که در درخواست کلاینت وجود دارد، درخواست کلاینت را تایید کرده و Access Token را به کلاینت میدهد.
در ادامه به تشریح کامل روند Authorization Code خواهیم پرداخت.
1- دریافت اجازه کاربر
ابتدا کلاینت باید تصمیم بگیرد که مجوزهای مورد نظر خود را درخواست کند، برای این کار، کاربر را برای لاگین و دریافت مجوز به یک پنجره دیگر مرورگر ارسال میکند.
در واقع برای شروع روندAuthorization ، (مثلا با کلیک بر روی دکمهی login with google) کلاینت یک URL مانند زیر را ایجاد و آن را در یک پنجره ی دیگر مرورگر باز میکند و وقتی کاربر از این URL بازدید میکند، Authorization Server از کاربر نهایی میپرسد که آیا میخواهد به درخواست این کلاینت مجوز دهد یا خیر.
https://authorization-server.com/auth
?response_type=code
&client_id=29352915982374239857
&redirect_uri=https://example-app.com/redirect
&scope=create+delete
&state=xcoiv98y2kd22vusuye3kch
هر کدام از پارامترهایهای موجود در URL بالا به شرح زیر میباشند:
· response_type : این پارامتر با مقدار code، به سرور مجوز یا Authorization Server میگوید که کلاینت در حال شروع روند Authorization Code میباشد.
· client_id : شناسه عمومی کلاینت، هنگامیکه برنامهنویس برای اولین بار کلاینت را ثبت کرد، به آن داده شده است و Authorization Server، کلاینت را با این شناسه تشخیص میدهد.
· redirect_uri : به Authorization Server میگوید که کاربر را پس از تایید درخواست، به این آدرس بازگرداند.
· scope : راهی برای محدود کردن دسترسی یک کلاینت به دادههای کاربر است. Scope به مشتریان API اجازه میدهد هنگام درخواست مجوز برای دسترسی به یک حساب، مجموعه خاصی از مجوزها را درخواست کنند و در حقیقت برای محدود کردن دسترسی کلاینت به حساب کاربر میباشند. به عنوان مثال، در یک کلاینت امکاناتی مانند خواندن، نوشتن، حذف و بهروزرسانی برای یک کاربر فراهم شده است. با استفاده از scopeها میتوانیم به برنامههای کاربردی جهت انجام هر کدام از این کارها، دسترسی دهیم.
برخی از کلاینت ها فقط برای شناسایی کاربر از OAuth استفاده میکنند، بنابراین تنها به دسترسی به شناسه کاربر و اطلاعات اولیه پروفایل نیاز دارند. از طرفی دیگر ممکن است کلاینتی نیاز به دانستن اطلاعات حساس تر مانند روز تولد کاربر داشته باشد، یا نیاز به ارسال مطالب از طرف کاربر یا تغییر دادهها داشته باشد. Scope روشی برای کنترل دسترسی و کمک به کاربر برای شناسایی مجوزهایی است که به کلاینت اعطا میکنند.
· state : این مورد برای جلوگیری از حملات CSRF استفاده میشود. کلاینت یک رشته تصادفی تولید میکند و آن را در درخواست قرار میدهد. پس از آنکه کاربر مجوز برنامه را صادر کرد، کلاینت باید بررسی کند که همان مقدار را برگردانده است یا خیر.
2- بازگشت به کلاینت
اگر کاربر درخواست را تایید کند، Authorization Server، مرورگر را به redirect_uri مشخص شده توسط کلاینت هدایت میکند و یک code و یک state را به رشته پرس و جو (query string) اضافه میکند.
برای مثال، کاربر دوباره به یک URL مانند زیر هدایت میشود.
https://example-app.com/redirect
?code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
&state=xcoiv98y2kd22vusuye3kch
مقدار state همان مقداری خواهد بود که کلاینت در ابتدا در درخواست قرار داده است. انتظار داریم که کلاینت بررسی کند که state در حالت تغییر مسیر با state اولیه خود مطابقت دارد. این کار برای محافظت در برابر حمله CSRF و سایر حملات مرتبط میباشد.
مقدار code، همان Authorization Code تولید شده توسط Authorization Server میباشد. این کد نسبتا کوتاه است و تولید آن بسته به سرویس OAuth بین 1 تا 10 دقیقه طول میکشد.
3- مبادله Authorization Code برای یک Access Token
اکنون که کلاینت دارای کد مجوز یا همان Authorization Code است، میتواند از آن برای به دست آوردن Access Token استفاده کند. کلاینت با استفاده از پارامترهای زیر یک درخواست POST را به Token Endpoint سرویس (token endpoint یکی از درگاه های Authorization Server است که وظیفه برگرداندن Token را بر عهده دارد.) ارائه میدهد:
POST /oauth/token HTTP/1.1
Host: authorization-server.com
grant_type=authorization_code
&code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
&redirect_uri=https://example-app.com/redirect
&client_id=29352915982374239857
&client_secret=xxxxxxxxxx
· grant_type = authorization_code: این پارامتر به token endpoint اشاره میکند که کلاینت از نوع Authorization Code Grant استفاده میکند.
· code: این پارامتر همان کد مجوز (authorization code) است که کلاینت قبلا از Authorization Server دریافت کرده است.
· redirect_uri : همان URI تغییر مسیر که هنگام درخواست کد از آن استفاده شد. برخی از APIها به این پارامتر احتیاج ندارند، بنابراین باید مستندات API خاصی را که به آن دسترسی دارید، حتما بررسی کنید.
· client_id : همان شناسه عمومی کلاینت که در مرحله قبل نیز ارسال شده بود
· client_secret: یک راز شناخته شده فقط برای کلاینت و Authorization Server است. این مقدار تضمین میکند که درخواست برای دریافت Access Token فقط از طریق کلاینت ساخته شده است، و نه از یک حمله کننده بالقوه که ممکن است Authorization Code را ردیابی کرده باشد.
Token endpoint، تمام پارامترهای موجود در درخواست را بررسی کرده و اطمینان حاصل میکند که کد هنوز منقضی نشده است و client_id و client_secret مطابقت دارد به این معنی که client_secret مربوط به همان client_id میباشد. اگر همه چیز درست باشد، یک Access Token ایجاد میکند و آن را در پاسخ باز میگرداند:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create+delete"
}
جریان Authorization Code کامل شد. اکنون کلاینت دارای یک Access Token است که میتواند در هنگام درخواست API از آن استفاده کند. در پاسخی که کلاینت از Authorization Server دریافت میکند علاوه بر Access Token اطلاعات دیگری نیز وجود دارد. مانند:
· token_type: نوع توکن را نشان میدهد.
· expires_in: تاریخ انقضای توکن
· refresh_token: همانطور که در بخش اصطلاحات توضیح داده شد، بعد از منقضی شدن توکن، برای دریافت توکن جدید استفاده میشود.
· scope: نشان دهندهی محدودیتهای دسترسی است.
4- چه زمانی باید از جریان Authorization Code استفاده کنیم؟
همانطور که قبلا گفته شد، جریان Authorization Codeبهترین استفاده را در برنامههای وب و موبایل دارد. از آنجا که Authorization Code Grant یک مرحله اضافی جهت تبادل Authorization Code برای Access Token دارد، یک لایه امنیتی اضافی را ارائه میدهد که در نوع Implicit Grant وجود ندارد (در فصل های بعد این نوع را توضیح میدهیم). مرحله تبادل کد تضمین میکند که یک مهاجم قادر به رهگیری Access Token نیست، زیرا همیشه Access Token از طریق یک کانال امن بین کلاینت و Authorization Server ارسال میشود.
در مستندات اصلی OAuth 2.0، یک Grant با نام PKCE زیر مجموعه Grant Type آورده شده است. در حقیقت یک افزونه یا Extension میباشد که جهت جلوگیری از حملات خاص در روند Authorization Code میتوان از آن استفاده کرد. توصیه میشود اگر از جریان Authorization Code در یک برنامه تلفن همراه یا هر نوع کلاینت دیگری که نمیتواند client secret را مخفی نگه دارد، استفاده میکنید، باید از افزونه PKCE استفاده کنید، که آن را در برابر حملات محافظت کند. در مورد PKCE در بخش بعد بیشتر صحبت میکنیم.