Mohsen Farokhi - محسن فرخی
Mohsen Farokhi - محسن فرخی
خواندن ۷ دقیقه·۲ سال پیش

مفاهیم OAuth و OpenID Connect - بخش چهارم

در بخش سوم، Bearer Token و Refresh Token را بررسی کردیم.

در این بخش، به موضوعات پیرامون Authentication و OpenID Connect (OIDC) می پردازیم.

در OAuth به مساله delegated authorization می پردازیم و در بخش های قبلی آن را بررسی کردیم. اما زمانی که هنوز موضوع OIDC مطرح نشده بود، افراد و سازمان هایی بودند که از authorization delegation برای authentication استفاده می کردند.

برای مثال، clientها user agent کاربر را با پارامترهای grant_type و scope، به ترتیب با مقادیر code و signin، به authorization endpoint ارسال می کردند. بعد از redirection و دریافت access token، آن را به یک endpoint برای مثال User Info ارسال می کردند و از آن مشخصات کاربر را دریافت و کاربر را authenticate می کردند.

این مساله مشکلاتی که به همراه داشت که باعث بوجود آمدن پروتکل OIDC به عنوان یک لایه بر روی OAuth شد.

در جریان authentication، سرویس Identity Provider را داریم که هویت را تایید می کند. و Relying Party (RP) را داریم که authentication را به یک سرویس دیگر واگذار کرده است. در اینجا موضوع دسترسی نیست و هدف شناسایی هویت کاربران است.

تصور کنید که شما یک وبسایت دارید و کاربران می خواهند در آن login کنند. شما از طریق سایت خود، کاربران را به identity provider هدایت می کنید. بعد از عملیات login، یک id token به وبسایت برمی گردد. این id token در مورد هویت کاربران است و مخاطب آن نیز RP است که در اینجا وبسایت شما می باشد.

بنابراین resource server، مخاطب access token است و RP یا client، مخاطب id token می باشد.

اگر با یک access token در طرف باشیم که دو هدف تشخیص هویت و دسترسی ها را دنبال کند، از لحاظ امنیتی ممکن است اتفاقاتی را ایجاد کند.

معمولا clientها در جریان دریافت id token، اگر اولین login کاربر باشد یک حساب کاربری برای کاربر می سازند و کوکی آن را ایجاد می کنند. بنابراین عمر id token کوتاه مدت است و فقط برای زمان تشخیص هویت کاربرد دارد.

در نتیجه access token وظیفه delegate کردن دسترسی کاربر به client را دارد و اصطلاحا به آن authorization delegation می گوییم. اما id token به دسترسی ها نمی پردازد و صرفا برای تشخیص هویت در RP می باشد.

دو قابلیتی که OIDC بر روی OAuth فعال می کند، شناسایی هویت کاربران و دریافت اطلاعات پروفایلی آنها می باشد.

در تصویر بالا، RP عملیات authentication request را از طریق redirection انجام می دهد. end user آن را authenticate می کند و response که هویت کاربری است که authentication را انجام داده است، به دست RP می رسد. RP می تواند با استفاده از این token که با فرمت JWT است، درخواست اطلاعات پروفایلی آن کاربر را هم انجام دهد.


در OIDC، با سه flow کلی روبرو هستیم.

  • Authorization code flow
  • Implicit flow
  • Hybrid flow

جریان authorization code مشابه authorization code flow در OAuth می باشد. در این جریان، client درخواست خود را همراه پارامترهایی که می خواهد، آماده می کند و redirection می کند. end user عملیات login را انجام می دهد و اگر consent وجود داشته باشد به آن اجازه می دهد و عبور می کند. authorization server یک authorization code را به سمت client ارسال می کند. client آن را به همراه id و secret خود مجددا ارسال می کند و در پاسخ، id_token و access_token را دریافت می کند. client از طریق id_token، کاربر را authenticate می کند.

در OIDC، دو scope استاندارد با نام های openid و profile در پروتکل تعریف شده است. openid، در مورد user identifier صحبت می کند و وجود آن الزامی است. و profile شامل داده هایی است که در OIDC استاندارد شده است و می تواند از سمت identity provider برگردد.

از پارامتر های دیگر، response_type را داریم که با مقدار code پر می شود. client_id و redirect_uri نیز از جمله پارامترهایی هستند که باید توسط client ارسال شوند.

در response نیز code و state توسط client دریافت می شود و برای دریافت token استفاده می شود.

در مرحله token request، پارامتر grant_type با مقدار authorization_code، پارامتر code با مقدار دریافت شده و همچنین پارامتر redirect_uri به identity provider ارسال می شود.

در response این مرحله، id_token به همراه access_token و سایر مقادیر دیگر به دست client می رسد.

در id_token عنوان sub به معنای subject با مقدار شناسه کاربر وجود دارد و اطلاعات اضافه تری از کاربر وجود ندارد. برای دریافت اطلاعات اضافه تری از کاربر، client باید access_token که profile scope داشته باشد را به userinfo endpoint ارسال کند و اطلاعات کاربر را دریافت کند.

نکته ای که هست، id_token هیچوقت به سمت api ارسال نمی شود و مخاطب آن authorization server می باشد.

اگر در تنظیمات client در authorization server، پروپرتی AlwaysIncludeUserClaimsInIdToken را true کنیم، می توانیم اطلاعات کاربر را همیشه بر روی id_token داشته باشیم.


جریان implicit مشابه implicit flow در OAuth است. implicit flow از طریق redirect کردن user agent شروع می شود. بعد از اینکه کاربر خودش را در authorization server معرفی می کند، به سمت client یک redirection انجام می شود و access token به همراه id token، از این طریق به دست client می رسد.

تا قبل از این، در redirectionهایی که انجام می دادیم، برای مقدار response_type از یک مقدار برای مثال code استفاده می کردیم. استانداردی به نام OAuth 2.0 Multiple Response Type Encoding Principle وجود دارد که در مورد response typeهای چند مقدار صحبت می کند و در implicit flow این مساله را مشاهده می کنیم.

در implicit flow و در زمان انجام redirection، اگر از مقدار id_token token برای response type استفاده کنیم، مشخص می کند که id token و access token را با هم می خواهیم. و اگر از مقدار id_token برای response type استفاده کنیم، مشخص می کند که ما فقط به دنبال id token و تشخیص هویت کاربر هستیم.

در implicit flow پارامتر دیگری به نام nonce داریم که برای جلوگیری از حمله replay استفاده می شود. در این پارامتر، مقداری که در سمت client ساخته و نگهداری می شود، به سمت authorization server ارسال می شود و در redirect back به سمت client بر می گردد. client مقدار برگردانده شده را با مقدار نگهداری شده مقایسه می کند و مطمئن می شود که redirection ارسال شده از سمت authorization server، یک حمله replay نیست و کسی مجددا آن را call نکرده است.

به طور کلی implicit flow هم در OAuth برای access token delegation و هم در OIDC برای Authentication توصیه نمی شود.


جریان hybrid، از ترکیب authorization code flow و implicit flow شکل می گیرد. در این flow، در response type می توانیم سه مقدار code token ،code id_token و code id_token token مختلف داشته باشیم. توصیه می شود از مقدار code id_token در hybrid flow استفاده شود.

در response type با مقدار code id_token، یک client را در نظر بگیرید که آن را به دو قسمت front end و back end تقسیم می کنیم. یک resource server و یک authorization server هم داریم. redirection را با مقدار code id_token انجام می دهیم. در زمان redirection back به front end، اتفاقی که می افتد id token به ما برمی گردد و برای authenticate کردن کاربر می توانیم از آن استفاده کنیم.

همچنین یک authorization code هم دریافت می کنیم که برای back end می باشد و client از طریق back end می تواند code را با access_token که نیاز دارد exchange کند. در اصل از امکاناتی که هم در implicit flow و هم در authorization code داشتیم، همزمان استفاده می کنیم.

مقدار access_token در response بازگشتی، در حالت code token و code id_token token به سمت ما برمی گردد. و مقدار id_token، در حالت code id_token و code id_token token برمی گردد. مقدار code نیز در هر سه حالت بر می گردد.

در OIDC برای موضوع authentication، اگر client وجود داشته باشد که دارای backend می باشد، روشی که توصیه می شود استفاده از authorization code flow می باشد. اما اگر client به دو بخش front end و back end تقسیم می شود که id_token فقط در frontend کاربرد دارد، در این حالت hybrid flow می تواند گزینه خوبی باشد که id_token می تواند برای authentication استفاده شود و از code برای دسترسی به access_token بصورت back channel استفاده شود.


oauthOpenID ConnectIdentity Managementمحسن فرخی
شاید از این پست‌ها خوشتان بیاید