مطالبی که اینجا مینویسم مواردی است که گهگاه برای خودم پیش آمده است و بیشتر حالت روزمره دارد.
چگونه میتوانیم API-Key را سمت کلاینت مخفی کنیم؟
شاید برای شما هم این مساله پیش آمده باشد که چگونه API-Key ای که به ما، برای استفاده از یک سرویس Endpoint داده شده است را از دید کاربران سایت پنهان کنیم. اینکه API-Key اختصاصی شما توسط دیگران دیده شود، اصلا از لحاظ امنیتی جالب نیست.
اول لازم است که کمی در مورد مساله توضیح بدهم. در صورتی که اپلیکیشن شما با استفاده از جاوااسکریپت بخشی از دیتای موردنظر خود را دریافت می کند، ممکن است که ارایه دهندهی اطلاعات به شما یک API-Key بدهد که از طریق آن کنترل کند که چه کسی به دیتای ارایه شده دسترسی دارد یا حتی بخواهد تعداد درخواستهای شما را کنترل کند.
برای مثال شما یک اشتراک از weather.com برای دریافت وضعیت آب و هوای شهرهای جهان میخرید و سایت به شما یک API-Key میدهد و شما برای استفاده از این سرویس، باید در هر درخواست، این کد را در هدر درخواستهای خود بفرستید.
نکته: معمولا چنین سایتهایی اجازه ی ارسال درخواست از سمت کلاینت به شما نمیدهد (احتمالا خطای Cors خواهد داد) ، اما چرا؟ پاسخ ساده است، چون اگر شما API-Key را سمت کلاینت بگذارید، این کد توسط همه قابل رویت خواهد بود و به ازای هر ویزین سایت شما یک درخواست یه سمت سرور آنها می رود که چیز جالبی نیست.
چطور بفهمیم آیا از API-Key استفاده شده است یا نه؟
کافی است وقتی یک سایت را مشاهده می کنید، بخش Developer Tools را در مرورگر خود فعال کنید و در بخش Network درخواستهای xhr را فیلتر کنید. و روی یک Request کلیک کنید و هدرها را ببینید. احتمالا چنین چیزی مشاهده خواهید کرد.
اگر API-Key ارسال شود شما حتماً در هدرها، آن را مشاهده خواهید کرد. پس اگر API-Key دارید کاربران سمت کلاینت شما اصلا نباید آن را ببینند (سوای اینکه اگر از جای درستی API-Key گرفته باشید اصلا نمیگذارد شما آن را سمت کلاینت اجرا کنید، چون در واقع آن را با همه به اشتراک گذاشتید)
در حالت کلی برای گرفتن اطلاعات عمومی سایتها و اپلیکیشن ها، مانند اخبار و محصولات، خیلی سخت گیری نمیشود و شما مثل صفحات سایت می توانید آنها را با دانستن قالب Endpoint فراخوانی کنید و مساله ای هم ندارد. اما برای دیتای حساس نباید چنین باشد.
راه حل
اما راه حل چیست و چگونه نگذاریم که کسی API Key ما را ببیند؟
نکته ی اول: کلیدتان را تحت هیچ عنوان سمت کلایت نفرستید، به هیچ وجه! نه کد شده، نه عادی و نه به صورت پنهان. هرکاری کنید توسط کاربر کلاینت دیده می شود و خودتان را خسته نکنید.
وقتی خیلی خیلی جوان بودم کلید را هر بار با یک متغیر وابسته به زمان کد می کردم (که مثلا کسی نفهمد) ولی چون الگوریتم کد کردن در اپلیکیشن شما سمت کلاینت میرود، باز هم کدگشایی خواهد شد. البته جلوی کاربران کم تجربه را میگیرید ولی هرکسی که کمی تجربه داشته باشد، کلید شما را استخراج میکند.
چاره ی کار این است که این کار را سمت سرور انجام دهید. یعنی به اصطلاح یک پروکسی بنویسید. سعی میکنم بیشتر توضیح دهم. در واقع باید یک اپلیکیشن جدا سمت سرور بنویسید که درخواستها را از کلاینت، به سمت آن اپلیکیشن بفرستید و آن اپلیکیشن سمت سرور، کلید را داشته باشد و درخواستها از آن اپلیکیشن، به سرویس دهندهی اصلی فرستاده شود و بعد از گرفتن پاسخ یا Response، آن را برای کلاینت بفرستد.
در این صورت هیچکس از API-Key یا حتی قالب Endpoint های شما اطلاعی پیدا نخواهد کرد (یا اینکه شما از چه کسی سرویس گرفتهاید) البته اگر از برخی فریمورک های جاوااسکریپتی مانند Next.js استفاده می کنید، میتوانید یک سری route handler در همان اپ خودتان بنویسید و خیلی کارتان راحت خواهد بود.
این کار فواید دیگری هم دارد:
- می توانید درخواستها را به تناسب Cache کنید که بسیار توصیه می شود.
- اگر سرویس دهنده عوض شود، شما لازم نیست که کدتان را سمت کلاینت تغییر دهید، فقط کافی است، بخش proxy را تغییر دهید.
در پایان همیشه حواستان به امنیت اپلیکیشنتان باشد، هیچ وقت مسایل امنیتی را کم ارزش تلقی نکنید! به قول معروف ؛خیلی خطرناکه حسن 😁
مطلبی دیگر از این انتشارات
آیا از CSS Framework ها مانند Tailwind یا Bootstrap استفاده کنیم یا نه؟
مطلبی دیگر از این انتشارات
کالبدشکافی مشکلات و حوادث: یادگیری از شکست
مطلبی دیگر از این انتشارات
توسعه دهندگان انعطاف ناپذیر و نقش سمی آنها در تیم های نرم افزاری