تطبيق مصادقة JWT في واجهات برمجة تطبيقات Node.js باحترافية

آخر تحديث: 02/11/2026
نبذة عن الكاتب: ج مصدر تريل
  • تتيح JWT المصادقة غير المعتمدة على الحالة والقابلة للتوسع لواجهات برمجة تطبيقات Node.js، وتتكامل بسلاسة مع مسارات Express والبرامج الوسيطة.
  • يؤدي الجمع بين Express و Mongoose و jsonwebtoken و bcrypt و Joi و dotenv إلى إنشاء أساس آمن ووحدات نمطية لتدفقات مصادقة المستخدم.
  • تتيح عملية التحقق من صحة JWT المستندة إلى JWKS لواجهات برمجة تطبيقات Node.js الوثوق بخوادم التخويل الخارجية وفرض النطاقات والمطالبات بشكل واضح.
  • يعد التحقق الشامل ومعالجة الأخطاء الواضحة والاختبار المنظم أمورًا ضرورية للحفاظ على نقاط النهاية المحمية بتقنية JWT قوية.

مصادقة واجهة برمجة تطبيقات JWT في Node.js

إذا كنت تقوم ببناء واجهات برمجة التطبيقات باستخدام Node.js، فإن إضافة المصادقة المناسبة باستخدام JWT هي واحدة من تلك الأشياء التي قد تبدو مخيفة في البداية، ولكن ليس بالضرورة أن تكون كذلك. باستخدام عدد قليل من المكتبات المختارة بعناية، وهيكل واضح، وبعض الممارسات الجيدة المتعلقة بالتحقق والأمان، يمكنك حماية نقاط النهاية الخاصة بك مع الحفاظ على قاعدة التعليمات البرمجية الخاصة بك نظيفة وقابلة للصيانة.

في هذا الدليل، سنشرح كيفية تنفيذ المصادقة المستندة إلى JWT في واجهة برمجة تطبيقات Node.js باستخدام Express وMongoDB وأدوات مثل jsonwebtoken وbcrypt وJoi وdotenv، وسنرى أيضًا كيفية التحقق من صحة الرموز المميزة باستخدام نقطة نهاية JWKS من خادم التخويل في سيناريوهات أكثر توجهاً نحو المؤسسات. ستتعلم كيفية تصميم هيكل المشروع، وإنشاء النماذج والمسارات، وإنشاء الرموز المميزة والتحقق منها، وإضافة برنامج وسيط للمصادقة، وربط كل شيء معًا بحيث لا يتمكن من الوصول إلى الموارد المحمية إلا المستخدمون المصادق عليهم.

ما الذي توفره رموز JSON Web Tokens (JWT) لواجهات برمجة تطبيقات Node.js الخاصة بك؟

رموز الويب JSON (JWT) هي رموز مضغوطة وآمنة للاستخدام في عناوين URL، تحمل مجموعة من المطالبات وتسمح لطرفين بتبادل المعلومات الموثقة دون الاحتفاظ بحالة جلسة الخادم. في سياق واجهة برمجة تطبيقات Node.js، هذا يعني أنه بمجرد تسجيل دخول المستخدم وإصدار JWT، يمكن التحقق من كل طلب لاحق بواسطة الواجهة الخلفية الخاصة بك باستخدام الرمز المميز نفسه ومفتاح سري أو عام فقط، وهو ما يتوسع بشكل أفضل بكثير من جلسات الخادم التقليدية.

يتكون رمز JWT النموذجي من ثلاثة أجزاء: رأس، وحمولة، وتوقيع، وكلها مشفرة باستخدام Base64URL ومفصولة بنقاط، على سبيل المثال xxxxx.yyyyy.zzzzz. يحدد رأس الطلب عادةً الخوارزمية ونوع الرمز المميز، وتحتوي الحمولة على مطالبات متعلقة بالمستخدم مثل المعرف أو الأدوار أو الأذونات، ويضمن التوقيع سلامة الرمز المميز بحيث لا يمكن التلاعب به دون اكتشافه.

عند تطبيق JWT في واجهات برمجة تطبيقات Node.js، عادةً ما تستخدم الرمز المميز كرمز حامل في Authorization رأس HTTP، مثل Authorization: Bearer <token>ثم قم بفك تشفيرها والتحقق من صحتها داخل برنامج Express الوسيط أو معالجات المسار. إذا كان الرمز المميز صالحًا، يمكنك إرفاق الحمولة التي تم فك تشفيرها بكائن الطلب واستخدامها لاحقًا لاتخاذ قرارات التفويض أو لتخصيص الاستجابة.

أحد الجوانب القوية لرموز JWT هو أنها مستقلة عن اللغة ومدعومة على نطاق واسع عبر الأنظمة البيئية، مما يجعلها خيارًا ممتازًا لتأمين واجهات برمجة التطبيقات التي تستخدمها React أو Vue أو تطبيقات الهاتف المحمول أو أي عميل تابع لجهة خارجية. بالإضافة إلى التحقق القوي وإدارة المفاتيح المناسبة، فإنها تسمح لخدمات Node.js بالمشاركة بسلاسة في بنى OAuth 2.0 و OpenID Connect.

نظرة عامة على المشروع: واجهة برمجة تطبيقات Node.js مع مصادقة JWT

لنتخيل واجهة برمجة تطبيقات Node.js بسيطة ولكنها واقعية حيث يمكن للمستخدمين التسجيل وتسجيل الدخول والوصول إلى نقاط النهاية المحمية فقط بعد تقديم رمز JWT صالح. سنعتمد على Express للتوجيه، وMongoose لتكامل MongoDB، وjsonwebtoken لإنشاء الرموز المميزة والتحقق منها، وbcrypt لتجزئة كلمات المرور الآمنة، وJoi للتحقق من صحة المدخلات، وdotenv لإدارة التكوين.

يساعد تصميم المجلدات النظيف على إبقاء الأمور مفهومة مع نمو المشروع، لذلك بدلاً من وضع كل شيء في ملف واحد، سنقوم بتحديد بنية أساسية مع وحدات منفصلة للتكوين وقاعدة البيانات والنماذج والمسارات والبرامج الوسيطة. كما أن هذا النهج المعياري يجعل من السهل اختبار أجزاء محددة من عملية المصادقة.

على مستوى عالٍ، ستعرض واجهة برمجة التطبيقات مجموعة من نقاط نهاية REST لتسجيل المستخدمين وتسجيل الدخول، بالإضافة إلى مورد محمي واحد على الأقل لا يمكن الوصول إليه إلا باستخدام JWT صالح في رؤوس الطلب. سنرى خلال هذه العملية كيفية التحقق من صحة حمولات الطلبات، وتجزئة كلمات المرور ومقارنتها، وإنشاء رموز مميزة تتضمن معرف المستخدم، ودمج برنامج وسيط للمصادقة يتحقق من الرموز المميزة في المكالمات الواردة.

يمكن توسيع النمط نفسه ليشمل أنظمة أكثر تعقيدًا، بما في ذلك تلك التي تتكامل مع خادم ترخيص خارجي وتستخدم نقاط نهاية JWKS للتحقق من صحة رموز الوصول الواردة من عملاء OAuth 2.0. هذا السيناريو الثاني شائع بشكل خاص عندما تقوم بتفويض المصادقة إلى موفري الهوية أو تحتاج إلى دعم تسجيل الدخول الموحد عبر خدمات متعددة.

قبل أن ننتقل إلى تفاصيل التنفيذ، دعونا نحدد الأجزاء الرئيسية للبيئة التي سنعتمد عليها ولماذا كل تبعية مهمة للتعامل الآمن مع JWT في Node.js.

المتطلبات الأساسية لمصادقة JWT في Node.js

يُعد Express العمود الفقري للعديد من واجهات برمجة تطبيقات Node.js، حيث يوفر إطار عمل بسيط ولكنه مرن للتوجيه والبرمجيات الوسيطة ومعالجة HTTP. في حالتنا، ستكون منصة Express هي المنصة التي نسجل من خلالها مسارات مثل /api/users or /api/authوحيث نقوم بتوصيل برنامج وسيط التحقق من JWT الذي يحمي نقاط النهاية الحساسة.

Mongoose هي مكتبة لنمذجة بيانات الكائنات (ODM) تجعل التفاعل مع MongoDB أسهل من خلال المخططات والنماذج، بدلاً من العمل مع الاستعلامات الخام مباشرة. سنستخدمه لتحديد أ User نموذج بخصائص مثل الاسم والبريد الإلكتروني وكلمة المرور، ولحفظ هذه المستندات أو استرجاعها من قاعدة البيانات بطريقة آمنة من حيث النوع.

استخدم jsonwebtoken تُعد المكتبة الخيار القياسي في Node.js لإنشاء والتحقق من JWTs باستخدام مفتاح سري أو مفتاح عام. أثناء تسجيل الدخول، سنقوم بتوقيع رمز مميز يتضمن معرف المستخدم (وأي مطالبات أخرى نحتاجها)، وسنقوم لاحقًا بالتحقق من هذا الرمز المميز على المسارات المحمية، ورفض أي طلب يحمل رمزًا مميزًا غير صالح أو مشوهًا أو منتهي الصلاحية.

لأغراض أمان كلمات المرور، يتم استخدام bcrypt لتجزئة كلمات المرور النصية العادية قبل تخزينها ولمقارنة بيانات الاعتماد المقدمة بالقيم المجزأة أثناء المصادقة. هذا أمر بالغ الأهمية، لأن تخزين كلمات المرور الخام أو استخدام استراتيجيات التجزئة الضعيفة يعرض المستخدمين لمخاطر هائلة في حالة حدوث تسريب في قاعدة البيانات، بينما يوفر bcrypt حلاً مثبتًا ومجربًا.

يلعب Joi دورًا كبيرًا في التحقق من صحة البيانات الواردة عند حدود واجهة برمجة التطبيقات، ووصف مخططات الكائنات والتحقق من أن كل حمولة طلب تتصرف كما هو متوقع. على سبيل المثال، يمكننا تحديد أن البريد الإلكتروني يجب أن يكون منسقًا بشكل صحيح، وأن كلمة المرور لها حد أدنى من الطول، وأن بعض الحقول إلزامية، مما يقلل بشكل كبير من فرص تسلل المدخلات السيئة أو الضارة إلى منطقنا.

وأخيرًا، يسمح لنا dotenv بتحميل متغيرات البيئة من .env ملف، يحتفظ بأسرار مثل مفاتيح توقيع JWT وعناوين URL لقواعد البيانات أو إعدادات التكوين خارج شفرة المصدر. يساعد هذا في تجنب تضمين القيم الحساسة بشكل ثابت، ويعزز الفصل الأفضل بين إعدادات التطوير والتجريب والإنتاج.

إعداد خادم Express وبيئته

نقطة دخول واجهة برمجة التطبيقات الخاصة بنا عادة ما تكون index.js الملف الذي نقوم فيه بتهيئة Express، وتسجيل البرامج الوسيطة، وتركيب تعريفات المسارات الخاصة بنا. سنحتاج في هذا الملف إلى تكوين قاعدة البيانات الخاصة بنا، ووحدات التوجيه الخاصة بنا، وأي برامج وسيطة عالمية مثل تحليل نص JSON أو CORS.

بعد تحميل التبعيات مباشرة، من المستحسن استدعاء require("dotenv").config() لذا، متغيرات البيئة من .env أصبح الملف متاحًا عبر process.env. وهذا يشمل مفاتيح مثل JWT_PRIVATE_KEY, MONGO_URI أو المنفذ الذي سيستمع إليه الخادم، مما يحافظ على مرونة التكوين وأمانه.

سيستخدم تطبيق Express نفسه عادةً app.use(express.json()) لتحليل محتوى طلبات JSON، وسيقوم بتثبيت أجهزة التوجيه لبادئات عناوين URL محددة، مثل app.use("/api/users", usersRouter) و app.use("/api/auth", authRouter). يحافظ هذا الفصل على عزل المسارات المتعلقة بالمصادقة ومخاوف إدارة المستخدمين عن الأجزاء الأخرى من واجهة برمجة التطبيقات.

بعد تهيئة البيئة وتشغيل Express، تتمثل الخطوة التالية في ربط قاعدة بيانات MongoDB من خلال وحدة مخصصة، وغالبًا ما تكون db.js الملف، حيث نقوم بإعداد منطق الاتصال.

تهيئة MongoDB باستخدام Mongoose

في خانة رمز الخصم، أدخل TABBYDAY. db.js في الوحدة النمطية، نقوم عادةً باستيراد Mongoose واستدعاء mongoose.connect() مع تخزين سلسلة اتصال MongoDB في متغير بيئي. يمكننا أيضًا تكوين خيارات مثل منطق إعادة المحاولة، أو البنية الموحدة، أو تجميع الاتصالات لضمان سلوك مستقر في بيئات الإنتاج.

من الشائع تسجيل رسالة عند نجاح الاتصال ومعالجة الأخطاء بسلاسة بحيث إذا كان الوصول إلى MongoDB غير ممكن، يبدأ تشغيل واجهة برمجة التطبيقات مع تشخيصات واضحة. في تطبيق كامل، قد تختار حتى إنهاء العملية إذا فشل الاتصال بقاعدة البيانات، لأن العديد من المسارات تعتمد عليه.

بمجرد db.js تم تنفيذ الملف، نقوم باستيراده من index.js واستدعائها مبكراً أثناء بدء تشغيل التطبيق، مع التأكد من أن واجهة برمجة التطبيقات الخاصة بنا متصلة بقاعدة البيانات قبل معالجة أي طلب. يحافظ هذا الفصل على عزل التكوين وإمكانية إعادة استخدامه، بينما index.js لا يزال التركيز منصباً على مخاوف إكسبريس.

بعد ربط قاعدة البيانات، يمكننا الانتقال إلى نمذجة البيانات التي تشغل نظام المصادقة الخاص بنا، والذي يبدأ بتعريف مخطط ونموذج المستخدم.

بناء نموذج المستخدم باستخدام دعم JWT

استخدم User نموذج، يوضع عادة في /models/user.js، يحدد بنية مستندات المستخدم المخزنة في MongoDB ويغلف السلوك المتعلق بالمصادقة. على الأقل، سنقوم بتضمين خصائص مثل name, email و passwordوقد نضيف أيضًا الطوابع الزمنية أو الأدوار أو البيانات الوصفية الأخرى حسب الحاجة.

يتمثل النمط المعتاد في وضع علامة على حقل البريد الإلكتروني على أنه فريد ومطلوب، مما يضمن عدم تمكن مستخدمين من التسجيل بنفس عنوان البريد الإلكتروني. وبالمثل، لن يخزن حقل كلمة المرور قيمة نصية عادية؛ بدلاً من ذلك، سنقوم بتخزين تجزئة bcrypt التي تم إنشاؤها في وقت التسجيل أو عندما يقوم المستخدم بتحديث بيانات اعتماده.

يتمثل أحد قرارات التصميم المثيرة للاهتمام والعملية للغاية في إضافة طريقة على مخطط المستخدم لإنشاء رموز JWT، والتي تأخذ معرف المستخدم كحمولة وتوقعها بمفتاح سري محدد في البيئة. يمكن استدعاء هذه الطريقة أثناء تسجيل الدخول لإنتاج رمز مميز خاص بهذا المستخدم، وهي تحافظ على منطق إنشاء الرمز المميز موجودًا جنبًا إلى جنب مع النموذج الذي يمتلك بيانات الهوية.

بالإضافة إلى أدوات التحقق القائمة على Joi، يصبح نموذج المستخدم هو العنصر المركزي لكل ما يتعلق بالهوية: وصف شكل بيانات المستخدم، والتحقق من صحة البيانات الواردة، وإنشاء الرموز المميزة التي تستخدمها بقية واجهة برمجة التطبيقات.

ومن هنا، يمكننا تنفيذ المسارات المسؤولة عن تسجيل الحسابات الجديدة والتحقق من المستخدمين الحاليين، باستخدام نموذج المستخدم و bcrypt و Joi جنبًا إلى جنب.

إنشاء مسار التسجيل

عادةً ما توجد منطق التسجيل في وحدة توجيه مثل /routes/users.jsحيث نحدد نقطة نهاية مثل POST /api/users لمعالجة طلبات التسجيل الواردة. سيقوم هذا المسار بالتحقق من صحة البيانات المرسلة باستخدام Joi، والتحقق مما إذا كان البريد الإلكتروني قيد الاستخدام بالفعل، وتجزئة كلمة المرور، وإنشاء المستخدم وحفظه في قاعدة البيانات.

قبل حفظ أي شيء، يمكننا استخدام مخطط Joi الذي يفرض متطلبات مثل الاسم والبريد الإلكتروني الإلزامي، وتنسيق البريد الإلكتروني المناسب، والحد الأدنى لطول كلمة المرور. في حالة فشل التحقق، يستجيب المسار برمز حالة خطأ ورسالة مناسبة، مما يمنع البيانات المشوهة من الوصول إلى منطق العمل.

إذا لم يكن البريد الإلكتروني موجودًا بالفعل، فإننا نقوم بإنشاء ملح bcrypt وتجزئة كلمة المرور، واستبدال كلمة المرور الخام بنسختها المجزأة في كائن المستخدم. هذه القيمة المجزأة هي ما يتم تخزينه في النهاية في MongoDB، مما يحد بشكل كبير من تأثير الاختراقات المحتملة للبيانات.

بعد حفظ المستخدم الجديد، تختار بعض التطبيقات أيضًا إنشاء JWT على الفور وإعادته في رأس الاستجابة أو نصها، بحيث يتم اعتبار المستخدم مصادقًا عليه مباشرة بعد التسجيل. قد تتطلب واجهات برمجة التطبيقات الأخرى خطوة تسجيل دخول منفصلة، ​​وذلك حسب متطلبات الأمان الخاصة بالنظام.

بمجرد إتمام عملية التسجيل، يمكن للمسار المصاحب لتسجيل الدخول إعادة استخدام الكثير من منطق التحقق نفسه مع التركيز على التحقق من بيانات الاعتماد وإصدار الرموز المميزة.

تنفيذ مسار تسجيل الدخول وتوليد الرمز المميز

تتم معالجة عملية تسجيل الدخول عادةً في /routes/auth.js، مع نقطة نهاية مثل POST /api/auth الذي يستقبل البريد الإلكتروني وكلمة المرور في نص الطلب. يستخدم هذا المسار Joi مرة أخرى للتأكد من وجود كلا الحقلين وهيكلتهما بشكل صحيح قبل محاولة مصادقة المستخدم.

بعد التحقق، يستعلم المسار من قاعدة البيانات عن مستخدم لديه البريد الإلكتروني المحدد، وإذا وجد واحدًا، فإنه يستخدم bcrypt لمقارنة كلمة المرور المقدمة مع التجزئة المخزنة. إذا فشلت المقارنة، يتم رفض الطلب مع رسالة خطأ مناسبة؛ وإلا، ننتقل إلى إصدار الرمز المميز.

في لحظة المصادقة الناجحة، نقوم باستدعاء طريقة توليد الرموز المميزة المحددة في نموذج المستخدم، والتي تقوم بإنشاء JWT مضمنة معرف المستخدم (وربما مطالبات أخرى) وتوقيعها بمفتاح سري. يمكن بعد ذلك إرسال هذا الرمز المميز إلى العميل، غالبًا في نص الاستجابة أو في رأس مخصص، حيث يقوم الواجهة الأمامية أو المستهلك الخارجي بتخزينه وإعادة استخدامه للطلبات المستقبلية.

من وجهة نظر العميل، ستتضمن كل مكالمة لاحقة إلى نقاط النهاية المحمية رمز JWT هذا في Authorization رأسية كرمز حامل، وهو بالضبط ما سيبحث عنه برنامجنا الوسيط. من جانب الخادم، يضمن وجود برنامج وسيط مخصص للمصادقة عدم تكرار منطق التحقق من الرمز المميز في كل مسار.

قبل الخوض في تفاصيل هذه البرمجيات الوسيطة، تجدر الإشارة إلى أن هذا النمط نفسه يتكامل بشكل جيد مع React أو أطر عمل SPA الأخرى، حيث تُستخدم التدفقات القائمة على JWT بشكل شائع لكل من المصادقة واحتياجات التخويل البسيطة.

بناء برنامج وسيط للمصادقة لحماية المسارات

غالبًا ما يتم تنفيذ برنامج الوسيط الخاص بالمصادقة في /middleware/auth.js، يعمل كحارس بوابة لأي مسار يتطلب المصادقة، حيث يعترض الطلبات قبل وصولها إلى معالج المسار. تتمثل وظيفتها الأساسية في قراءة JWT من Authorization قم بفحص رأس الطلب، ثم قم بإدخال البيانات التي تم فك تشفيرها في كائن الطلب لاستخدامها لاحقًا.

تبدأ البرمجية الوسيطة بالتحقق من أن Authorization يوجد رأس الصفحة ويتبع ما هو متوقع Bearer <token> التنسيق؛ إذا كان الرمز المميز مفقودًا أو غير صحيح، فإنه يستجيب على الفور برمز حالة غير مصرح به. وهذا يضمن عدم تسلل الطلبات غير المحمية عن طريق الخطأ إلى نقاط النهاية الآمنة.

عند وجود رمز مميز، يقوم البرنامج الوسيط باستدعاءات jwt.verify() (من jsonwebtoken المكتبة)، تمرير الرمز المميز والمفتاح السري أو العام المستخدم للتوقيع. إذا فشلت عملية التحقق بسبب انتهاء الصلاحية أو عدم تطابق التوقيع أو أي مشكلة أخرى، فإن البرنامج الوسيط يستجيب بخطأ؛ وإلا فإنه يلتقط الحمولة التي تم فك تشفيرها.

تقوم العديد من التطبيقات بإرفاق هذه الحمولة التي تم فك تشفيرها بـ req.user أو خاصية مماثلة، بحيث يمكن لمعالجات المسار اللاحقة الوصول إلى المطالبات المتعلقة بالمستخدم دون الحاجة إلى إعادة تحليل أو إعادة التحقق من الرمز المميز. وأخيرًا، استدعاءات البرمجيات الوسيطة next() لتمرير التحكم إلى الوظيفة التالية في مسار Express.

من خلال الجمع بين هذه البرامج الوسيطة وتعريفات المسارات، يمكننا بسهولة وضع علامة على بعض نقاط النهاية على أنها عامة والبعض الآخر على أنها محمية ببساطة عن طريق إضافة البرامج الوسيطة إلى سلسلة معالجة الطلبات لتلك المسارات.

الوصول إلى الموارد المحمية باستخدام JWT

تتمثل إحدى حالات الاستخدام الشائعة بعد تطبيق المصادقة في توفير مسار يجلب ملف تعريف المستخدم الحالي أو قائمة المستخدمين، والتي لا يمكن الوصول إليها إلا من قبل المتصلين الذين يقدمون رمزًا صالحًا. على سبيل المثال، في /routes/users.jsقد يكون هناك GET /api/users/me نقطة نهاية تُرجع معلومات حول المستخدم الذي قام بتسجيل الدخول.

لحماية هذا المسار، نقوم بإرفاق برنامج وسيط المصادقة بحيث يجب أن يحمل أي طلب يصل إليه رمز JWT صالحًا؛ وإلا، فسينهي البرنامج الوسيط الطلب قبل تنفيذ المعالج الفعلي. لأن الحمولة التي تم فك تشفيرها مرفقة بالفعل بـ req.user، يمكن للمعالج استرداد معرف المستخدم مباشرة من الرمز المميز والاستعلام عن قاعدة البيانات وفقًا لذلك.

يضمن هذا النمط أن منطق الأعمال لا يهتم بكيفية إجراء المصادقة؛ فهو ببساطة يثق في وجود حمولة تم التحقق منها ويركز على جلب بيانات المجال أو تعديلها. في الإعدادات الأكثر تقدماً، يمكنك أيضاً تضمين الأدوار أو الأذونات أو النطاقات داخل الرمز المميز واستخدامها لإجراء عمليات التحقق من التفويض في المعالجات.

من وجهة نظر المستهلك، سيقوم المتصل أولاً بالوصول إلى نقطة نهاية تسجيل الدخول للحصول على رمز مميز ثم تضمينه في الطلبات اللاحقة إلى نقاط النهاية المحمية هذه، وغالبًا ما يكون ذلك من تطبيق صفحة واحدة مثل React أو تطبيق جوال أو تكامل بين الخوادم الخلفية. تكون التجربة العامة سلسة إذا كانت رسائل الخطأ واضحة عند انتهاء صلاحية الرمز المميز أو عند كونه غير صالح.

لقد غطينا حتى الآن إعداد JWT مستقل باستخدام سر مخزن في .env ملف، ولكن العديد من أنظمة الإنتاج تتكامل أيضًا مع خوادم التخويل الخارجية وتستخدم نقاط نهاية JWKS للتحقق من صحة الرموز المميزة؛ وهنا يأتي دور برنامج Express الوسيط لواجهات برمجة التطبيقات الآمنة OAuth.

استخدام نقطة نهاية JWKS للتحقق من صحة رموز JWT في Node.js

في البنى الأكثر تقدماً، وخاصة تلك التي تعتمد على OAuth 2.0 و OpenID Connect، غالباً ما تتلقى واجهات برمجة تطبيقات Node.js رموز الوصول الصادرة عن خادم ترخيص خارجي بدلاً من إنشاء JWTs بنفسها. في هذه الحالة، يجب على واجهة برمجة التطبيقات التحقق من صحة الرموز المميزة الموقعة بمفاتيح غير متماثلة، عادةً RSA أو EC، حيث يحتفظ خادم التخويل فقط بالمفتاح الخاص.

يتمثل الحل الشائع في استخدام مكتبة وسيطة Express تقوم بجلب مجموعات مفاتيح الويب JSON (JWKS) من نقطة نهاية مُكوّنة يتم عرضها بواسطة خادم التخويل. تعرض نقطة نهاية JWKS هذه المفاتيح العامة بتنسيق قياسي، مما يسمح لواجهة برمجة التطبيقات بالتحقق من توقيعات JWT الواردة دون الحاجة إلى إدارة المفاتيح الخاصة.

على سبيل المثال، قد تقوم بتثبيت حزمة مثل express-oauth-jwt وقم بتهيئته باستخدام عنوان URL الخاص بـ JWKS، مثل https://idsvr.example.com/oauth/v2/oauth-anonymous/jwksثم قم بتوصيل البرنامج الوسيط بمسارات واجهة برمجة تطبيقات Node.js الخاصة بك. بمجرد دمجها، تتولى البرمجيات الوسيطة تلقائيًا معظم مهام التحقق من صحة الرموز على المستوى الأدنى.

مع تطبيق هذا التكوين، تبحث المكتبة عن kid (معرف المفتاح) من رأس JWT، يقوم بتنزيل المفتاح العام المناسب من نقطة نهاية JWKS (إذا لم يتم تخزينه مؤقتًا بالفعل) ويتحقق من التوقيع باستخدام هذا المفتاح. كما يقوم بفحص تاريخ انتهاء صلاحية الرمز المميز والجهة المصدرة والجمهور والحقول القياسية الأخرى، وذلك حسب كيفية تكوين خياراته.

بعد التحقق الناجح، يصبح رمز JWT المُحلل ومطالباته متاحين على Express request الكائن، مما يتيح لمعالجاتك فحص النطاقات أو معرفات المستخدم أو السمات المخصصة لأغراض التفويض والتسجيل. في حال حدوث أي خطأ (على سبيل المثال، انتهاء صلاحية الرمز المميز أو عدم تطابق التوقيع)، يستجيب البرنامج الوسيط برموز خطأ HTTP المناسبة ويتضمن السبب في WWW-Authenticate رأس.

نطاقات الصلاحيات والمطالبات ومنطق التفويض في واجهة برمجة التطبيقات الخاصة بك

بمجرد أن تثق واجهة برمجة تطبيقات Node.js الخاصة بك في JWT، إما لأنها وقعتها مباشرة أو لأن برنامج وسيط قائم على JWKS قد تحقق منها، فإن الخطوة التالية هي استخدام مطالباتها ونطاقاتها لتنفيذ التفويض. هنا تتجاوز عملية المصادقة البسيطة وتبدأ في منح أو رفض الوصول بناءً على ما يُسمح للمستخدم بفعله.

تمثل النطاقات عادةً أذونات عامة، مثل read:users or write:ordersوعادةً ما يتم تضمينها في رموز JWT تحت مطالبة مثل scope or scopes. يمكن لواجهة برمجة التطبيقات (API) التحقق مما إذا كان النطاق المطلوب موجودًا قبل معالجة طلب يمس بيانات أعمال معينة، وإرجاع استجابة محظورة إذا كان مفقودًا.

وبالمثل، فإن المطالبات مثل معرف المستخدم أو البريد الإلكتروني أو الدور أو معلومات المستأجر تتيح لك تطبيق قواعد أكثر دقة؛ على سبيل المثال، ضمان وصول المستخدمين فقط إلى سجلاتهم الخاصة أو تقييد الإجراءات الإدارية بأدوار محددة. في لغة Express، من السهل كتابة برامج وسيطة مخصصة تقوم بفحص هذه الادعاءات على req.user وتطبيق إجراءات التحقق من السياسات.

توفر بعض مكتبات التحقق من صحة JWT لـ Express خطافات مدمجة للتحقق من النطاقات المطلوبة كجزء من خياراتها، مما يجعل من السهل ربط كل مسار أو جهاز توجيه بمجموعة أذونات محددة. يُبقي هذا النهج مخاوف الترخيص قريبة من تعريفات المسار، مما يحسن من سهولة القراءة والصيانة.

من منظور التصميم، من الأفضل عمومًا التعامل مع نطاقات ومطالبات JWT كجزء من سياسة تصريحية، بدلاً من نثر سلاسل مشفرة بشكل ثابت في جميع أنحاء التعليمات البرمجية الخاصة بك، لتجنب التناقضات وتسهيل التغييرات المستقبلية في نموذج الأمان الخاص بك.

اختبار واستكشاف أخطاء واجهات برمجة تطبيقات Node.js المحمية بـ JWT وإصلاحها

بمجرد توصيل كل شيء، سترغب في اختبار استدعاء واجهة برمجة تطبيقات Node.js الخاصة بك مع وبدون رموز JWT صالحة للتأكد من أن التحكم في الوصول يعمل تمامًا كما هو متوقع. تُعد الأدوات البسيطة مثل curl و HTTPie أو Postman مثالية لهذا الغرض، حيث تتيح لك ضبط الرؤوس والحمولات بسهولة.

تتضمن عملية الاختبار النموذجية أولاً استدعاء نقطة نهاية تسجيل الدخول للحصول على رمز مميز، ثم إرسال طلب ثانٍ إلى مسار محمي باستخدام Authorization: Bearer <token> مجموعة رأس الصفحة. إذا كان تطبيقك صحيحًا، فيجب أن تنجح الطلبات المصرح بها بينما يجب رفض المكالمات بدون رموز مميزة أو برموز مميزة غير صالحة.

عند استخدام مكتبة التحقق من صحة JWT الخاصة بـ Express والمتكاملة مع نقطة نهاية JWKS، غالبًا ما يتم الإشارة إلى أي مشكلة في الرمز المميز بواسطة 401 Unauthorized الرد والمعلومات التفصيلية في WWW-Authenticate رأس الاستجابة. على سبيل المثال، إذا انتهت صلاحية رمز الوصول، فسيشير هذا العنوان عادةً إلى رمز الخطأ المحدد ووصفه.

تُعد رسائل الخطأ المفصلة هذه مفيدة للغاية أثناء التطوير وتصحيح الأخطاء، ولكن يجب عليك توخي الحذر من عدم تسريب معلومات داخلية حساسة للغاية في سجلات الإنتاج أو الاستجابات. غالباً ما يكون من الجيد مركزة تسجيل البيانات وإخفاء أو تعميم بعض الرسائل مع الحفاظ على سياق كافٍ للمشغلين لتشخيص المشكلات.

يمكن للاختبارات الآلية و JWTs الوهمية أن تزيد من ثقتك، مما يسمح لك بالتحقق من أن سلوك التفويض مستقر عند تغيير المسارات أو إضافة نطاقات أو إعادة هيكلة منطق البرامج الوسيطة.

بوضع كل ذلك معًا، فإن واجهة برمجة تطبيقات Node.js التي تجمع بين Express و MongoDB و bcrypt و Joi و JWT - المدعومة اختياريًا بمكتبة التحقق القائمة على JWKS - تمنحك أساسًا قويًا لتأمين نقاط النهاية مع الحفاظ على المرونة الكافية للتكامل مع أطر عمل الواجهة الأمامية الحديثة وتطبيقات الهاتف المحمول وموفري هوية المؤسسات.

الوظائف ذات الصلة: