كيفية فك تشفير رمز JWT: دليل عملي للمطورين
عادت واجهة الـAPI لديك للتو بالخطأ 401 Unauthorized، ورأس Authorization: Bearer eyJhbGciOi... يبدو سليمًا ظاهريًا. هل انتهت صلاحية الرمز، أم أن قيمة الجمهور (audience) خاطئة، أم أن المُصدِر دوّر أحد المفاتيح؟ لا تستطيع الإجابة قبل أن تقرأ ما يوجد فعليًا داخل الرمز، ولفك تشفير JWT لا تحتاج سرًا ولا مكتبة ولا حتى اتصالًا بالشبكة. رمز JWT ثلاث قطع مُرمَّزة بـbase64url مفصولة بنقاط، وفكّه عملية ميكانيكية: قسّم، ثم فك base64url، ثم JSON.parse. لا سحر، ولا تعمية.
يأخذك هذا الدليل عبر بنية الرمز، ويوضح كيف تفك JWT في Node.js وPython وGo والمتصفح، ويشرح الفارق بين فك التشفير والتحقق الذي يوقع كثيرًا من الفرق في فخ، ثم يسرد أنماط الفشل الفعلية التي ستصادفها. إذا كنت تحتاج فحص رمز الآن فقط، اقفز إلى مفكك JWT المجاني؛ فهو يعمل بالكامل داخل متصفحك، فلا تغادر رموز الإنتاج جهازك.
ما هو JWT؟ نظرة سريعة على البنية
رمز JSON Web Token (أو JWT) هو بيان اعتماد مضغوط وآمن للاستخدام في عناوين URL، ومُعرَّف في RFC 7519. يحمل مطالبات (claims) عن المستخدم وعن الرمز نفسه بين طرفين. ويتكوّن JWT من ثلاث قطع مُرمَّزة بـbase64url مفصولة بنقاط: هيدر، وبيلود، وتوقيع.
إليك رمزًا حقيقيًا مفصولًا لترى البنية:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 ← header
.
eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0 ← payload
.
4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0 ← signature
يصف الهيدر طريقة توقيع الرمز، وعادةً يأتي بالشكل { "alg": "HS256", "typ": "JWT" }. ويحمل البيلود المطالبات، سواء المسجّلة منها مثل sub وexp وiat، أو المخصصة مثل role وtenant. أما التوقيع فهو إثبات تعمية محسوب على الهيدر والبيلود، ويتيح للمستلم اكتشاف أي تلاعب. وBase64url نسخة من base64 آمنة لعناوين URL؛ راجع دليل Base64 المبسَّط لمقدمة من عشر دقائق.
ستقابل رموز JWT في كل مكان تسكنه المصادقة الحديثة: رموز الوصول في OAuth 2.0، ورموز الهوية في OpenID Connect، وبيانات اعتماد واجهات API التي تُصدرها Auth0 وOkta وClerk وSupabase وFirebase، والرموز المنقولة بين الخدمات المصغّرة داخل شبكة خدمات. هي ببساطة صيغة بيان الاعتماد الافتراضية للعقد الأخير.
قبل أن نمضي، جملة واحدة يجب أن ترسّخها: رموز JWT مُرمَّزة وليست مُشفَّرة. أي شخص يحمل الرمز يستطيع قراءة كل مطالبة فيه. التوقيع يُثبت المصدر؛ لا يُخفي المحتوى. هذه الحقيقة وحدها تحكم كل شيء آخر في هذا الدليل: ما الذي يصحّ وضعه في البيلود، ولماذا لا يحتاج فك التشفير إلى سر، ولماذا يكون التحقق من التوقيع على جانب الخادم أمرًا غير قابل للتفاوض.
كيف يعمل فك تشفير JWT (base64url، لا فك تشفير تعمية)
فك تشفير JWT ليس عملية تعمية، بل أربع خطوات ميكانيكية:
- قسّم الرمز عند
.إلى ثلاثة مقاطع بالضبط. - فكّ ترميز المقطع الأول بـbase64url ثم حلّله كـJSON، فتحصل على الهيدر.
- فكّ ترميز المقطع الثاني بـbase64url ثم حلّله كـJSON، فتحصل على البيلود.
- اترك المقطع الثالث (التوقيع) بايتات خام، فالتحقق منه يتطلب المفتاح.
هذه هي الخوارزمية بالكامل. لا توجد مكتبة إلزامية. أي لغة فيها base64 ومحلّل JSON تستطيع فك تشفير JWT في خمسة أسطر. وسيقوم مرمّز/مفكك Base64 لدينا بالخطوتين 2 و3 يدويًا إذا أردت رؤية الميكانيكا بعينيك.
ما هو base64url؟
Base64url هو base64 عادي مع ثلاثة تعديلات تجعل الخرج آمنًا في عناوين URL وترويسات HTTP: يحل - محل +، ويحل _ محل /، وتُحذف حشوة = من النهاية. وإذا أدخلت base64url الخام في مفكك base64 قياسي دون عكس هذه الاستبدالات، فستحصل إما على هراء أو على خطأ. ويغطي دليل Base64 المتقدم حالات حافة الحشوة بتعمق.
| base64 قياسي | base64url | |
|---|---|---|
| الأبجدية | A-Z a-z 0-9 + / | A-Z a-z 0-9 - _ |
| الحشوة | = مطلوبة في النهاية | محذوفة |
| آمن لعناوين URL؟ | لا | نعم |
| مثال | PDw/Pz8+ | PDw_Pz8- |
تنبيه ثانٍ يستحق الحبر: لا يمكنك فك تشفير التوقيع من جانب العميل. فك التشفير عملية أحادية الاتجاه من البايتات المُرمَّزة إلى JSON، أما التحقق من التوقيع فعملية منفصلة تحتاج إما إلى سر HMAC (لعائلة خوارزميات HS) أو إلى المفتاح العام للمُصدِر (لـRS وPS وES وEdDSA).
لماذا لا تحتاج إلى السر لفك التشفير
لأن البيلود عبارة عن base64url زائد JSON، وليس نصًا مُعمَّى. لا يدخل السر في الصورة إلا حين تريد إثبات أن الرمز لم يُعبث به، أي عند فحص التوقيع. أي شخص على مسار الشبكة، وأي شخص يرى الرمز في سطر سجل، وأي شخص لديه متصفح، يستطيع قراءة كل مطالبة تضعها داخله. لذلك يجب ألا تضع كلمات المرور أو مفاتيح API أو أي بيانات شخصية تتجاوز ما يعرفه المستلم مسبقًا داخل بيلود JWT. ولنموذج التهديد الأوسع، اقرأ دليل أفضل ممارسات الأمان.
فك تشفير JWT أونلاين في 3 نقرات، مع مفكك JWT مجاني
أحيانًا تحتاج إجابة في هذه اللحظة فقط: هل انتهت صلاحية هذا الرمز، هل قيمة aud هي ما تظن، هل يقول الهيدر alg:none؟ أسرع طريق هو مفكك JWT أونلاين لدينا، وقد بُني لمسار الاستجابة للحوادث في الساعة الثانية صباحًا.
- الصق الرمز الكامل في منطقة الإدخال، متضمّنًا المقاطع الثلاثة المفصولة بالنقاط.
- اقرأ الهيدر والبيلود المفكوكَين وشرائح الحالة في الأعلى: الخوارزمية، وقت الإصدار، وقت الانتهاء، وشارة
Expiredحمراء إذا كانت exp في الماضي. - انسخ أي لوحة تحتاجها إلى تقرير الخطأ أو مناقشة Slack أو مطابقة اختبار.
لماذا هو آمن على رموز الإنتاج الحقيقية؟
- يعمل 100% في المتصفح. يجري فك التشفير عبر
atobوJSON.parseالأصلية، ولا يوجد طلب شبكة. - لا تسجيل ولا تتبع ولا ملفات ارتباط ولا اشتراك.
- يعمل بدون اتصال بمجرد تحميل الصفحة.
أداة مفكك JWT محايدة من حيث الخوارزمية. ولأن فك التشفير لا يحتاج سوى base64url وJSON، فإنه يقرأ كل نسخة من JWS: HS256/384/512 وRS256/384/512 وPS256/384/512 وES256/384/512 وEdDSA وalg:none. فقط التحقق من التوقيع يعتمد على الخوارزمية، وهو ليس شيئًا تريد أن تقوم به أداة ويب عامة، وسنعود إلى هذه النقطة بعد قليل.
أتحتاج إلى فك ترميز مقطع يدويًا بـbase64 للتحقق المتقاطع؟ استخدم مرمّز/مفكك Base64 وأَدخِل كل مقطع كـbase64url.
كيفية فك تشفير JWT في الكود (Node.js، Python، Go، المتصفح)
لكل شيء ليس تصحيحًا تفاعليًا (الوسيطيات، الاختبارات، نصوص الهجرة، أدوات CLI) ستمدّ يدك إلى مكتبة. وفيما يلي الحد الأدنى من الكود لفك تشفير JWT في البيئات الأربع التي من المرجح أن تواجهها، مع مسار القراءة فقط ومسار التحقق جنبًا إلى جنب. وكل مقتطف قابل للنسخ واللصق وينتج المخرجات الموضحة في التعليقات.
فك تشفير JWT في Node.js (jsonwebtoken)
// npm install jsonwebtoken
const jwt = require('jsonwebtoken');
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' +
'.eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0' +
'.4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0';
// فك التشفير فقط — لا يتحقق من التوقيع
const decoded = jwt.decode(token, { complete: true });
console.log(decoded.header); // { alg: 'HS256', typ: 'JWT' }
console.log(decoded.payload); // { sub: 'user_123', exp: 1999999999 }
// التحقق — مسار الإنتاج
const secret = process.env.JWT_SECRET;
const verified = jwt.verify(token, secret, { algorithms: ['HS256'] });
مرّر دائمًا قائمة سماح صريحة لـalgorithms إلى verify. فإغفال ذلك سمح تاريخيًا للمهاجمين بتخفيض رمز RS256 إلى HS256، وذلك بالتوقيع بالمفتاح العام كسر HMAC، وهو هجوم الالتباس الكلاسيكي في الخوارزميات. وقائمة السماح هي دفاعك الأول.
فك تشفير JWT في Python (PyJWT)
# pip install PyJWT
import jwt
token = (
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
".eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0"
".4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0"
)
# فك التشفير فقط — غير آمن للمصادقة، مناسب للفحص
decoded = jwt.decode(token, options={"verify_signature": False})
print(decoded) # {'sub': 'user_123', 'exp': 1999999999}
# الهيدر دون لمس البيلود
header = jwt.get_unverified_header(token)
print(header) # {'alg': 'HS256', 'typ': 'JWT'}
# التحقق — مسار الإنتاج
payload = jwt.decode(
token,
key="your-hs256-secret",
algorithms=["HS256"],
audience="api.example.com",
)
ترفض PyJWT التحقق بدون قائمة algorithms، وهو افتراض سليم يمنع هجوم الالتباس ذاته الذي حذّر منه مثال Node.
فك تشفير JWT في Go (golang-jwt/jwt/v5)
// go get github.com/golang-jwt/jwt/v5
package main
import (
"fmt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +
".eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTk5OTk5OTk5OX0" +
".4NhxPjwoZxPNuxG-2C5ugGxaUsUJ0QyskAz7Ymz5Sg0"
// فك التشفير فقط
parser := jwt.NewParser()
claims := jwt.MapClaims{}
_, _, err := parser.ParseUnverified(tokenString, claims)
if err != nil {
panic(err)
}
fmt.Println(claims["sub"], claims["exp"]) // user_123 1.999999999e+09
// التحقق
secret := []byte("your-hs256-secret")
token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected alg: %v", t.Header["alg"])
}
return secret, nil
})
fmt.Println(token.Valid, err)
}
إغلاق keyFunc هو المكان الذي تفرض فيه عائلة الخوارزميات؛ ارفض أي شيء ليس الطريقة التي تتوقعها قبل إعادة المفتاح.
فك تشفير JWT في المتصفح (دون أي اعتماديات)
أحيانًا لا ترغب في أي اعتمادية إطلاقًا: لوحة تصحيح سريعة، أو امتداد للمتصفح، أو شارة واجهة مستخدم صغيرة تُظهر دور المستخدم الحالي. وتكفيك واجهات المتصفح الأصلية:
function decodeJwt(token) {
const [h, p] = token.split('.');
const pad = (s) => s + '==='.slice((s.length + 3) % 4);
const decodeSegment = (s) => {
const b64 = pad(s).replace(/-/g, '+').replace(/_/g, '/');
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
return JSON.parse(new TextDecoder().decode(bytes));
};
return { header: decodeSegment(h), payload: decodeSegment(p) };
}
const { header, payload } = decodeJwt(token);
console.log(header); // { alg: 'HS256', typ: 'JWT' }
console.log(payload); // { sub: 'user_123', exp: 1999999999 }
تمرير TextDecoder مهم لأي رمز يحتوي على بيلود غير ASCII (إيموجي في اسم معروض، أو حروف سيريلية في preferred_username)، لأن atob وحده يُعيد سلسلة ثنائية تكسر JSON.parse على UTF-8 متعدد البايتات. وهذا بالضبط ما يشغّله مفكك JWT أونلاين محليًا في متصفحك، ناقصًا واجهة المستخدم.
جدول المقارنة
| اللغة | فك التشفير فقط | التحقق | المكتبة |
|---|---|---|---|
| Node.js | jwt.decode(token) | jwt.verify(token, key, { algorithms: [...] }) | jsonwebtoken |
| Python | jwt.decode(token, options={"verify_signature": False}) | jwt.decode(token, key, algorithms=[...]) | PyJWT |
| Go | parser.ParseUnverified(token, claims) | jwt.Parse(token, keyFunc) | golang-jwt/jwt/v5 |
| المتصفح | atob + TextDecoder + JSON.parse | اسأل الخادم الخلفي | — |
فك التشفير مقابل التحقق، الفرق الحاسم
فك تشفير JWT يقرأ مطالباته، والتحقق من JWT يُثبت أن تلك المطالبات لم يُعبث بها. فك التشفير لا يثق؛ التحقق هو الثقة نفسها. وهذا هو الفارق الوحيد الذي يفصل بين تنفيذ مصادقة سليم وبين ثغرة أمنية مُعلنة.
| فك التشفير | التحقق | |
|---|---|---|
| يحتاج سرًا/مفتاحًا؟ | لا | نعم |
| يعمل من جانب العميل؟ | بأمان | أبدًا |
| يُثبت الأصالة؟ | لا | نعم |
| يفحص انتهاء الصلاحية؟ | اختياري | نعم |
| حالة الاستخدام | التصحيح، الفحص | المصادقة، التفويض |
لا تتخذ قرار تفويض اعتمادًا على JWT مفكوك (غير مُتحقَّق منه). ليس في الوسيطيات، ولا في خطاف React، ولا في دالة عديمة الخادم تظن أنها خلف البوابة. المطالبات المفكوكة تقول ما يدّعيه الرمز، بينما المطالبات المُتحقَّق منها تقول ما وقّعه المُصدِر فعلًا. ويستطيع مهاجم يسلّم خادمك رمزًا مصنوعًا يدويًا دون توقيع صالح أن يضع ما يشاء في البيلود، وفحص التوقيع وحده هو ما يرفضه.
تفصيلة أخرى حاسمة في عائلة HMAC: إن استخدمت HS256، فإن عشوائية سرّك هي اللعبة كلها. سر قصير قابل للتخمين يُكسر بالقوة الغاشمة بلا اتصال ضد أي رمز يلتقطه المهاجم، وعندها يصك رموزه الخاصة ويدخل من الباب الأمامي. استخدم 256 بت على الأقل من عشوائية حقيقية. وراجع دليل قوة أسرار HMAC لمعرفة حسابات أهمية ذلك.
مرجع مطالبات JWT الشائعة
كل JWT تلقاه يستخدم مجموعة فرعية من المطالبات المسجّلة في RFC 7519. احفظ القائمة القصيرة:
| المطالبة | الاسم | مثال | ملاحظات |
|---|---|---|---|
iss | المُصدِر (Issuer) | https://auth.example.com | من صكّ الرمز |
sub | الموضوع (Subject) | user_123 | عادةً معرّف المستخدم |
aud | الجمهور (Audience) | api.example.com | لمن الرمز — يجب أن يتطابق على الخادم |
exp | انتهاء الصلاحية (Expiration) | 1715003600 | ثوانٍ يونكس؛ الماضي يعني منتهية |
iat | وقت الإصدار (Issued At) | 1715000000 | ثوانٍ يونكس وقت صكّ الرمز |
nbf | ليس قبل (Not Before) | 1715000060 | أبكر وقت يصلح فيه الرمز |
jti | معرّف JWT | d1f8… | فريد لكل رمز، ويمنع إعادة التشغيل |
kid | معرّف المفتاح (في الهيدر) | key-2025-01 | أي مفتاح في JWKS وقّع هذا |
تجلس المطالبات الخاصة بالتطبيق إلى جانب هذه: role وscope وemail وtenant_id، أيًا ما يصدره مزوّد الهوية لديك. أبقِها قصيرة، فكل بايت يُرافق كل طلب.
لقراءة تواريخ مفهومة من iat وexp، جرّب محوّل طوابع Unix الزمنية. الصق الرقم، واحصل على التاريخ في منطقتك الزمنية المحلية، واكتشف خطأ انحراف الساعة في ثانية.
استكشاف الأخطاء، لماذا لا يُفكُّ رمز JWT الخاص بي؟
خمسة أنماط فشل حقيقية، بترتيب تقريبي للتكرار، وكل واحد مُؤطَّر ضمن العَرَض ← السبب ← الحل.
- “صيغة JWT غير صالحة، يتوقع ثلاثة مقاطع.” نسخت البيلود وحده، أو غلّفت الصدفة الرمز عبر أسطر والتقطت أول سطر فقط. الحل: أعد نسخ القيمة الكاملة
xxx.yyy.zzzمن متن الاستجابة الأصلي، لا من طرفية معروضة. القيم الطويلة ذات السطر الواحد تبقى أسلم في لوحة شبكة أدوات مطوّري المتصفح منها في طرفية قيد التمرير. - خمسة مقاطع بدلًا من ثلاثة. لديك JWE (رمز JWT مُشفَّر) لا JWS. الصيغة هي
header.encryptedKey.iv.ciphertext.tag. سيقرأ المفكك الهيدر، لكن البيلود نص مُعمَّى. الحل: فك تشفير البيلود يتطلب مفتاح فك التشفير، ويُدار عادةً من جانب الخادم بواسطة SDK المصادقة لديك، لا بأداة تصحيح. - خطأ base64url في رمز يبدو سليمًا. جرى ترميز الرمز بـURL في مكان ما من مسار النسخ (ملف ارتباط، عنوان إعادة توجيه، سجل وكيل ملتقَط). سترى
%2Eأو%2Bحرفيًا في السلسلة. الحل: فك ترميز URL أولًا، ثم أَدخِل النتيجة في مفكك JWT. - خطأ تحليل JSON في البيلود. أدخلت طرفية أو عميل محادثة أسطرًا جديدة من التغليف الناعم، أو لصقت أداة نصية علامات اقتباس ذكية حول معرّف. الحل: شاهد بايتات الاستجابة الخام (curl مع
-o file.txt، أو عرض Raw في أدوات المطوّر)، ثم انزع المسافات والصق مجددًا. - يُفك بوضوح لكن الخادم الخلفي يرفضه. ليست مشكلة فك تشفير، بل مشكلة تحقق. الرمز سليم بنيويًا، وشيء ما يفحصه الخادم (التوقيع، aud، exp، انحراف الساعة، بحث kid) يفشل. انتقل إلى القسم التالي.
وذكر شرفي لحالتين ليستا خطأي تحليل لكنهما تستحقان الالتقاط ومفكك الرمز مفتوح: قيمة alg تساوي none في الهيدر (تعامل معها كمعادية في الإنتاج)، وقيمة exp في الماضي (يُظهر المفكك المطالبات ليتسنى لك التصحيح، وهذا سلوك صحيح، وأداتنا تشير إليه بشارة Expired حمراء).
حين لا يكفي فك التشفير، التحقق من التوقيع
فك التشفير ينتهي عند “إليك ما يدّعيه الرمز”، والتحقق هو ما يحوّل ادعاءً إلى قرار ثقة. التوقيع إثبات محسوب بالمفتاح الخاص للمُصدِر أو بسر مشترك، يربط الهيدر بالبيلود؛ غيّر بايتًا واحدًا وسيفشل فحص التوقيع. وبدون هذا الفحص، يستطيع أي شخص يمكنه إرسال POST إلى نقطة نهايتك أن يصنع يدويًا رمز “مسؤول” بتحرير البيلود وتخطي التوقيع تمامًا.
لا تقبل alg:none أبدًا.
يبدو التحقق في الإنتاج، في كل لغة وإطار عمل، قائمة تدقيق تشبه هذه تقريبًا. تعامل مع أي عنصر ناقص كخلل:
- مرّر قائمة سماح صريحة مثل
algorithms: ['RS256'](أو ما تستخدمه). هذا يُبطل هجمات الالتباس في الخوارزميات. - تحقق أن aud يطابق معرّف خدمتك وأن iss يطابق عنوان URL للمُصدِر المتوقَّع.
- افحص exp مقابل الوقت الحالي مع سماح بانحراف ساعة بـ 60 ثانية كحد أقصى.
- عند تدوير المفاتيح، ابحث عن المفتاح العام بـkid من نقطة نهاية JWKS، ولا تُرمّز مفتاحًا واحدًا إلى الأبد.
- أبطل بفعالية بإبقاء exp قصيرة (دقائق لا أيامًا)، وبإمكانية الحفاظ على قائمة حظر jti للرموز عالية القيمة.
كل مكتبة JWT شائعة تعرض هذه كخيارات في استدعاء واحد. وإذا لم يُعيّنها كود التحقق لديك، فأنت تترك الافتراضات على حالها، والافتراضات كانت تاريخيًا هي الخلل. ولنموذج التهديد الكامل، راجع دليل أفضل ممارسات الأمان.
الأسئلة الشائعة
هل يمكنني فك تشفير JWT بدون مفتاح سري؟
نعم. الهيدر والبيلود مُرمَّزان بـbase64url وليسا مُشفَّرَين، فأي شخص يحمل الرمز يستطيع قراءة مطالباته. والسر أو المفتاح العام مطلوب فقط للتحقق من التوقيع. هذا بالتصميم: البيلود مصمَّم ليكون قابلًا للقراءة حتى يستطيع المستلم اتخاذ قرارات تفويض.
هل من الآمن لصق JWT الإنتاج الخاص بي في مفكك أونلاين؟
فقط إذا كان المفكك يعمل في متصفحك ولا يرفع الرمز أبدًا. مفكك JWT لدينا يحلّل محليًا عبر atob وJSON.parse الأصلية، فلا يُرسَل شيء إلى أي خادم. أما أدوات التصحيح عن بُعد التي تُرسل رمزك عبر POST إلى واجهة API، فينبغي معاملتها كتسريبات بيانات اعتماد.
ما الفرق بين فك تشفير JWT والتحقق منه؟
فك التشفير يقرأ المطالبات فقط، فلا يحتاج إلى مفتاح ولا يُثبت شيئًا. والتحقق يفحص التوقيع مقابل مفتاح المُصدِر ويؤكد أن الرمز لم يُعبث به. لا تتخذ قرار مصادقة اعتمادًا على رمز مفكوك لكن غير مُتحقَّق منه.
رمز JWT الخاص بي يبدو مقطوعًا، ما الذي يُعدّ صيغة صالحة؟
رمز JWT الصالح يحتوي بالضبط على ثلاثة مقاطع base64url مفصولة بنقاط: header.payload.signature. وجود خمسة مقاطع يعني أن لديك رمز JWT مُشفَّرًا (JWE) لا JWS. وصفر نقاط يعني أنك نسخت مقطعًا واحدًا فقط من سطر طرفية مُغلَّف.
لماذا لا يزال المفكك يُظهر رمزًا منتهي الصلاحية؟
يقرأ المفكك المطالبات بصرف النظر عن الصلاحية ليتسنى لك تصحيح حالات الرفض. فقط المُتحقِّق يرفض الرموز المنتهية. وأداتنا تُبرز شارة Expired بمقارنة exp بساعتك المحلية، حتى تكتشف المشكلة فورًا دون تحديق في طوابع Unix الزمنية.
أي الخوارزميات يمكنني فك تشفيرها؟
كلها. فك التشفير لا يحتاج سوى base64url وتحليل JSON، وهو محايد من حيث الخوارزمية. وهذا يشمل HS256/384/512 وRS256/384/512 وPS256/384/512 وES256/384/512 وEdDSA وalg:none. فقط التحقق يعتمد على الخوارزمية التي اخترتها.
هل أستخدم jwt-decode أم jsonwebtoken في Node.js؟
استخدم jwt-decode على الواجهة الأمامية حين تحتاج فقط إلى قراءة البيلود، مثل عرض اسم مستخدم من رمز وصول. واستخدم jsonwebtoken في الخادم الخلفي، لأن الخادم الخلفي وحده يستطيع الاحتفاظ بمفتاح التوقيع وتنفيذ jwt.verify. لا تتحقق على جانب العميل أبدًا.
الخاتمة
فك تشفير JWT ليس قريبًا من الغموض الذي توحي به عبارة “رمز تعمية”. تمسّك بخمس خلاصات ولن تعود عالقًا تُحدّق في سلسلة eyJhbGciOi… مبهمة:
- فك التشفير هو base64url زائد تحليل JSON. لا سر مطلوب.
- يتكوّن JWT من ثلاثة أجزاء (هيدر، بيلود، توقيع) موصولة بنقاط.
- فك التشفير لا يُثبت الأصالة. تحقق دائمًا على جانب الخادم بمفتاح المُصدِر.
- ارفض
alg:none، ومرّر دائمًا قائمة سماح خوارزميات صريحة إلىverify. - لا تُخزّن كلمات المرور أو المفاتيح الخاصة أو بيانات شخصية حساسة في البيلود أبدًا، فهي قابلة للقراءة من قِبل أي شخص يحمل الرمز.
أضف مفكك JWT المجاني إلى المفضلة لتصحيح أخطاء نوبات العمل. الصق رمزًا، اقرأ المطالبات، اكتشف انتهاء الصلاحية في ثانية، كل ذلك دون أن يغادر رمزك المتصفح.