۱۶ فروردین ۱۴۰۵۱۲ دقیقه مطالعه
امنیت API؛ اصولی که نباید نادیده گرفته شوند
با مهمترین اصول امنیت API آشنا شوید؛ از Authentication و Authorization تا OAuth، JWT، Rate Limiting، مدیریت Secret، اعتبارسنجی ورودی و Logging.

APIها قرار است کار را سادهتر کنند.
اپلیکیشن موبایل به Backend وصل میشود، سیستم فروش با حسابداری حرف میزند، یک سرویس اطلاعات را برای سرویس دیگری میفرستد و چند نرمافزار مختلف بدون دخالت مستقیم کاربر با هم کار میکنند.
همین ویژگی یک معنی دیگر هم دارد:
API یکی از مستقیمترین مسیرهای دسترسی به داده و منطق کسبوکار است.
اگر این مسیر درست محافظت نشود، ظاهر امن وبسایت یا اپلیکیشن کمک زیادی نمیکند.
به همین دلیل امنیت API فقط این نیست که «روی Endpointها Token گذاشتهایم». باید مشخص باشد چه کسی درخواست را میفرستد، به چه چیزی دسترسی دارد، چه عملیاتی اجازه انجامش را دارد، با چه سرعتی میتواند درخواست بفرستد و اگر رفتار غیرعادی اتفاق افتاد، آیا اصلاً متوجه آن میشویم یا نه.
OWASP در آخرین نسخه پایدار API Security Top 10، ریسکهایی مثل Broken Object Level Authorization، Broken Authentication، Broken Object Property Level Authorization، Unrestricted Resource Consumption و Broken Function Level Authorization را در بالای فهرست قرار داده است.
پس امنیت API را بهتر است از یک سؤال ساده شروع کنیم:
این درخواست واقعاً باید اجازه انجام این کار را داشته باشد؟
Authentication و Authorization یک چیز نیستند
این دو مفهوم زیاد کنار هم استفاده میشوند، اما وظیفه متفاوتی دارند.
Authentication مشخص میکند درخواستکننده چه کسی است.
مثلاً:
- این درخواست متعلق به کاربر محمد است.
- این سرویس متعلق به سیستم مالی است.
- این Client با Credential معتبر وارد شده است.
اما Authorization سؤال دیگری میپرسد:
حالا که فهمیدیم چه کسی هستی، دقیقاً اجازه انجام چه کاری را داری؟
ممکن است یک کاربر کاملاً معتبر Login کرده باشد، اما نباید بتواند سفارش کاربر دیگری را مشاهده کند.
ممکن است یک کارمند اجازه مشاهده مشتریان را داشته باشد، اما اجازه حذف آنها را نداشته باشد.
ممکن است یک API Client معتبر باشد، اما فقط به یک Scope محدود نیاز داشته باشد.
این تفاوت پایه بسیاری از مشکلات امنیتی API است.
حتی OWASP اشاره میکند که Authorization همچنان یکی از بزرگترین چالشهای امنیت API است و سه مورد از پنج ریسک اول نسخه ۲۰۲۳ آن به کنترل دسترسی مربوط میشوند.
داشتن Token به معنی داشتن اجازه نیست
فرض کنید API این Endpoint را دارد:
GET /orders/18427
کاربر Login کرده و Access Token معتبر دارد.
آیا همین کافی است؟
نه.
Backend باید بررسی کند که Order شماره 18427 واقعاً متعلق به همان کاربر است یا کاربر مجوز مشاهده آن را دارد.
اگر صرفاً با تغییر:
18427
به:
18428
بتوان سفارش شخص دیگری را دید، با یک مشکل کلاسیک Broken Object Level Authorization یا BOLA طرف هستیم.
OWASP این مورد را در رتبه اول API Security Top 10 قرار داده و توصیه میکند هر تابعی که با یک شناسه دریافتی از کاربر به Objectی دسترسی پیدا میکند، کنترل مجوز در سطح همان Object داشته باشد.
پس قاعده این نیست:
کاربر Login کرده؛ پس اجازه دارد.
قاعده بهتر این است:
کاربر Login کرده؛ حالا برای همین Object و همین Operation هم مجوزش را بررسی کن.
کنترل دسترسی فقط در سطح Endpoint کافی نیست
مسئله فقط این نیست که یک User به /admin دسترسی داشته باشد یا نه.
گاهی خود Object شامل اطلاعاتی است که همه کاربران نباید ببینند.
مثلاً API مشتری این Response را برمیگرداند:
- نام
- ایمیل
- شماره تماس
- شماره ملی
- سطح دسترسی
- وضعیت حساب
- اطلاعات داخلی Risk
ممکن است Frontend فقط سه مورد اول را نمایش دهد.
اما اگر API تمام فیلدها را برگرداند، مخفیکردن آنها در رابط کاربری هیچ محافظتی ایجاد نمیکند.
همین مسئله هنگام Update هم وجود دارد.
اگر کاربر بتواند همراه درخواست تغییر پروفایل، فیلدی مثل role=admin یا Propertyای را تغییر دهد که قرار نبوده قابل ویرایش باشد، کنترل دسترسی در سطح Property شکست خورده است.
OWASP این دسته از مشکلات را تحت Broken Object Property Level Authorization پوشش میدهد.
API باید خودش تصمیم بگیرد:
- چه Propertyهایی قابل خواندن هستند؟
- چه Propertyهایی قابل تغییرند؟
- و برای چه Role یا Scopeای؟
Frontend مرز امنیتی نیست.
Least Privilege را از ابتدا جدی بگیرید
یک Integration که فقط قرار است موجودی را بخواند، چرا باید امکان حذف محصول داشته باشد؟
یک سرویس گزارشگیری که فقط داده میخواند، چرا باید Write Permission داشته باشد؟
یک Access Token که برای یک API صادر شده، چرا باید به پنج سرویس دیگر هم دسترسی بدهد؟
اصل Least Privilege یعنی هر User، Service یا Token فقط کمترین دسترسی لازم برای انجام کارش را داشته باشد.
در OAuth میتوان این محدودیت را با Scope و Resource-specific authorization بهتر کنترل کرد. RFC 9700 نیز محدودکردن Privilege توکنها و استفاده از Scope یا Authorization Details برای تعیین Resource و Action را در Best Practiceهای OAuth قرار میدهد.
دسترسی اضافه شاید امروز مشکلی ایجاد نکند.
اما اگر Credential فردا لو برود، همان دسترسیهای اضافی تبدیل به دامنه حمله میشوند.
اگر OAuth استفاده میکنید، از الگوهای قدیمی کپی نکنید
OAuth 2.0 سالهاست استفاده میشود و مثالهای قدیمی زیادی در اینترنت وجود دارد.
مشکل اینجاست که بعضی از آن مثالها دیگر Best Practice امروز نیستند.
IETF در ژانویه ۲۰۲۵، RFC 9700 — Best Current Practice for OAuth 2.0 Security را منتشر کرد تا توصیههای امنیتی OAuth را بر اساس تجربه سالهای گذشته بهروز کند.
چند نکته مهم آن:
Authorization Code + PKCE
PKCE دیگر فقط موضوع Mobile App نیست. RFC 9700 میگوید توصیههای آن برای انواع Client، از جمله Web Applicationها هم کاربرد دارد و Authorization Server باید PKCE را پشتیبانی کند. برای Challenge نیز S256 روش فعلیای است که Verifier را در Authorization Request آشکار نمیکند.
Implicit Grant
روش Implicit میتواند Access Token را در Authorization Response قرار دهد و در معرض Token Leakage و Replay قرار بگیرد. راهنمای جدید توصیه میکند Clientها بهطور معمول از این Flow استفاده نکنند و به سمت Authorization Code Flow بروند.
Password Grant
در مورد Resource Owner Password Credentials Grant حتی توصیه ملایمی وجود ندارد:
RFC 9700 صریحاً میگوید این Grant نباید استفاده شود، چون Credential کاربر را در اختیار Client قرار میدهد و سطح حمله را افزایش میدهد.
نتیجه ساده است:
اگر Authentication Architecture جدید طراحی میکنیم، کد نمونهای که پنج سال پیش از یک Blog کپی شده نباید مرجع امنیت ما باشد.
JWT جادو نیست
JWT راه متداولی برای انتقال Claimهای امنیتی است، اما صرف استفاده از JWT، سیستم را امن نمیکند.
یک سوءبرداشت رایج این است که:
«اطلاعات داخل JWT امن است چون Token است.»
JWT میتواند Signed و/یا Encrypted باشد. Signed بودن به این معنی نیست که Payload برای Client قابل مشاهده نیست.
بنابراین اطلاعات حساس را صرفاً به این امید که داخل Token قرار گرفتهاند، در Payload نریزید.
IETF در RFC 8725 برای استفاده امن از JWT چند کنترل مهم را مطرح میکند؛ از جمله محدودکردن Algorithmهای قابل قبول و بررسی دقیق Claimهایی مثل Issuer و Audience.
در عمل Validation یک JWT نباید فقط این باشد که:
«Signature درست بود.»
بسته به معماری باید مواردی مانند اینها هم کنترل شوند:
iss— چه کسی Token را صادر کرده؟aud— Token برای کدام سرویس صادر شده؟exp— آیا منقضی شده؟nbf— از چه زمانی معتبر است؟- و آیا Algorithm استفادهشده همان Algorithm مورد انتظار برنامه است؟
RFC 8725 مشخصاً تأکید میکند Application نباید Algorithm را صرفاً بر اساس چیزی که خود Token اعلام کرده، بدون محدودیت قبول کند.
API Key را Password عمومی سیستم نکنید
API Key برای بعضی سناریوها ابزار مناسبی است.
مثلاً شناسایی یک Client، Metering، محدودکردن مصرف یا دسترسی به یک سرویس مشخص.
اما API Key بهتنهایی انتخاب مناسبی برای محافظت از Resourceهای بسیار حساس نیست.
OWASP نیز توصیه میکند برای Endpointهای محافظتشده API Key در Request لازم باشد، اما روی API Key بهتنهایی برای Resourceهای حساس یا باارزش تکیه نشود.
و مهمتر:
API Key نباید داخل Source Code بماند.
- نه در Repository خصوصی با این تصور که «کسی نمیبیند».
- نه داخل Docker Image.
- نه در JavaScript سمت Client.
- نه در فایل Configurationای که بین تیمها دستبهدست میشود.
Secretهایی مثل API Key، Database Credential، Certificate و SSH Key باید بهصورت متمرکز ذخیره، کنترل، Audit و در صورت نیاز Rotate شوند. OWASP در Secrets Management Cheat Sheet دقیقاً روی همین چرخه مدیریت Secret تأکید میکند.
Secret خوب، Secretی نیست که هیچوقت تغییر نکند؛ Secretی است که بتوان آن را کنترل و Rotate کرد.
هر ورودی را Untrusted فرض کنید
حتی اگر درخواست از یک سیستم Partner یا API داخلی آمده باشد، Input نباید بدون Validation مصرف شود.
OWASP توصیه میکند Validation تا جای ممکن زود و هنگام دریافت داده از منبع خارجی انجام شود و ورودی از منابعی مثل Partnerها و Vendorها هم بهعنوان داده بالقوه Untrusted دیده شود.
Validation باید دو سطح داشته باشد:
Syntactic Validation
آیا ساختار داده درست است؟
مثلاً:
- این فیلد واقعاً Integer است؟
- تاریخ Format درستی دارد؟
- String بیش از اندازه طولانی نیست؟
- JSON با Schema مورد انتظار سازگار است؟
Semantic Validation
آیا مقدار در Context کسبوکار منطقی است؟
مثلاً:
- تعداد سفارش منفی نیست؟
- تاریخ پایان قبل از تاریخ شروع قرار نگرفته؟
- تخفیف ۸۰۰ درصد نیست؟
- کاربر اجازه تغییر این Status را دارد؟
JSON Schema و Validatorهای Framework میتوانند کمک زیادی کنند، اما Business Rule هنوز باید در Backend کنترل شود.
Rate Limiting فقط برای DDoS نیست
فرض کنید Login API محدودیت ندارد.
مهاجم میتواند هزاران Credential را امتحان کند.
یا Endpoint ارسال OTP میتواند هزاران پیام ایجاد کند.
یا یک API پردازش تصویر، AI یا Report Generation با چند Request هزینه Compute زیادی ایجاد کند.
OWASP این دسته را Unrestricted Resource Consumption مینامد.
Rate Limiting میتواند بر اساس موارد مختلف طراحی شود:
- IP
- User
- API Key
- Client
- Endpoint
- Tenant
- یا حتی Cost هر Operation
یک Request ساده GET و یک Request که پنج دقیقه CPU مصرف میکند، الزاماً نباید Limit مشابهی داشته باشند.
OWASP REST Security Cheat Sheet نیز استفاده از 429 Too Many Requests برای Clientهایی که بیش از حد Request میفرستند را توصیه میکند.
Rate Limit فقط یک عدد نیست.
بخشی از Business Logic امنیتی API است.
Business Flowها را هم محافظت کنید
گاهی تکتک Requestها معتبرند، اما مجموع رفتار مخرب است.
مثلاً:
- خرید خودکار تمام موجودی یک محصول محدود
- ساخت تعداد زیادی حساب جعلی
- رزرو خودکار Slotها
- ارسال هزاران Coupon Request
- یا سوءاستفاده از Workflow بازیابی Password
در این حالت ممکن است Authentication و Authorization هر دو درست کار کنند.
مشکل، سوءاستفاده از یک Business Flow حساس است.
OWASP در نسخه ۲۰۲۳ برای همین مسئله دسته مستقلی با عنوان Unrestricted Access to Sensitive Business Flows اضافه کرده است.
Rate Limiting، Anti-automation، Risk Scoring و در بعضی سناریوها Human Verification باید متناسب با ارزش همان Flow طراحی شوند.
به APIهای دیگر هم کورکورانه اعتماد نکنید
API شما ممکن است خودش امن باشد، اما به ده سرویس دیگر متصل شود.
- Payment Gateway
- CRM
- Shipping Provider
- AI API
- Webhook
- سرویس احراز هویت
- یا API یکی از Partnerها
دادهای که از یک API خارجی میآید همچنان باید Validate شود.
OWASP در Unsafe Consumption of APIs هشدار میدهد که Developerها گاهی به سرویسهای خارجی بیش از حد اعتماد میکنند و روی Transport Security، Authentication، Authorization یا Validation آنها سختگیری کمتری دارند.
Third-party بودن یک Response به معنی Trusted بودن آن نیست.
URLهایی که API دریافت میکند میتوانند خطرناک باشند
برخی APIها URL میگیرند:
- Webhook URL
- Image URL
- Callback
- Import from URL
- PDF Generator
- Preview Service
- یا Integration Endpoint
اگر Server بدون محدودیت به هر URL دریافتی Request بزند، ممکن است مهاجم از آن برای دسترسی به Resourceهایی استفاده کند که از بیرون قابل دسترسی نیستند.
این حمله با عنوان Server-Side Request Forgery یا SSRF شناخته میشود و OWASP آن را در API Security Top 10 قرار داده است.
برای چنین Featureهایی باید مقصدهای مجاز، Protocolها، Redirectها و دسترسی Network بهدقت محدود شوند.
APIهای قدیمی را فراموش نکنید
یکی از مشکلات امنیت API این است که Endpointهای قدیمی گاهی بیشتر از خود تیم عمر میکنند.
نسخه جدید:
/api/v3
منتشر میشود.
اما:
/api/v1
هنوز از اینترنت قابل دسترسی است.
کسی هم دقیق نمیداند چه Clientی از آن استفاده میکند.
OWASP این مشکل را Improper Inventory Management مینامد.
برای APIها باید Inventory واقعی داشته باشید:
- چه APIهایی داریم؟
- Owner هرکدام کیست؟
- کدام Version فعال است؟
- کدام Public است؟
- کدام Internal است؟
- کدام Deprecated شده؟
- چه زمانی باید Retire شود؟
Documentation در اینجا فقط برای Developer Experience نیست.
بخشی از امنیت است.
APIای که نمیدانید وجود دارد، سختتر از APIای محافظت میشود که میشناسید.
Production جای Debug Mode نیست
Security Misconfiguration میتواند یک API سالم را آسیبپذیر کند.
مواردی مثل:
- Debug Mode فعال
- Default Credential
- CORS بیش از حد باز
- Endpoint مدیریتی Public
- HTTP Methodهای غیرضروری
- TLS ناقص
- Error Message حاوی Stack Trace
- یا Permissionهای پیشفرض نامناسب
OWASP توصیه میکند HTTP Methodها با Allowlist محدود شوند و Requestهایی که Method مجاز ندارند Reject شوند.
Production باید Configuration مخصوص Production داشته باشد.
نه نسخهای از Development Environment که فقط Domain آن عوض شده است.
HTTPS هنوز غیرقابل مذاکره است
Token، Cookie، API Key و اطلاعات حساس نباید روی ارتباط بدون Transport Security حرکت کنند.
RFC 9700 استفاده از TLS انتهابهانتها بین Client و Resource Server را توصیه میکند.
TLS فقط برای Login Endpoint نیست.
تمام API باید از ارتباط امن استفاده کند؛ مخصوصاً وقتی Credential یا داده حساس ردوبدل میشود.
چیزی را Log کنید که فردا به درد Investigation بخورد
امنیت فقط جلوگیری از حمله نیست.
باید بتوانید بفهمید چه اتفاقی افتاده است.
OWASP Logging Cheat Sheet تأکید میکند Application Logging برای Security Eventها باید وجود داشته باشد و میتواند برای شناسایی Incident، Policy Violation، رفتار خودکار مشکوک و Audit Trail استفاده شود.
در API معمولاً اطلاعاتی مثل اینها ارزشمندند:
- چه کسی Request را فرستاد؟
- چه Endpointی فراخوانی شد؟
- چه Operationی انجام شد؟
- موفق بود یا Fail شد؟
- Authorization چرا رد شد؟
- چه Objectی هدف بود؟
- Source کجا بود؟
- چه زمانی اتفاق افتاد؟
- Correlation ID چیست؟
اما Logging خودش نباید تبدیل به Data Leak شود.
Password، Access Token کامل، Secret و اطلاعات حساس را بدون دلیل داخل Log نریزید.
OWASP نیز تأکید میکند Logها ممکن است اطلاعات شخصی و حساس داشته باشند و باید در ذخیره، انتقال و دسترسی محافظت شوند.
تست امنیتی API را به آخر پروژه موکول نکنید
اگر Security Testing فقط یک هفته قبل از Release انجام شود، پیدا شدن یک مشکل معماری میتواند بسیار گران باشد.
بهتر است بخشی از کنترلها وارد Development Lifecycle شوند:
- Unit Test برای Authorization
- Integration Test برای Roleها
- Test با دو Identity متفاوت برای BOLA
- Schema Validation Test
- Rate Limit Test
- JWT Validation Test
- Dependency Scanning
- Secret Scanning
- SAST
- DAST
- و تست Endpointهای قدیمی یا فراموششده
OWASP حتی API Security Testing Framework خود را برای پوشش ریسکهای API Top 10 توسعه داده و Test Caseهایی برای BOLA، Broken Authentication، Resource Consumption و Function Level Authorization دارد.
امنیت API یک Gate آخر Pipeline نیست.
بخشی از Definition of Done است.
یک چکلیست عملی امنیت API
| موضوع | سؤال |
|---|---|
| Authentication | آیا هویت Client/User با روش مناسب تأیید میشود؟ |
| Authorization | آیا هر Request در سطح Function و Object کنترل میشود؟ |
| Properties | آیا فقط فیلدهای مجاز خوانده و تغییر داده میشوند؟ |
| Least Privilege | آیا Token و Service فقط دسترسی لازم را دارند؟ |
| OAuth | آیا Flowها با Best Practice جدید همخوان هستند؟ |
| JWT | آیا Signature، Algorithm، Issuer، Audience و Expiry Validate میشوند؟ |
| Secrets | آیا API Key و Credential خارج از Source Code مدیریت میشوند؟ |
| Input | آیا تمام دادههای خارجی Syntactic و Semantic Validation دارند؟ |
| Rate Limit | آیا مصرف Resource و Abuse محدود میشود؟ |
| Business Flows | آیا Flowهای حساس در برابر Automation محافظت میشوند؟ |
| Third Parties | آیا Response سرویسهای خارجی هم Untrusted در نظر گرفته میشود؟ |
| SSRF | آیا URL و Callbackهای ورودی محدود و Validate میشوند؟ |
| Inventory | آیا همه APIها و Versionها Owner مشخص دارند؟ |
| Transport | آیا ارتباط API با TLS محافظت میشود؟ |
| Logging | آیا رخدادهای امنیتی قابل ردیابیاند بدون اینکه Secretها Log شوند؟ |
| Testing | آیا تست امنیت بخشی از CI/CD و Release Process است؟ |
امنیت API از کجا شروع میشود؟
نه از خرید یک Gateway.
نه از JWT.
نه از OAuth.
و حتی نه از WAF.
همه اینها ابزارند.
امنیت API از تعریف درست Trust Boundary شروع میشود.
- چه کسی وارد سیستم میشود؟
- چه چیزی میتواند بخواند؟
- چه چیزی میتواند تغییر دهد؟
- چند بار میتواند این کار را انجام دهد؟
- کدام داده از سیستم خارج میشود؟
- و اگر رفتار غیرعادی رخ داد، چه کسی متوجه میشود؟
یک API امن معمولاً نتیجه یک قابلیت عجیب و پیچیده نیست.
نتیجه تعداد زیادی تصمیم کوچک است که درست گرفته شدهاند.
هر Request باید فقط همان کاری را انجام دهد که واقعاً اجازه انجامش را دارد؛ نه یک قدم بیشتر.