خطای 401 Unauthorized یکی از پرتکرارترین کدهای وضعیت HTTP است که هر توسعه‌دهنده وب، ادمین سرور و متخصص API در طول حرفه خود بارها با آن روبرو می‌شود — چه در قالب پیام ساده «401» در مرورگر، چه در پاسخ JSON یک API، و چه در قالب یک پیام مدیریتی مبهم در پنل. برخلاف تصور عمومی، 401 همیشه به معنای «رمز اشتباه» نیست؛ این کد یک پیام مشخص از سرور به کلاینت است: «هویت شما برای این منبع تأیید نشده است، ابتدا احراز هویت کنید». تفاوت دقیق این پیام با 403 Forbidden، محل امنیتی آن در زنجیره احراز هویت، و روش عیب‌یابی آن، موضوع اصلی این مقاله است.

401 Unauthorized دقیقاً چه معنایی دارد؟

در استاندارد HTTP Status Codes، کد 401 در دسته 4xx (خطای کلاینت) قرار می‌گیرد و به‌طور رسمی به این معناست: «درخواست ارسال شده فاقد اطلاعات احراز هویت معتبر است و باید دوباره با هویت معتبر ارسال شود». این پیام، نه از سمت سرور به‌معنای «اشتباه داخلی» است، و نه به‌معنای «دسترسی ممنوع». بلکه یک چالش است: سرور از کلاینت می‌خواهد خودش را معرفی کند.

در عمل، سه نکته دقیق درباره کد 401 وجود دارد که اکثر توسعه‌دهنده‌ها به آن‌ها توجه نمی‌کنند. اول، این کد باید همرا با هدر WWW-Authenticate ارسال شود؛ اگر سروری 401 برگرداند اما هدر WWW-Authenticate نداشته باشد، این یک پاسخ ناقص است و رفتار مرورگر ممکن است غیرمنتظره شود. دوم، 401 در هر لایه‌ای می‌تواند رخ دهد — از وب‌سرور (Nginx/Apache)، از PHP، از API خارجی، از CDN، یا از WAF — و تشخیص لایه رخداد، کلید رفع سریع است. سوم، در معماری مدرن وب، کد 401 اغلب به‌عنوان بخشی از جریان طبیعی احراز هویت استفاده می‌شود: کلاینت بدون توکن درخواست می‌زند، سرور 401 برمی‌گرداند، کلاینت با توکن معتبر دوباره درخواست می‌زند. اگر با معماری کلی سرور آشنایی ندارید، ابتدا سرور چیست و چگونه کار می‌کند را بخوانید تا تصویر کلی در ذهن شما شکل بگیرد.

401 یک خطا نیست، یک چالش است. سرور به کلاینت می‌گوید «نمی‌دانم کی هستی» و منتظر می‌ماند تا کلاینت هویت خودش را اثبات کند.

سه لایه‌ای که باید تفکیک شوند

در تجربه من، خطای 401 همیشه در یکی از این سه لایه ریشه دارد. تفکیک لایه پیش از هر اقدام، نیمی از راه را رفته‌اید:

  • لایه وب‌سرور: Nginx یا Apache قبل از رسیدن به PHP، درخواست را رد می‌کند (مثلاً Basic Auth با htpasswd).
  • لایه اپلیکیشن: کد PHP، افزونه یا فریم‌ورک شما درخواست را رد می‌کند (JWT منقضی، Application Password نامعتبر، سشن ناهمگام).
  • لایه میان‌راهی: CDN، WAF، پروکسی معکوس یا فایروال سمت ابری، درخواست را رد می‌کند (IP بلاک، هدر ناهمگام).

جدول زیر نگاشت سریع سیمپتوم به لایه خطا را نشان می‌دهد:

سیمپتوملایه احتمالیاولین اقدام تشخیصی
مرورگر پنجره «Authentication Required» نشان می‌دهدلایه وب‌سرور (Basic Auth)بررسی فایل htpasswd و .htaccess
پاسخ JSON با 401 در APIلایه اپلیکیشنبررسی توکن، JWT یا کلید API
401 فقط از بعضی IPها رخ می‌دهدلایه میان‌راهیبررسی قواعد WAF و CDN
401 فقط در بعضی مرورگرها یا دستگاه‌هالایه اپلیکیشن یا کشبررسی کوکی، نشست و هدرهای مرورگر

تفاوت بنیادین 401 و 403

یکی از پرتکرارترین سؤالات در جلسات فنی این است که «401 با 403 چه تفاوتی دارد؟» و اشتباه گرفتن این دو، یکی از دلایل اصلی عیب‌یابی اشتباه است. تفاوت بنیادین این دو را می‌توان در یک جمله خلاصه کرد: 401 یعنی «نمی‌دانم کی هستی، اول معرفی کن» و 403 یعنی «می‌دانم کی هستی، اما اجازه نداری». به‌عبارت دقیق‌تر، 401 درباره احراز هویت (Authentication) است و 403 درباره مجوزدهی (Authorization). تفاوت دقیق این دو مفهوم را در تفاوت احراز هویت و مجوزدهی باز کرده‌ام.

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

معیار401 Unauthorized403 Forbidden
معناهویت تأیید نشدههویت تأیید شده اما مجوز کافی نیست
مفهومAuthenticationAuthorization
هدرWWW-Authenticateمعمولاً بدون این هدر
اقدام کلاینتارسال اطلاعات احراز هویتارسال اطلاعات احراز هویت اثر ندارد
مثالورود بدون رمز یا با رمز اشتباهورود موفق اما دسترسی به پوشه ممنوع

هدر WWW-Authenticate: پیام رسمی سرور

هدر WWW-Authenticate همراه با پاسخ 401 ارسال می‌شود و به کلاینت می‌گوید چه روش احراز هویتی را باید برای دسترسی به این منبع استفاده کند. فرمت کلی این هدر به این شکل است: WWW-Authenticate: realm="". مثلاً در Basic Auth، سرور می‌فرستد: WWW-Authenticate: Basic realm="Restricted Area". مرورگر با دیدن این هدر، پنجره ورود کاربری را نمایش می‌دهد.

سه نکته دقیق در این لایه:

  1. نبود WWW-Authenticate، خطای ناقص: اگر سروری 401 برگرداند اما این هدر را نگذارد، مرورگر نمی‌داند چه روشی را امتحان کند و ممکن است پاسخ را به‌عنوان خطای عمومی نمایش دهد. این سناریو در APIهای با احراز هویت سفارشی شایع است.
  2. پشتیبانی از چند روش: سرور می‌تواند چند هدر WWW-Authenticate با روش‌های مختلف ارسال کند. کلاینت یکی را انتخاب می‌کند. مثلاً: WWW-Authenticate: Basic realm="x" و WWW-Authenticate: Bearer realm="x".
  3. نقش realm: مقدار realm یک برچسب متنی است که نشان می‌دهد کدام محدوده امنیتی محافظت می‌شود. مرورگر از این مقدار برای نمایش در پنجره ورود و ذخیره credential استفاده می‌کند.

روش تشخیص: با ابزار curl -I به URL مورد نظر درخواست بزنید و همه هدرها را ببینید. اگر پاسخ 401 دریافت کردید اما هدر WWW-Authenticate نبود، ریشه در لایه اپلیکیشن است و پیاده‌سازی احراز هویت شما ناقص است. اصول کلی امنیت وب و لایه‌های آن را در امنیت وب چیست آورده‌ام.

Basic Auth و چالش‌های آن

Basic Auth ساده‌ترین روش احراز هویت HTTP است: کلاینت نام کاربری و رمز عبور را با فرمت user:pass در هدر Authorization: Basic <base64> می‌فرستد. سرور این مقدار را decode می‌کند و با فهرست کاربران معتبر مقایسه می‌کند. این روش در محیط‌های staging، در پنل‌های مدیریتی و در محافظت از پوشه‌های حساس بسیار رایج است — اما در برابر حملات MITM (Man-in-the-Middle) آسیب‌پذیر است و باید همیشه روی HTTPS استفاده شود.

سه سناریوی دقیق که در Basic Auth خطای 401 می‌سازند:

  • ناسازگاری هدر Authorization: بعضی پروکسی‌ها یا افزونه‌های امنیتی، هدر Authorization را حذف می‌کنند. نتیجه: سرور درخواست را بدون هدر می‌بیند و 401 برمی‌گرداند. این سناریو در هاست‌های اشتراکی و CDNهای با تنظیمات تهاجمی شایع است.
  • رمز عبور با کاراکترهای خاص: اگر رمز عبور شامل کاراکترهای غیر ASCII باشد، ممکن است در فرآیند encoding/decoding خطا رخ دهد.
  • پنجره ورود مکرر: اگر مرورگر credential قدیمی را ذخیره کرده باشد و سرور رمز جدیدی انتظار داشته باشد، مرورگر همان credential قدیمی را می‌فرستد و 401 تکرار می‌شود تا زمانی که کاربر cache مرورگر را پاک کند.

روش تشخیص قطعی: با curl و ارسال دستی هدر Basic Auth، به URL درخواست بزنید. اگر پاسخ موفق بود اما مرورگر شکست خورد، ریشه در cache مرورگر یا پروکسی است. حفاظت از مسیرهای مدیریتی با Basic Auth را در امن‌سازی لاگین ادمین و فایروال نرم‌افزاری در سرور آورده‌ام.

Basic Auth یک ابزار ساده و کارآمد است، اما ساده بودنش به‌معنای بی‌خطر بودنش نیست. روی HTTP بدون SSL، هر درخواست یک فاجعه امنیتی است.

401 در APIها: REST، JWT و OAuth

در دنیای APIهای مدرن، 401 شایع‌ترین کد خطای احراز هویت است. سه روش اصلی احراز هویت در APIها عبارتند از: API Key، JWT و OAuth. هرکدام، سناریوهای مخصوص به خود را برای شکست دارند. ابتدا با مفهوم API و انواع آن آشنا شوید اگر تازه‌وارد هستید، API چیست و چه کاربردی دارد و REST API چیست نقطه شروع مناسبی هستند.

401 در APIهای مبتنی بر API Key

در این روش، کلاینت یک کلید ثابت در هدر ارسال می‌کند. سه اشتباه رایج:

  1. کلید اشتباه یا منقضی: اگر کلید از پنل API حذف شده باشد اما در کد شما هنوز قدیمی است، هر درخواست با 401 رد می‌شود.
  2. هدر اشتباه: بعضی APIها کلید را در هدر X-API-Key می‌خواهند، بعضی در Authorization، بعضی در query string. ارسال کلید در جای اشتباه، بدون خطای واضح، باعث 401 می‌شود.
  3. IP بلاک: اگر API برای امنیت، IP کلاینت را بررسی می‌کند و IP شما تغییر کرده، 401 برمی‌گردد.

401 در JWT

JWT (JSON Web Token) یک توکن امضاشده است که در آن اطلاعات هویت کاربر رمزنگاری شده. سه سناریوی دقیق که JWT باعث 401 می‌شود:

  1. انقضای توکن (exp): هر JWT یک زمان انقضا دارد. بعد از این زمان، سرور توکن را باطل می‌بیند و 401 برمی‌گرداند. راه‌حل: استفاده از refresh token و تجدید خودکار.
  2. عدم تطابق امضا (signature): اگر کلید امضای JWT در سرور تغییر کرده باشد، توکن‌های قدیمی نامعتبر می‌شوند. اگر بعد از تغییر کلید، همه کاربران 401 گرفتند، ریشه همین است.
  3. هدر Authorization نادرست: فرمت صحیح ارسال JWT در هدر به این شکل است: Authorization: Bearer <token>. اگر کلمه Bearer را ننویسید یا نوع دیگری بنویسید، سرور درخواست را رد می‌کند.

مبانی JWT و کاربردهای آن را در JWT چیست و چه کاربردی در احراز هویت دارد و پیاده‌سازی آن در پیاده‌سازی JWT در APIهای مدرن آورده‌ام.

401 در OAuth

OAuth یک چارچوب پیچیده‌تر است که در آن، به‌جای اشتراک رمز، از یک access token استفاده می‌شود. سه سناریوی دقیق در این لایه:

  1. انقضای access token: توکن‌های OAuth معمولاً عمر کوتاهی دارند (از چند دقیقه تا چند ساعت). اگر refresh token به‌درستی پیاده‌سازی نشده باشد، بعد از انقضا، هر درخواست 401 می‌گیرد.
  2. scope نامعتبر: اگر scope توکن شامل مجوز درخواستی شما نباشد، سرور ممکن است 401 یا 403 برگرداند. بعضی پیاده‌سازی‌ها 401 را برای scope ناقص برمی‌گردانند که دقیق نیست اما شایع است.
  3. redirect_uri ناسازگار: در فرآیند OAuth، اگر redirect_uri با آنچه در برنامه ثبت شده مطابقت نداشته باشد، درخواست رد می‌شود.

مبانی کامل OAuth را در OAuth چیست و چگونه کار می‌کند آورده‌ام. برای درک تفاوت انتخاب بین JWT و OAuth، انتخاب بین OAuth و JWT راهنمای دقیقی است.

401 در وردپرس و Application Passwords

در وردپرس، خطای 401 معمولاً از سه مسیر رخ می‌دهد: احراز هویت Basic Auth برای REST API، Application Passwords، یا محافظت از پوشه wp-admin و wp-login. REST API وردپرس از روش‌های مختلف احراز هویت پشتیبانی می‌کند که هرکدام شرایط خودش را دارد.

سه سناریوی دقیق در وردپرس:

  1. Application Password نامعتبر: از وردپرس ۵.۶، Application Passwords بخشی از هسته شده. اگر رمز برنامه را اشتباه در کد وارد کرده باشید یا در سرور غیرفعال باشد، هر درخواست REST API با 401 رد می‌شود.
  2. Basic Auth مسدود توسط افزونه امنیتی: بسیاری از افزونه‌های امنیتی، هدر Authorization را حذف می‌کنند تا از حملات جلوگیری کنند. نتیجه: REST API شما که با Basic Auth محافظت شده، هر درخواست را 401 می‌بیند. این سناریو در پروژه‌هایی که از REST API برای اپلیکیشن موبایل یا اتصال به سیستم خارجی استفاده می‌کنند، بسیار شایع است.
  3. .htaccess روی wp-json: بعضی ادمین‌ها برای محافظت از REST API، مسیر /wp-json/ را در .htaccess با Basic Auth محافظت می‌کنند. اگر credential اشتباه ارسال شود، 401 برمی‌گردد.

روش تشخیص: با curl و ارسال Application Password دستی، درخواست تست بگیرید. اگر موفق شد اما اپلیکیشن شما شکست خورد، ریشه در کد اپلیکیشن است. راهنمای کامل REST API وردپرس در API در وردپرس و استفاده از REST API در وردپرس آمده است.

در REST API وردپرس، هدر Authorization گاهی توسط افزونه‌های امنیتی حذف می‌شود و شما در سرور 401 می‌بینید، در حالی که کلاینت شما هدر را درست ارسال کرده. شناخت این لایه، از ساعات عیب‌یابی جلوگیری می‌کند.

401 در پنل‌های مدیریتی: cPanel، phpMyAdmin و WHM

پنل‌های مدیریتی معمولاً از چند لایه احراز هویت استفاده می‌کنند و به همین دلیل، خطای 401 در این لایه‌ها می‌تواند از چند جهت رخ دهد. سه سناریوی دقیق:

  • cPanel و محدودیت IP: بعضی هاست‌ها، دسترسی به cPanel را به IPهای مشخص محدود می‌کنند. اگر IP شما تغییر کرده، 401 برمی‌گردد. راه‌حل: تماس با هاست و به‌روزرسانی IP مجاز.
  • phpMyAdmin با Basic Auth: بعضی هاست‌ها، phpMyAdmin را با Basic Auth محافظت می‌کنند. اگر credential اشتباه وارد شود، 401 می‌گیرید و صفحه سفید یا پیام Authentication Required ظاهر می‌شود.
  • دو مرحله‌ای ناهمگام: اگر پنل شما دو مرحله احراز هویت دارد (مثل WHM + 2FA) و یکی از مراحل fail شود، ممکن است پیام 401 بگیرید در حالی که ریشه در لایه 2FA است.

مبانی cPanel و کاربردهای آن را در cPanel چیست و چه کاربردی دارد آورده‌ام. تنظیمات امنیتی دقیق cPanel را هم در تنظیمات امنیتی cPanel پوشش داده‌ام. برای حفاظت از دسترسی‌های ادمین سرور، افزایش امنیت سرور راهنمای عملیاتی است.

401 در Nginx، Apache و htpasswd

در لایه وب‌سرور، 401 معمولاً از Basic Auth ناشی می‌شود که با فایل htpasswd پیاده‌سازی شده. این روش برای محافظت از پوشه‌های حساس (مثل staging، پوشه آپلود، یا کل سایت) بسیار رایج است. سه اشتباه دقیق در این لایه:

  1. مسیر اشتباه فایل htpasswd: اگر فایل .htpasswd در مسیر اشتباهی باشد یا مسیر در .htaccess یا تنظیمات Nginx نادرست باشد، احراز هویت fail می‌شود و 401 برمی‌گردد.
  2. فرمت فایل خراب: فایل htpasswd باید فرمت مشخصی داشته باشد (user:hashed_password). اگر خط اضافه، کاراکتر ناخواسته یا hash اشتباه داشته باشد، سرور همه credentialها را رد می‌کند.
  3. عدم دسترسی خواندن فایل: اگر فایل htpasswd مجوز خواندن برای وب‌سرور نداشته باشد، سرور نمی‌تواند آن را بخواند و همه درخواست‌ها را 401 برمی‌گرداند.

روش تشخیص: با htpasswd -vb /path/to/.htpasswd user password بررسی کنید که credential ذخیره‌شده با ورودی شما مطابقت دارد. اگر مطابقت داشت اما سایت 401 می‌دهد، ریشه در مجوز یا مسیر فایل است.

401 در CDN و WAF

در معماری‌های مدرن، درخواست‌ها ابتدا از CDN و WAF عبور می‌کنند. اگر این لایه‌ها، درخواست را به‌عنوان «مشکوک» یا «غیرمجاز» تشخیص دهند، ممکن است 401 برگردانند حتی اگر اپلیکیشن شما سالم باشد. سه سناریوی دقیق:

  • WAF با قانون هدر: بعضی WAFها، درخواست‌هایی که هدر Authorization غیر استاندارد دارند، بلاک می‌کنند و 401 برمی‌گردانند.
  • CDN با Basic Auth قدیمی: بعضی CDNها، یک لایه Basic Auth اضافی روی سایت قرار می‌دهند که ممکن است با Basic Auth اپلیکیشن تداخل کند. نتیجه: دو پنجره ورود پشت سر هم یا 401 در لایه دوم.
  • IP بلاک در CDN: اگر IP شما در لیست سیاه CDN قرار گرفته باشد، ممکن است 401 یا 403 بگیرید.

روش تشخیص: با ابزارهای CDN ببینید که آیا درخواست به سرور اصلی رسیده یا نه. اگر درخواست به سرور رسیده اما 401 گرفته، ریشه در اپلیکیشن است؛ اگر نرسیده، ریشه در CDN یا WAF. توضیح معماری CDN و WAF را در CDN چیست و چگونه کار می‌کند آورده‌ام.

دلایل شایع بروز 401

بعد از آشنایی با لایه‌ها، فهرست سریع دلایل شایع 401 در پروژه‌های واقعی را مرور کنیم:

  1. توکن منقضی یا اشتباه: در JWT، OAuth و Application Password، انقضای توکن شایع‌ترین دلیل 401 است.
  2. هدر Authorization حذف‌شده: پروکسی، WAF یا افزونه امنیتی، هدر را حذف می‌کند و اپلیکیشن بدون هدر درخواست را می‌بیند.
  3. رمز عبور یا کلید API قدیمی: تغییر رمز بدون به‌روزرسانی کد، منجر به 401 مکرر می‌شود.
  4. IP بلاک یا محدودیت جغرافیایی: بعضی سرویس‌ها دسترسی از IPهای خاص را بلاک می‌کنند و 401 یا 403 برمی‌گردانند.
  5. مشکل ساعت سرور: در JWT و امضای دیجیتال، اختلاف ساعت بین سرور و کلاینت می‌تواند توکن را نامعتبر کند. این سناریو در محیط‌های ابری شایع است.
  6. سشن ناهمگام: اگر سشن کاربر در سرور منقضی شده اما کلاینت هنوز کوکی قدیمی دارد، 401 می‌گیرد.
  7. تنظیمات اشتباه Basic Auth: مسیر فایل htpasswd، مجوز فایل یا فرمت اشتباه.
  8. CDN یا WAF تهاجمی: قواعد امنیتی که به‌اشتباه درخواست‌های مجاز را بلاک می‌کنند.
  9. تداخل افزونه امنیتی با API: افزونه‌ای که مسیر /wp-json/ را بلاک می‌کند و REST API را می‌شکند.
  10. کش مرورگر: مرورگر credential قدیمی را ذخیره کرده و همان را می‌فرستد.

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

پروتکل عیب‌یابی گام‌به‌گام

حالا ترتیب عملی عیب‌یابی، از سریع‌ترین به دقیق‌ترین:

  1. بازتولید و ثبت دقیق: قبل از هر چیز، با curl -v درخواست را بزنید و همه هدرهای ارسال و دریافت را ثبت کنید. این، اولین قدم برای تشخیص لایه است.
  2. بررسی WWW-Authenticate: در پاسخ، هدر WWW-Authenticate را ببینید. اگر وجود دارد، لایه احراز هویت روشن است. اگر وجود ندارد، ریشه ممکن است در لایه دیگری باشد.
  3. بررسی لاگ سرور: در /var/log/nginx/error.log یا /var/log/apache2/error.log، آخرین درخواست‌ها و خطاهای مرتبط را ببینید. روش دقیق در بررسی خطاهای سرور در لاگ‌ها آمده است.
  4. بررسی لاگ اپلیکیشن: در وردپرس، debug.log و لاگ‌های افزونه‌ها. ریشه اغلب اینجا نوشته شده.
  5. تست با credential صحیح: با curl و ارسال دستی توکن یا credential، تست بگیرید. اگر موفق شد، ریشه در لایه کلاینت است؛ اگر نشد، در لایه سرور.
  6. بررسی تنظیمات CDN و WAF: آیا درخواست به سرور اصلی رسیده؟ لاگ CDN را ببینید.
  7. بررسی htaccess و Nginx config: فایل‌های پیکربندی را برای Basic Auth غیرمنتظره بازبینی کنید.
  8. بررسی ساعت سرور: با date روی سرور، مطمئن شوید ساعت همگام است. برای JWT و امضا، این حیاتی است.
  9. تست با مرورگر ناشناس: اگر فقط مرورگر شکست می‌خورد، cache یا کوکی قدیمی است.
  10. بررسی افزونه‌های امنیتی: اگر افزونه امنیتی به‌تازگی نصب شده، احتمال تداخل با REST API وجود دارد.

برای خطاهای مرتبط با سرور، خطای SSL سرور، خطای 502 Bad Gateway و خطای 503 Service Unavailable مسیرهای مکمل عیب‌یابی هستند. برای مدیریت دستورات سرور، دستورات ضروری CLI راهنمای کاربردی است.

در عیب‌یابی 401، اولین کار این نیست که «توکن را عوض کنم» یا «فایروال را غیرفعال کنم». اولین کار این است که با curl -v بفهمید سرور دقیقاً چه چیزی دریافت کرده.

اشتباهات پرهزینه در تشخیص

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

  • غیرفعال کردن افزونه امنیتی برای «رفع سریع»: این کار مشکل را موقتاً حل می‌کند اما سایت را در برابر حملات باز می‌گذارد. راه‌حل درست: تنظیم دقیق استثنائات، نه غیرفعال کردن.
  • اشتباه گرفتن 401 با 403: اگر سرور 401 برگرداند اما شما در لایه مجوزدهی جست‌وجو کنید، وقت تلف می‌شود.
  • نادیده گرفتن WWW-Authenticate: نبود این هدر در پاسخ 401، یک سیگنال مهم است که اغلب دیده نمی‌شود.
  • ویرایش کورکورانه فایل htpasswd: بدون تست، می‌توانید فایل را خراب‌تر کنید. همیشه با htpasswd -vb تست بگیرید.
  • نادیده گرفتن ساعت سرور: در JWT، اختلاف ساعت حتی چند دقیقه می‌تواند کل توکن‌ها را باطل کند.

پرسش‌های پرتکرار درباره خطای 401 Unauthorized

401 Unauthorized با 403 Forbidden چه تفاوتی دارد؟ 401 به‌معنای «هویت تأیید نشده» است (احراز هویت)، در حالی که 403 به‌معنای «هویت تأیید شده اما مجوز کافی نیست» است (مجوزدهی). در 401، کلاینت باید اطلاعات احراز هویت را بفرستد؛ در 403، فرستادن دوباره اطلاعات کمکی نمی‌کند.

چرا مرورگر پنجره ورود نمایش می‌دهد و بعد از وارد کردن رمز، دوباره 401 می‌گیرم؟ این نشانه عدم‌تطابق credential ذخیره‌شده در سرور با آنچه وارد می‌کنید است. با htpasswd -vb بررسی کنید که رمز ذخیره‌شده با ورودی شما مطابقت دارد. اگر مطابقت دارد، ریشه در cache مرورگر یا پروکسی است.

چرا REST API وردپرس از خارج 401 می‌گیرد ولی از داخل همان سرور درست کار می‌کند؟ این نشانه حذف شدن هدر Authorization توسط یک لایه میانی (افزونه امنیتی، CDN یا پروکسی) است. سرور داخلی این لایه را ندارد. با بررسی لاگ CDN یا غیرفعال کردن موقت افزونه امنیتی روی استجینگ، ریشه را پیدا کنید.

JWT من با اینکه تازه ساخته شده، 401 می‌گیرد. چه شده؟ سه ریشه: (۱) ساعت سرور با کلاینت ناهمگام است و توکن در آینده‌ای معتبر است که هنوز نرسیده؛ (۲) کلید امضا تغییر کرده؛ (۳) فرمت هدر Authorization اشتباه است (کلمه Bearer فراموش شده). با date روی سرور، اول ساعت را چک کنید.

چرا Application Password وردپرس کار نمی‌کند؟ یا Application Password در سرور غیرفعال است (در بعضی تنظیمات)، یا افزونه امنیتی هدر Authorization را حذف می‌کند، یا رمز برنامه در کد اشتباه وارد شده. با تست مستقیم curl، اول از صحت credential مطمئن شوید.

آیا Basic Auth روی HTTP بدون SSL خطرناک است؟ بله، به‌شدت. رمز عبور در هدر Authorization به‌صورت base64 ارسال می‌شود که رمزنگاری نیست. هر مهاجم روی مسیر (MITM) می‌تواند آن را ببیند. همیشه Basic Auth را روی HTTPS استفاده کنید.

چرا بعد از افزودن CDN، سایت شروع به درخواست Basic Auth کرد؟ بعضی CDNها یک لایه Basic Auth اضافی برای محیط staging یا محافظت دارند. اگر فعال باشد، از کاربران پنجره ورود می‌گیرد. این را در تنظیمات CDN بررسی کنید.

چطور بفهمم 401 از کدام لایه است؟ با curl -v درخواست را بزنید و هدرهای پاسخ را ببینید. اگر هدر Server یا WWW-Authenticate نشانه‌های Nginx یا Apache داشت، لایه وب‌سرور است. اگر نشانه‌های CDN (مثل Cloudflare) داشت، لایه CDN است. اگر هیچ‌کدام، لایه اپلیکیشن است.

آیا می‌توانم 401 را در مرورگر غیرفعال کنم تا کاربر تجربه بهتری داشته باشد؟ غیرفعال کردن 401 راه‌حل نیست؛ 401 پیام استاندارد HTTP است. اگر می‌خواهید کاربر پنجره ورود نبیند، از احراز هویت مبتنی بر فرم یا توکن استفاده کنید، نه Basic Auth.

چرا 401 فقط از بعضی IPها رخ می‌دهد؟ این نشانه یک لایه محدودیت جغرافیایی یا IP در WAF یا CDN است. لاگ CDN را بررسی کنید و مطمئن شوید IP مشتری در لیست سیاه نیست.

آیا 401 می‌تواند از سمت دیتابیس رخ دهد؟ خیر، 401 یک کد HTTP است که فقط در لایه وب و انتقال معنا دارد. اگر دیتابیس مشکل داشته باشد، معمولاً خطای 500 یا پیام PHP می‌بینید.

چطور از بروز 401 در آینده پیشگیری کنم؟ سه اصل: (۱) از توکن‌های با انقضای معقول و refresh خودکار استفاده کنید؛ (۲) بعد از هر تغییر در رمز یا کلید، همه سرویس‌های وابسته را هم‌زمان به‌روز کنید؛ (۳) لاگ دقیق درخواست‌های احراز هویت داشته باشید تا ترند را ببینید.

آنچه از این مسیر با ما می‌ماند

خطای 401 Unauthorized در ظاهر یک پیام ساده است؛ در عمل، یک چالش احراز هویت که در یکی از چند لایه ممکن است شکل گرفته باشد. سه اصل که از این مسیر با من می‌ماند:

  1. اول لایه را تشخیص بده، بعد راه‌حل را انتخاب کن: بدون شناخت لایه، غیرفعال کردن فایروال یا عوض کردن رمز، ممکن است مسئله را تشدید کند. با curl -v و هدر WWW-Authenticate، اولین قدم را دقیق بردارید.
  2. یک لاگ مرکزی برای احراز هویت: در هر سرویس، یک لاگ دقیق از درخواست‌های رد‌شده در احراز هویت داشته باشید. این لاگ، در لحظه بحران ارزش ساعت‌ها وقت را دارد. اصول ثبت لاگ سرور را در بررسی خطاهای سرور در لاگ‌ها آورده‌ام.
  3. مستندسازی پیکربندی احراز هویت: برای هر سرویس، یک برگه کوچک بسازید که روش احراز هویت، کلیدها، محدودیت‌های IP و روش تمدید توکن را ثبت کند. این سند، در روزهای بعدی، سرمایه شماست.

اگر در پروژه‌ای با مشکل 401 دست‌وپنجه نرم کرده‌اید، برای من جالب است بدانم کدام لایه بیشترین وقت شما را گرفت: Basic Auth، JWT، CDN یا افزونه امنیتی. تجربه‌تان را در دیدگاه‌ها بنویسید؛ مخصوصاً اگر نشانه‌ای کشف کرده‌اید که در این فهرست نبوده. همین نشانه‌ها، دقیق‌ترین راهنمای نفر بعدی‌اند. 🔐