متن حاضر قسمت چهارم از سری مقالات آشنایی به پروتکل OAuth2 است، اگر سه قسمت قبلی رو مطالعه نکردید، قبل از مطالعه این قسمت، سری به سه لینک زیر بزنید.
در دو قسمت ابتدایی درمورد نقش ها و کامپوننت های اصلی پروتکل OAuth2 صحبت کردیم و گفتیم که تعامل این کامپوننت ها با همدیگه منجر به ایجاد یک فرآیند OAuth میشه. در این قسمت قصد داریم کمی بیشتر در خصوص این تعامل بحث کنیم.
پروتکل OAuth2 مبتنی بر پروتکل HTTP است. حتما میدونید که اساس پروتکل HTTP، درخواست (Request) و پاسخ (Response) است.
خلاصه فرآیند پروتکل HTTP: در مرحله اول کلاینت درخواستی رو به سرور ارسال میکنه، سرور درخواست رو پردازش و پاسخ رو تولید میکنه. درنهایت پاسخ رو از طریق Connection موجود برای کلاینت ارسال میکنه و Connection قطع میشه.
با وجود سادگی تراکنش HTTP، پروتکل OAuth2 طی یک Request-Response ساده انجام نمیشه و شامل چندین درخواست-پاسخ است.
همانطور که در دو قسمت قبلی هم اشاره شد، یک OAuth Transaction به دو بخش اصلی تقسیم میشه:
برای مرحله اول چندین Flow در پروتکل OAuth2 تعریف شده که هر کدوم روش متفاوتی برای گرفتن Access Token دارند. تفاوت اصلی این Flow ها که اصطلاحا به آن ها Authorization Grant Type هم گفته میشه در درخواست-پاسخ های آن هاست.
به طور کلی چهار Authorization Grant Type وجود دارد:
در این Flow گرفتن Access Token از Authorization Server در یک مرحله انجام می شود.
مراحل نمودار بالا را برای سناریوی اصلی تعریف می کنیم:
1. در مرحله اول کاربر به کلاینت اعلام میکنه که قصد داره با سرویس مدنظر که اینجا اینستاگرام هست لاگین کنه.
2. کلاینت درخواست زیر را به Authorization Endpoint اینستاگرام ارسال میکنه.
GET https://api.instagram.com/oauth/authorize ?client_id={your-client-id}, &redirect_uri={your-redirect-uri}, &response_type=token, &scope={required-scopes-like-user_profile}
توجه داشته باشید که:
پس از ارسال درخواست، با توجه به وضعیت Authentication کاربر، کاربر به صفحه لاگین یا Consent ریدایرکت میشه. در این صفحه کاربر باید به سیستم لاگین و در نهایت رضایت خودش رو از دسترسی کلاینت به Scope های درخواست شده اعلام کنه.
3. بعد از لاگین شدن و تایید درخواست توسط کاربر، Authorization Server اطلاعات کاربر که همون نام کاربری و رمزعبور هست رو بررسی میکنه و اگه اطلاعات معتبر بود، access_token رو میسازه و به کلاینت ریدایرکت میکنه.
GET /your-redirect-uri#access_token={your_access_token}&token_type=Bearer
4. کلاینت باید این access_token رو در جایی ذخیره کنه.
5. از این مرحله به بعد هر زمانی که کلاینت قصد داشت به اینستاگرام درخواست بزنه (مثلا درخواست گرفتن اطلاعات کاربری) باید همراه با درخواستش access_token رو ارسال کنه.
GET https://graph.instagram.com/me &access_token={user's-access-token}
6. اینستاگرام اعتبار access_token دریافتی رو به کمک Authorization Server بررسی میکنه و اگه مشکلی وجود نداشت، درخواست کلاینت رو پردازش میکنه و جواب رو به کلاینت میفرسته.
نکات زیر را در استفاده از Implicit Grant Type به خاطر بسپارید:
در این Flow گرفتن Access Token از Authorization Server در دو مرحله انجام میشه. در مرحله اول با ارسال درخواست به Authorization Endpoint کدی با نام Authorization Code دریافت میشه، درنهایت این
کد به Token Endpoint فرستاده میشه و با Access Token مبادله میشه.
مراحل نمودار بالا را برای سناریوی اصلی تعریف می کنیم:
1. در مرحله اول کاربر به کلاینت اعلام میکنه که قصد داره با سرویس مدنظر که اینجا اینستاگرام هست لاگین کنه.
2. کلاینت درخواست زیر را به Authorization Endpoint اینستاگرام ارسال میکنه.
GET https://api.instagram.com/oauth/authorize ?client_id={your-client-id}, &redirect_uri={your-redirect-uri}, &response_type=code, &scope={required-scopes-like-user_profile}
توجه داشته باشید که:
پس از ارسال درخواست، با توجه به وضعیت Authentication کاربر، کاربر به صفحه لاگین یا Consent ریدایرکت میشه. در این صفحه کاربر باید به سیستم لاگین و در نهایت رضایت خودش رو از دسترسی کلاینت به Scope های درخواست شده اعلام کنه.
3. بعد از لاگین شدن و تایید درخواست توسط کاربر، Authorization Server اطلاعات کاربر که همون نام کاربری و رمزعبور هست رو بررسی میکنه و اگه اطلاعات معتبر بود، authorization_code رو میسازه و به کلاینت ریدایرکت میکنه.
GET /your-redirect-uri#code={your-authorization-code}&token_type=Bearer
4. در این مرحله کلاینت authorization_code رو از URL اکسترکت میکنه و درخواست تبادل این کد با access_token رو ارسال میکنه.
POST https://api.instagram.com/oauth/token grant_type=authorization_code& client_secret={your-client-secret} redirect_uri={your-redirect-uri} &code={your-authorization-code}
5. سرور Authorization اطلاعات ارسال شده مثل redirect_uri و client_secret رو بررسی میکنه و درصورت صحت برای کاربر access_token رو تولید کرده و در پاسخ ارسال میکنه.
HTTP 200 OK { "access_token": "{users-access-token}", "token_type": "Bearer" }
کلاینت باید این access_token رو در جایی ذخیره کنه.
5. از این مرحله به بعد هر زمانی که کلاینت قصد داشت به اینستاگرام درخواست بزنه (مثلا درخواست گرفتن اطلاعات کاربری) باید همراه با درخواستش access_token رو ارسال کنه.
GET https://graph.instagram.com/me &access_token={user's-access-token}
6. اینستاگرام اعتبار access_token دریافتی رو به کمک Authorization Server بررسی میکنه و اگه مشکلی وجود نداشت، درخواست کلاینت رو پردازش میکنه و جواب رو به کلاینت میفرسته.
نکات زیر را در استفاده از Authorization grant type به خاطر بسپارید:
تا به حال هر زمان که بحث از OAuth2 شد، صحبت از کاربر به میان اومد. گفتیم که هدف اصلی OAuth2 اینه که کاربر مجوز دسترسی به اطلاعات Protected خودش رو به یک کلاینت اعطا کند. حال فرض کنید اصلا کاربری درکار نباشد و دو سیستم قرار است بدون هیچ کاربری با همدیگر ارتباط برقرار کنند، در این حالت از جریان Client Credential استفاده می شود.
1. در مرحله اول کلاینت درخواست خود را به Token Endpoint ارسال میکند.
POST https://api.instagram.com/oauth/token grant_type=client_credentials &client_id={your-client-id} &client_secret={your-client-secret} &scope={required-scopes}
2. سیستم Authorization پس از دریافت درخواست، ابتدا اطلاعات کلاینت رو بررسی میکند و اگر کلاینت معتبر بود access_token کلاینت رو تولید و در Response به کلاینت ارسال میکند.
HTTP 200 OK { "access_token": "{client's-access-token}", "scope": "{requested-scopes}", "token_type": "Bearer" }
4. کلاینت باید این access_token رو در جایی ذخیره کنه.
5. از این مرحله به بعد هر زمانی که کلاینت قصد داشت به Protected Resource درخواست بده باید همراه با درخواستش access_token رو ارسال کنه.
GET https://graph.instagram.com/explore &access_token={client's-access-token}
6. اینستاگرام اعتبار access_token دریافتی رو به کمک Authorization Server بررسی میکنه و اگه مشکلی وجود نداشت، درخواست کلاینت رو پردازش میکنه و جواب رو به کلاینت میفرسته.
نکات زیر را در استفاده از Client credentials grant type درنظر بگیرید:
مثالی از کاربرد Client credential grant type
فرض کنید سیستمی برای پردازش وضعیت آب و هوایی دنیا دارید. در این سیستم وضعیت آب و هوای تمام شهرها و کشورها پردازش میشه و اطلاعات مفیدی مثل پیش بینی وضعیت آب و هوایی به دست میاد. شما قصد دارید سیستم تون رو در اختیار کلاینت های دیگه بزارید و از این کار درامدزایی کنید. یکی از روش های پیاده سازی استفاده از این Grant type است. به این صورت که شما برای هر کلاینتی که میخواهد از سرویس شما استفاده کند یک client_id و client_secret میسازید و کلاینت ها ابتدا با استفاده از این دو مقدار به سیستم شما Authenticate می شوند و سپس می توانند از API شما استفاده کنند.
به طور خلاصه میتوان گفت که زمانی که ارتباط سرویس به سرویس دارید یکی از راه های پیاده سازی، Client credential grant type است.
در این Flow کلاینت اطلاعات کاربری اینستاگرام رو از کاربر درخواست میکنه و خودش مستقیم به اینستاگرام درخواست لاگینش رو میفرسته و توکن رو دریافت میکنه.
1. کاربر ابتدا اطلاعات کاربری خود را در اختیار کلاینت قرار می دهد.
2.کلاینت درخواست خود را به Token Endpoint ارسال میکند.
POST /token grant_type=password &client_id={client-id} &client_secret={client-secret} &scope={required-scopes} &username={username} &password={password}
همانطور که می بینید اطلاعات کاربر در درخواست به صورت مستقیم به Authorization Server ارسال می شود.
3. در این مرحله Authorization Server اطلاعات کلاینت و کاربر رو بررسی میکنه و اگه اطلاعات معتبر بود، access_token رو میسازه و در پاسخ به کلاینت ارسال میکنه.
4. کلاینت باید این access_token رو در جایی ذخیره کنه.
5. از این مرحله به بعد هر زمانی که کلاینت قصد داشت به اینستاگرام درخواست بزنه (مثلا درخواست گرفتن اطلاعات کاربری) باید همراه با درخواستش access_token رو ارسال کنه.
6. اینستاگرام اعتبار access_token دریافتی رو به کمک Authorization Server بررسی میکنه و اگه مشکلی وجود نداشت، درخواست کلاینت رو پردازش میکنه و جواب رو به کلاینت میفرسته.
نکات زیر را در استفاده از Resource owner credential grant type درنظر بگیرید:
اگه قسمت اول رو با دقت مطالعه کرده باشید، این جریان همان "راه حل دوم" است. درست است که گفتیم راه حل های قبل از OAuth2 همگی دارای معایبی هستند، اما این جریان برای زمان هایی که نمی خواهیم کاربر به طور مستقیم با Authorization Server در ارتباط باشد مناسب است. هر چند که طبق استاندارد تعریف شده بهتر است تنها در شرایط خاص از این جریان استفاده کرد.