اولین باری که برای یک پروژه چندنفره با یک API خارجی کار می‌کردم، مشتری از من خواست که کاربر بتواند با حساب گوگلش وارد شود. من که تا آن روز فقط با احراز هویت سادهٔ یوزرنیم و پسورد کار کرده بودم، اولین پیشنهاد ذهنی‌ام این بود که فرم خودم را بسازم و رمز گوگل کاربر را بگیرم. چند دقیقه بعد فهمیدم این کار نه‌فقط غیراستاندارد است، بلکه از نظر امنیتی فاجعه است. راه‌حل درست چیز دیگری بود: OAuth. آن روز یکی از آن لحظه‌هایی بود که یک مفهوم فنی را واقعاً فهمیدم، چون در یک پروژهٔ واقعی به آن نیاز پیدا کردم.

OAuth یا Open Authorization، یک استاندارد باز برای مجوزدهی (Authorization) است که به کاربران امکان می‌دهد بدون این‌که رمز عبورشان را به سرویس سوم بدهند، به اپلیکیشن‌های دیگر اجازهٔ دسترسی محدود به منابعشان را بدهند. اگر تا امروز عبارت «ورود با گوگل» را روی سایتی دیده‌اید، دقیقاً همان OAuth در پشت صحنه اجرا می‌شود. مفهوم پایهٔ احراز هویت را در احراز هویت چیست و چه انواعی دارد؟ آورده‌ام؛ این مقاله، به مکانیزم دقیق OAuth و پیاده‌سازی‌اش می‌پردازد.

OAuth چیست و چه مسئله‌ای را حل می‌کند؟

OAuth یک استاندارد باز برای مجوزدهی است که اولین نسخه‌اش در سال ۲۰۰۷ توسط توییتر و چند شرکت دیگر معرفی شد. نسخهٔ فعلی استاندارد، OAuth 2.0 است که در سال ۲۰۱۲ منتشر شد و امروز پایهٔ اصلی احراز هویت و مجوزدهی در اکوسیستم APIهاست.

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

OAuth این سه مشکل را حل می‌کند: اپلیکیشن رمز عبور را نمی‌بیند، تنها به بخش مشخصی از داده‌ها دسترسی دارد، و کاربر می‌تواند هر زمان که بخواهد دسترسی را بدون تغییر رمز قطع کند. در تجربهٔ خودم، این سه ویژگی پایه‌ای، دلیل اصلی‌ست که OAuth به استاندارد اصلی مجوزدهی در دنیای مدرن تبدیل شده.

OAuth مثل دادن یک کلید محدود به خدمتکار است که فقط به اتاق پذیرایی دسترسی دارد، نه به گاوصندوق اتاق خواب. در سیستم احراز هویت سنتی، کارفرما کلید اصلی را به همه می‌داد.

تفاوت OAuth با احراز هویت: Authorization در برابر Authentication

یکی از بیشترین سوءبرداشت‌ها دربارهٔ OAuth، خلط کردن آن با احراز هویت است. در حالی که نامش Open Authorization است و به مجوزدهی مربوط می‌شود، نه به احراز هویت. تفاوت این دو را در تفاوت احراز هویت و مجوزدهی چیست؟ باز کرده‌ام. خلاصه:

  • احراز هویت (Authentication): شناسایی هویت کاربر. یعنی تأیید اینکه شما همان فردی هستید که ادعا می‌کنید.
  • مجوزدهی (Authorization): تصمیم‌گیری دربارهٔ اینکه کاربر چه کاری می‌تواند انجام دهد.

OAuth در لایهٔ مجوزدهی کار می‌کند و به‌تنهایی هویت کاربر را تأیید نمی‌کند. برای استفادهٔ OAuth به‌عنوان روش احراز هویت، استاندارد دیگری به نام OpenID Connect روی OAuth ساخته شده که لایهٔ هویتی را اضافه می‌کند. وقتی کاربر روی دکمهٔ «ورود با گوگل» کلیک می‌کند، در واقع OAuth + OpenID Connect با هم اجرا می‌شوند.

چهار نقش اصلی در OAuth

OAuth چهار نقش مشخص دارد که بدون درکشان، فهم جریان OAuth ممکن نیست:

نقش اول: Resource Owner یا صاحب منبع

کاربر نهایی که صاحب داده است. مثلاً خود شما که صاحب حساب گوگل هستید.

نقش دوم: Client یا اپلیکیشن

اپلیکیشنی که می‌خواهد به دادهٔ کاربر دسترسی پیدا کند. مثلاً یک اپلیکیشن مدیریت وظایف که می‌خواهد به تقویم شما دسترسی داشته باشد.

نقش سوم: Authorization Server یا سرور مجوزدهی

سروری که مسئول تأیید هویت کاربر و صدور توکن است. مثلاً سرور OAuth گوگل.

نقش چهارم: Resource Server یا سرور منبع

سروری که دادهٔ واقعی را نگه می‌دارد. گاهی این سرور با Authorization Server یکی است و گاهی جدا. مثلاً سرور تقویم گوگل.

تصویر ذهنی که در جلسات توضیح می‌دهم: فرض کنید می‌خواهید کلید خانه‌تان را به یک نظافتچی بدهید. Resource Owner خودتان هستید، Client نظافتچی، Authorization Server کلیدسازی معتبر، و Resource Server خودِ خانه. OAuth فرآیندی است که در آن نظافتچی با اجازهٔ شما، کلید مخصوص در ورودی را می‌گیرد، اما کلید گاوصندوق را ندارد.

مکانیزم OAuth: پنج گام اصلی

جریان استاندارد OAuth 2.0 (معروف به Authorization Code Flow) پنج گام اصلی دارد. این جریان در پروژه‌های وب رایج‌ترین است:

گام اول: درخواست مجوز

اپلیکیشن، کاربر را به صفحهٔ لاگین Google OAuth هدایت می‌کند. در آن آدرس، اپلیکیشن مشخص می‌کند که چه دسترسی‌هایی می‌خواهد (Scope)، مثل calendar.readonly یا profile. کاربر وارد حساب گوگلش می‌شود و صفحهٔ تأیید دسترسی را می‌بیند.

گام دوم: تأیید کاربر

اگر کاربر تأیید کند، Google کاربر را با یک کد موقت (Authorization Code) به آدرسی که اپلیکیشن تعیین کرده بود برمی‌گرداند. کد موقت معمولاً فقط چند دقیقه اعتبار دارد.

گام سوم: تبادل کد برای توکن

اپلیکیشن کد موقت را به Authorization Server می‌فرستد و درخواست Access Token می‌کند. این تبادل معمولاً در سمت سرور انجام می‌شود، نه در مرورگر کاربر.

گام چهارم: دریافت Access Token

Authorization Server پس از بررسی اعتبار Client، Access Token را به اپلیکیشن برمی‌گرداند. این توکن، مجوز دسترسی به منابع مورد نظر است و معمولاً بین ۱۵ دقیقه تا یک ساعت اعتبار دارد.

گام پنجم: دسترسی به منابع

اپلیکیشن با استفاده از Access Token، به Resource Server درخواست می‌فرستد. اگر توکن معتبر باشد، داده برگردانده می‌شود. بعد از انقضای توکن، اپلیکیشن می‌تواند با Refresh Token توکن جدید بگیرد، بدون اینکه کاربر مجبور به تأیید مجدد باشد.

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

انواع Grant Type و کاربرد هرکدام

OAuth 2.0 چند نوع Grant Type (نوع مجوز) دارد که هرکدام برای سناریوی خاصی طراحی شده‌اند:

Grant Typeسناریوی کاربردملاحظات امنیتی
Authorization Codeاپلیکیشن‌های وب با سرورامن‌ترین و رایج‌ترین
Authorization Code + PKCEاپلیکیشن‌های موبایل و SPAتوصیه‌شده برای کلاینت‌های عمومی
Client Credentialsارتباط سرور به سروربدون کاربر انسانی
Implicit (منسوخ)SPAهای قدیمیدیگر توصیه نمی‌شود
Resource Owner Password (منسوخ)سرویس‌های داخلی قدیمیدیگر توصیه نمی‌شود
Device Codeدستگاه‌های بدون مرورگرمثل تلویزیون و کنسول

قاعده‌ای که در پروژه‌ها رعایت می‌کنم: برای اپلیکیشن‌های وب و موبایل همیشه Authorization Code با PKCE. برای ارتباط سرور به سرور، Client Credentials. سه نوع منسوخ را کنار بگذارید، چون در نسخه‌های جدید استاندارد به‌عنوان ناامن شناخته شده‌اند.

Access Token و Refresh Token: قلب سیستم

دو نوع توکن در OAuth وجود دارد که هرکدام نقشی متفاوت دارند:

Access Token

این توکن، مجوز دسترسی به منابع است. اپلیکیشن با فرستادن آن در هدر درخواست، به‌سرور می‌گوید که مجاز به دسترسی است. Access Token معمولاً کوتاه‌مدت است (۱۵ دقیقه تا یک ساعت) تا اگر لو رفت، آسیب محدود بماند. Access Token می‌تواند یکی از دو ساختار داشته باشد:

  • Opaque Token: رشته‌ای تصادفی که سرور باید برای بررسی آن به Authorization Server مراجعه کند.
  • JWT (JSON Web Token): توکنی که حاوی اطلاعات درونی است و می‌توان بدون مراجعه به سرور اعتبارش را بررسی کرد. جزئیات JWT در JWT چیست و چه کاربردی در احراز هویت دارد؟

Refresh Token

Refresh Token عمر طولانی‌تری دارد (چند هفته یا ماه) و برای دریافت Access Token جدید استفاده می‌شود، بدون این‌که کاربر مجبور به ورود دوباره شود. هنگام درخواست Access Token جدید، فقط Refresh Token به Authorization Server فرستاده می‌شود و اپلیکیشن لازم نیست کاربر را به صفحهٔ لاگین هدایت کند.

نکتهٔ امنیتی مهم: Refresh Token باید فقط در سمت سرور نگهداری شود، نه در مرورگر. اگر Refresh Token لو برود، مهاجم می‌تواند به‌طور مداوم Access Token تازه بگیرد و دسترسی نامحدود داشته باشد.

Access Token مثل بلیط سینماست که فقط برای یک سانس اعتبار دارد. Refresh Token مثل کارت عضویت سالانه است که هر بار با آن می‌توانید بلیط جدید بگیرید. هر دو را باید گران‌قیمت بدانید.

ملاحظات امنیتی که نباید نادیده بگیرید

OAuth ابزار قدرتمندی است، اما اگر نادرست پیاده‌سازی شود، خودش می‌تواند منبع آسیب‌پذیری شود. پنج نکتهٔ امنیتی که در پروژه‌ها جدی می‌گیرم:

نکته اول: استفاده از HTTPS اجباری

تمام ارتباطات OAuth باید روی HTTPS باشد. بدون HTTPS، توکن‌ها در مسیر قابل شنود هستند. تفاوت HTTP و HTTPS را در HTTPS چیست و چه تفاوتی با HTTP دارد؟ باز کرده‌ام.

نکته دوم: بررسی دقیق Redirect URI

Authorization Server باید Redirect URI را با دقت بررسی کند. اگر بررسی ضعیف باشد، مهاجم می‌تواند Redirect URI را به دامنهٔ خودش هدایت کند و کد مجوز را بدزدد.

نکته سوم: اعتبارسنجی State Parameter

پارامتر state برای محافظت در برابر حملهٔ CSRF (Cross-Site Request Forgery) استفاده می‌شود. مفهوم CSRF در CSRF چیست و چگونه دفع می‌شود؟ آمده. اگر state اعتبارسنجی نشود، حملهٔ CSRF روی OAuth ممکن است.

نکته چهارم: استفاده از PKCE برای کلاینت‌های عمومی

PKCE (Proof Key for Code Exchange) یک لایهٔ امنیتی اضافه برای اپلیکیشن‌هایی است که نمی‌توانند Client Secret را محرمانه نگه دارند، مثل SPA و اپلیکیشن موبایل. از ۲۰۲۰ به بعد، استفاده از PKCE برای این نوع کلاینت‌ها اجباری شده.

نکته پنجم: مدیریت صحیح Scope

Scope‌ها (حوزهٔ دسترسی) باید کمترین حد ممکن باشند. اگر اپلیکیشن فقط به ایمیل کاربر نیاز دارد، نباید دسترسی به کل پروفایل یا تقویم بخواهد. اصل کمترین دسترسی (Least Privilege) در طراحی Scope بسیار مهم است.

OAuth در وردپرس: کاربردها و پیاده‌سازی

در وردپرس، OAuth در چند سناریو کاربرد دارد:

سناریوی اول: ورود با گوگل یا سرویس‌های خارجی

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

سناریوی دوم: اتصال به APIهای خارجی

اگر وردپرس شما به یک API خارجی مثل سرویس ایمیل، CRM یا پلتفرم ذخیره‌سازی متصل می‌شود، این اتصال معمولاً با OAuth انجام می‌شود. راهنمای کلی در اتصال وردپرس به سرویس‌های خارجی با API آمده است.

سناریوی سوم: ساخت API اختصاصی

اگر یک API اختصاصی روی وردپرس می‌سازید و می‌خواهید دسترسی به آن امن باشد، OAuth 2.0 راه‌حل استاندارد است. پیاده‌سازی در ساخت API اختصاصی برای وردپرس و احراز هویت در REST API آمده است.

اشتباهات رایج در پیاده‌سازی OAuth

پنج اشتباه که در پروژه‌ها زیاد دیده‌ام:

  • نگهداری Access Token در localStorage: این محل امنی نیست. اگر سایت شما آسیب‌پذیری XSS داشته باشد، مهاجم می‌تواند توکن را بدزدد. جای درست، HttpOnly Cookie یا سرور است.
  • استفاده از Implicit Flow: این grant type دیگر توصیه نمی‌شود. جایگزینش Authorization Code با PKCE است.
  • عدم اعتبارسنجی State: باعث می‌شود حملهٔ CSRF روی فرآیند OAuth ممکن شود.
  • Scope بیش از حد لازم: درخواست دسترسی‌های اضافی، هم اعتماد کاربر را کم می‌کند و هم ریسک امنیتی می‌سازد.
  • عدم بررسی انقضای توکن: کد باید همیشه انقضای Access Token را چک کند و در صورت نیاز، از Refresh Token استفاده کند. اگر انقضا چک نشود، درخواست‌ها با خطای 401 رد می‌شوند.

پرسش و پاسخ‌های رایج درباره OAuth

OAuth چیست به زبان ساده؟

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

تفاوت OAuth و OpenID Connect چیست؟

OAuth یک پروتکل مجوزدهی است که فقط به سؤال «چه کاری می‌توانی بکنی؟» جواب می‌دهد. OpenID Connect یک لایهٔ هویتی است که روی OAuth ساخته شده و به سؤال «تو کی هستی؟» هم جواب می‌دهد. وقتی می‌گوییم ورود با گوگل، در واقع OAuth + OpenID Connect با هم اجرا می‌شوند.

آیا OAuth جایگزین رمز عبور است؟

خیر و بله، بستگی به تعریف دارد. OAuth جایگزین رمز عبور کاربر نیست، چون کاربر همچنان در صفحهٔ سرویس مبدأ (مثل گوگل) رمزش را وارد می‌کند. اما از منظر اپلیکیشن مقصد، بله، OAuth به اپلیکیشن اجازه می‌دهد بدون نیاز به رمز عبور، به داده‌های کاربر دسترسی داشته باشد.

OAuth 1.0 و 2.0 چه تفاوتی دارند؟

OAuth 1.0 در سال ۲۰۰۷ با رویکرد پیچیده‌تر و امنیت بیشتر (با امضای رمزنگاری) معرفی شد. OAuth 2.0 در سال ۲۰۱۲ طراحی ساده‌تری را ارائه داد و بر پایهٔ HTTPS به‌جای امضای رمزنگاری بنا شد. امروز تقریباً همه از OAuth 2.0 استفاده می‌کنند. OAuth 1.0 دیگر توصیه نمی‌شود. تفاوت‌های دقیق‌تر در انتخاب بین OAuth و JWT برای پروژه آمده است.

چرا اپلیکیشن‌های موبایل به PKCE نیاز دارند؟

اپلیکیشن‌های موبایل نمی‌توانند Client Secret را محرمانه نگه دارند، چون کد آنها روی دستگاه کاربر در دسترس است. PKCE یا Proof Key for Code Exchange یک لایهٔ امنیتی جایگزین است که اجازه می‌دهد این اپلیکیشن‌ها هم بدون Client Secret، OAuth را امن پیاده کنند. از سال ۲۰۲۰ به بعد، PKCE برای کلاینت‌های عمومی اجباری شده است.

چگونه بفهمم یک وب‌سایت OAuth را امن پیاده‌سازی کرده؟

سه نشانه: اول، در آدرس‌باری، دامنهٔ سرویس مبدأ (مثل accounts.google.com) قابل مشاهده است نه دامنهٔ غیرمعمول. دوم، پروتکل HTTPS در تمام مراحل ارتباط استفاده می‌شود. سوم، اپلیکیشن فقط دسترسی‌هایی را درخواست می‌کند که منطقی هستند (مثلاً یک سایت مدیریت وظایف نباید به تقویم شما دسترسی بخواهد مگر اینکه دلیل واضحی داشته باشد).

سخن آخر: چرا OAuth به استاندارد تبدیل شد

OAuth یکی از آن تکنولوژی‌هایی است که در طول سال‌ها به‌قدری جا افتاده که دیگر کسی دربارهٔ اهمیتش سؤال نمی‌کند. اما وقتی به عقب نگاه می‌کنیم، می‌بینیم که این استاندارد، سه مسئلهٔ بنیادین دنیای وب را حل کرد: دادن دسترسی محدود بدون به‌اشتراک‌گذاری رمز عبور، امکان لغو دسترسی بدون تغییر رمز، و استانداردسازی مکانیزم دسترسی که در همهٔ سرویس‌ها یکسان کار می‌کند.

پیشنهاد عملی من برای توسعه‌دهندگان: پیش از پیاده‌سازی OAuth، سه کار انجام دهید. اول، تصمیم بگیرید که آیا به احراز هویت نیاز دارید یا فقط به مجوزدهی. اگر فقط مجوزدهی است، OAuth کافی است؛ اگر احراز هویت هم لازم است، OpenID Connect را هم اضافه کنید. دوم، همیشه از Authorization Code Flow با PKCE استفاده کنید و از انواع منسوخ پرهیز کنید. سوم، Refresh Token را در جای امن نگه دارید، نه در مرورگر کاربر.

اگر تجربه‌ای از پیاده‌سازی OAuth در پروژه‌های خودتان دارید — به‌خصوص اگر چالشی دیده‌اید که در این مقاله پیش‌بینی نشده — برایم بنویسید. مسائل امنیتی OAuth معمولاً از جزئیات کوچکی بیرون می‌آیند که فقط در پروژه‌های میدانی کشف می‌شوند. 🔐