ক্যাটাগরি Story

  • JWT Parser গাইড: JSON Web Token কীভাবে ডিকোড, ভ্যালিডেট ও পরিদর্শন করবেন

    JWT Parser গাইড: JSON Web Token কীভাবে ডিকোড, ভ্যালিডেট ও পরিদর্শন করবেন

    প্রোডাকশনে আপনার অথেনটিকেশন হঠাৎ কাজ করা বন্ধ করে দিয়েছে। ব্যবহারকারীরা “Invalid Token” এরর পাচ্ছেন, আর আপনাকে দ্রুত কারণ খুঁজে বের করতে হবে। আপনি JWT টোকেনটি খুললেন, আর তা দেখায় এলোমেলো কিছু অক্ষর: ডট দিয়ে আলাদা তিনটি ব্লক। ডেটা ভেতরে আছে, কিন্তু একটি পার্সার ছাড়া আপনি তা পড়তে পারবেন না।

    একটি JWT Parser হলো এমন একটি বিশেষায়িত টুল, যা RFC 7519 স্ট্যান্ডার্ড অনুসরণ করে একটি JSON Web Token-এর তিনটি অংশ — Header, Payload এবং Signature — আলাদা করে। ২০২৬ সালের এপ্রিল পর্যন্ত, এই পার্সারগুলো Base64URL-এনকোড করা ডেটা ডিকোড করে এবং টোকেন কোনোভাবে পরিবর্তিত হয়নি তা নিশ্চিত করতে সিক্রেট বা পাবলিক কী ব্যবহার করে সিগনেচার যাচাই করে, যার ফলে “alg: none” আক্রমণের মতো হুমকি আটকানো যায়।

    একটি JWT Parser আসলে কী করে

    JWT পার্সারকে একজন অনুবাদক হিসেবে ভাবুন। এটি একটি দীর্ঘ, অস্বচ্ছ স্ট্রিং নেয় এবং তাকে পুনরায় পঠনযোগ্য JSON অবজেক্টে রূপান্তর করে। আধুনিক অ্যাপ্লিকেশনে ব্যবহারকারীর পরিচয় পরিচালনা ও ডেটা বিনিময় নিরাপদ করার জন্য এটি মৌলিকভাবে জরুরি।

    অভ্যন্তরীণভাবে, পার্সার দুটি পিরিয়ড (.) খুঁজে বের করে যা টোকেনটিকে তিনটি অংশে ভাগ করে:

    অংশ উদ্দেশ্য এনকোডেড? কী ছাড়া পঠনযোগ্য?
    Header মেটাডেটা: সাইনিং অ্যালগরিদম (HS256, RS256) Base64URL হ্যাঁ
    Payload ক্লেইম: ব্যবহারকারীর ডেটা, মেয়াদ শেষ, রোল Base64URL হ্যাঁ
    Signature সততা প্রমাণকারী ডিজিটাল সিল HMAC/RSA না — কী প্রয়োজন

    একটি JWT টোকেনের সরলীকৃত ৩-অংশের কাঠামো

    ধাপে ধাপে ডিকোডিং: ভেতরে কী ঘটে

    একটি বাস্তব টোকেনের মধ্য দিয়ে আমরা ট্রেস করে দেখি। এই উদাহরণের JWT-টি নিন:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE3MDAwMDAwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    

    ধাপ ১: পিরিয়ডে ভাগ করুন

    [0] eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    [1] eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE3MDAwMDAwMDB9
    [2] SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    

    ধাপ ২: অংশ [0] Base64URL-ডিকোড করুন (Header)

    {
      "alg": "HS256",
      "typ": "JWT"
    }
    

    ধাপ ৩: অংশ [1] Base64URL-ডিকোড করুন (Payload)

    {
      "sub": "1234567890",
      "name": "John",
      "iat": 1700000000
    }
    

    ধাপ ৪: অংশ [2] যাচাই করুন (Signature) — সিক্রেট কী প্রয়োজন

    পার্সার Base64URL-এনকোড করা header + “.” + payload নেয়, তারপর সিক্রেট ব্যবহার করে একটি HMAC-SHA256 গণনা করে। যদি ফলাফলটি অংশ [2]-এর সাথে মিলে যায়, তবে টোকেনটি সত্যিকারের।

    গুরুত্বপূর্ণ নিরাপত্তা নোট: Base64URL এনক্রিপশন নয়

    নতুন ডেভেলপারদের একটি সাধারণ ফাঁদ হলো ধরে নেওয়া যে এনকোড করা header ও payload এনক্রিপ্ট করা। তা নয়। JustUse.me যেমন বলেছে, Base64URL এনকোডিং শুধু JSON-কে URL ও header-এর মাধ্যমে নিরাপদে পাঠানোর উপযোগী করে। যার কাছেই টোকেন আছে, সে কোনো পাসওয়ার্ড বা কী ছাড়াই payload ডিকোড করতে পারবে।

    কখনোই সংবেদনশীল ডেটা (পাসওয়ার্ড, SSN, API কী) JWT payload-এ সংরক্ষণ করবেন না। টোকেন ইন্টারসেপ্ট করা যে কারও কাছে এটি দৃশ্যমান।

    সিগনেচার ভেরিফিকেশন: নিরাপত্তার গেট

    যে কেউ একটি টোকেনের ডেটা পড়তে পারে, কিন্তু আপনার সিস্টেমকে আসলে নিরাপদ রাখে সিগনেচার ভেরিফিকেশন। একটি JWT পার্সার শুধু তথ্য পড়ে না — এটি প্রমাণ করে তা কোথা থেকে এসেছে।

    পার্সার header, payload ও একটি কী ব্যবহার করে সিগনেচার পুনরায় গণনা করে, তারপর যাচাই করে ফলাফল টোকেনের সিগনেচারের সাথে মেল কি না। যদি না মেলে, তবে টোকেনটি পরিবর্তিত হয়েছে।

    দুটি অ্যালগরিদম পরিবার

    অ্যালগরিদম কী-এর ধরন কীভাবে কাজ করে সাধারণ ব্যবহার
    HS256 (HMAC) সিমেট্রিক — সাইন ও ভেরিফাইয়ের জন্য একই সিক্রেট কী উভয় পক্ষ একটি সিক্রেট শেয়ার করে একক-সার্ভিস অথ, এক টিমের মাইক্রোসার্ভিস
    RS256 (RSA) অ্যাসিমেট্রিক — প্রাইভেট কী সাইন করে, পাবলিক কী ভেরিফাই করে প্রেরক প্রাইভেট কী রাখে; পাবলিক কী সহ যে কেউ ভেরিফাই করতে পারে OAuth2 প্রোভাইডার, থার্ড-পার্টি API ইন্টিগ্রেশন
    ES256 (ECDSA) অ্যাসিমেট্রিক — RSA-এর মতোই মডেল কিন্তু এলিপটিক কার্ভ সহ ছোট কী, দ্রুত ভেরিফিকেশন মোবাইল অ্যাপ, পারফরম্যান্স-সংবেদনশীল সার্ভিস

    একটি JWT পার্সারের ৩-ধাপের ভেরিফিকেশন লজিক

    “alg: none” আক্রমণ

    এটি JWT-এর অন্যতম বিপজ্জনক ভালনারেবিলিটি। আক্রমণকারী header পরিবর্তন করে দাবি করে "alg": "none" এবং সিগনেচার মুছে ফেলে। দুর্বলভাবে তৈরি একটি পার্সার এটি গ্রহণ করতে পারে, কোনো ভেরিফিকেশন ছাড়াই টোকেনটিকে বৈধ হিসেবে গণ্য করে।

    প্রতিরক্ষা: আপনার পার্সারকে অবশ্যই স্পষ্টভাবে সেই সব টোকেন প্রত্যাখ্যান করতে হবে যেখানে অ্যালগরিদম “none” অথবা আপনার প্রত্যাশিত অ্যালগরিদমের সাথে মেলে না। Stas Persiianenko, যিনি Apify JWT টুলটি তৈরি করেছেন, তিনি জোর দিয়ে বলেন যে টোকেনগুলো নকশানুসারেই স্বচ্ছ, কিন্তু তাদের নিরাপত্তা নির্ভর করে পার্সারের উপর যে সে সাইনবিহীন বা পরিবর্তিত টোকেন কঠোরভাবে প্রত্যাখ্যান করবে।

    decoded = jwt.decode(token, key, algorithms=None)  # NEVER do this
    
    decoded = jwt.decode(token, key, algorithms=["HS256"])
    

    স্ট্যান্ডার্ড JWT ক্লেইম: প্রতিটি ফিল্ডের অর্থ

    একটি JWT পার্সার payload থেকে “ক্লেইম” বের করে। ক্রস-সিস্টেম সামঞ্জস্যের জন্য এগুলো JOSE (JSON Object Signing and Encryption) ফ্রেমওয়ার্ক অনুসরণ করে।

    ক্লেইম পূর্ণ নাম উদ্দেশ্য উদাহরণ মান
    iss Issuer কে টোকেনটি ইস্যু করেছে "auth.example.com"
    sub Subject টোকেন যে ব্যবহারকারী বা সত্তাকে নির্দেশ করে "user:12345"
    aud Audience টোকেনের উদ্দিষ্ট গ্রহীতা "api.example.com"
    exp Expiration Time কবে টোকেনটি অবৈধ হবে 1700000000 (Unix timestamp)
    iat Issued At টোকেনটি কবে তৈরি হয়েছিল 1699999999
    nbf Not Before এই সময়ের আগে টোকেন বৈধ নয় 1699999999
    jti JWT ID টোকেনের জন্য স্বতন্ত্র শনাক্তকারী "a1b2c3d4"

    অ্যাসিমেট্রিক সিগনেচার ব্যবহারের সময়, পার্সারগুলো প্রায়ই একটি JWK (JSON Web Key) উল্লেখ করে — যা একটি পাবলিক কী-কে নির্দেশকারী JSON কাঠামো। পার্সার টোকেন যাচাই করতে ইস্যুয়ারের মেটাডেটা এন্ডপয়েন্ট থেকে সঠিক JWK স্বয়ংক্রিয়ভাবে আনে।

    বাস্তবায়ন: প্রোডাকশনের জন্য আসল কোড

    PHP-তে lcobucci/jwt দিয়ে

    PHP ইকোসিস্টেমের স্ট্যান্ডার্ড হলো lcobucci/jwtPackagist-এর তথ্য অনুযায়ী, ২০২৬ সালের এপ্রিল পর্যন্ত এটি 322 মিলিয়নের বেশি বার ইনস্টল হয়েছে, যা একে Laravel ও Symfony প্রজেক্টের প্রথম পছন্দে পরিণত করেছে।

    use Lcobucci\JWT\Configuration;
    use Lcobucci\JWT\Signer\Hmac\Sha256;
    use Lcobucci\JWT\Signer\Key\InMemory;
    
    $config = Configuration::forSymmetricSigner(
        new Sha256(),
        InMemory::plainText('your-secret-key')
    );
    
    // Parsing and validating a token
    $token = $config->parser()->parse($jwtString);
    
    // Verify constraints: expiration, issuer, etc.
    $constraints = [
        new \Lcobucci\JWT\Validation\Constraint\IssuedBy('auth.example.com'),
        new \Lcobucci\JWT\Validation\Constraint\PermittedFor('api.example.com'),
        new \Lcobucci\JWT\Validation\Constraint\SignedWith(
            $config->signer(),
            $config->signingKey()
        ),
    ];
    
    $isValid = $config->validator()->validate($token, ...$constraints);
    

    Hono (Edge/Serverless) Web Crypto সহ

    হালকা এজ অ্যাপ্লিকেশনের জন্য, Hono JWT Helper একটি ন্যূনতম decode() ফাংশন দেয় যা সার্ভারলেস প্ল্যাটফর্মের জন্য উপযুক্ত, যেখানে আপনি দ্রুত কোল্ড স্টার্ট ও সর্বনিম্ন ডিপেন্ডেন্সি চান।

    import { jwt } from 'hono/jwt'
    
    // Middleware to verify JWT on every request
    app.use('/api/*', jwt({ secret: 'your-secret' }))
    
    // Access decoded claims in your handler
    app.get('/api/profile', (c) => {
      const payload = c.get('jwtPayload')
      return c.json({ user: payload.sub })
    })
    

    MCP দিয়ে AI-চালিত JWT বিশ্লেষণ

    ২০২৬ সালের মধ্যে, Model Context Protocol (MCP) Claude Code বা Cursor-এর মতো AI অ্যাসিস্ট্যান্টদের সরাসরি JWT টুলের সাথে কথা বলার সুযোগ দেয়। একটি MCP সার্ভার সেট আপ করুন, আর একজন ডেভেলপার AI-কে বলতে পারেন “এই লগগুলোর সব JWT-তে মেয়াদ-শেষ এরর আছে কিনা দেখো” — এজেন্ট কমান্ড লাইনের মাধ্যমে পার্সিং সামলে নেয়।

    Apify-এর মতে, ২০২৬ সাল অনুযায়ী বাল্ক প্রসেসিংয়ের খরচ প্রতি ১০,০০০ টোকেনে প্রায় $11.50। এই অটোমেশন AI এজেন্টদের মেয়াদ শেষ হওয়া টোকেন খুঁজে বের করতে এবং অ্যাপের নিরাপত্তা সেটিংসের জন্য সাথে সাথে কোড ফিক্স সাজেস্ট করতে দেয়।

    উপসংহার

    একটি JWT পার্সার শুধু ডিবাগিংয়ের সুবিধা নয় — এটি একটি অত্যাবশ্যকীয় নিরাপত্তা চেকপয়েন্ট। এটি সিগনেচার চেকের মাধ্যমে নিশ্চিত করে যে টোকেনগুলো সত্যিকারের, আর ক্লেইম ভেরিফিকেশনের মাধ্যমে নিশ্চিত করে যে সেগুলো বৈধ। সবচেয়ে গুরুত্বপূর্ণ দুটি নিয়ম মনে রাখুন: Base64URL এনক্রিপশন নয়, তাই payload-এ কখনো সিক্রেট রাখবেন না। আর “alg: none” আক্রমণ রোধে সবসময় অনুমোদিত অ্যালগরিদম স্পষ্টভাবে উল্লেখ করুন।

    প্রোডাকশন অ্যাপের জন্য, নিজের পার্সার তৈরি করার বদলে lcobucci/jwt বা Hono-এর JWT হেল্পারের মতো প্রমাণিত লাইব্রেরি ব্যবহার করুন। ডিবাগিং ও বাল্ক বিশ্লেষণের জন্য, AI-চালিত MCP টুলগুলো হলো নিরাপত্তা অডিট স্বয়ংক্রিয় ও পুঙ্খানুপুঙ্খ রাখার আধুনিক পদ্ধতি।

    FAQ

    আমার ব্রাউজারে পাওয়া একটি JWT টোকেন ডিকোড করা কি বৈধ?

    হ্যাঁ, এটি সম্পূর্ণ বৈধ। JWT-গুলো নকশানুসারেই স্বচ্ছ হওয়ার জন্য তৈরি — header ও payload পরিবহনের সুবিধার্থে এনকোড করা হয়, গোপনীয়তার জন্য এনক্রিপ্ট করা হয় না। টোকেনটির অধিকার থাকার অর্থ হলো আপনার কাছে এর ক্লেইমের ডেটায় অ্যাক্সেস আছে। তবে, যখন টোকেনে ব্যক্তিগত তথ্য থাকে, তখন সবসময় GDPR-এর মতো স্থানীয় ডেটা সুরক্ষা আইন মেনে চলুন।

    আমি এইমাত্র তৈরি করা একটি টোকেনের ক্ষেত্রে আমার JWT পার্সার কেন isExpired: true দেখাচ্ছে?

    এটি সাধারণত টোকেন তৈরিকারী সার্ভার ও এটি পার্স করা সিস্টেমের মধ্যে ক্লক ড্রিফট-এর কারণে হয়। যদি দুটি সিস্টেমের ঘড়ি (UTC/NTP-এর মাধ্যমে) সিঙ্ক্রোনাইজড না থাকে, তবে exp বা nbf ক্লেইমগুলো অবৈধ মনে হতে পারে। উভয় সিস্টেম যাতে NTP ব্যবহার করে নিশ্চিত করে এটি ঠিক করুন, অথবা ছোট স্কিউ মেনে নেওয়ার জন্য আপনার পার্সিং লাইব্রেরিতে একটি ছোট “leeway” (সাধারণত 60 seconds) যোগ করুন।

    আমি কি সিক্রেট বা পাবলিক কী ছাড়া একটি JWT ডিকোড করতে পারি?

    হ্যাঁ, আপনি সবসময় কী ছাড়াই Header ও Payload ডিকোড করে পড়তে পারেন, কারণ সেগুলো কেবল Base64URL-এনকোড করা JSON। তবে, সংশ্লিষ্ট সিক্রেট (HS256-এর জন্য) বা পাবলিক কী (RS256-এর জন্য) ছাড়া আপনি Signature ভেরিফাই করতে বা ডেটা সত্যিকারের বলে বিশ্বাস করতে পারবেন না। ভেরিফিকেশন ছাড়া, ডেটাকে অযাচাইকৃত এবং সম্ভবত পরিবর্তিত হিসেবে বিবেচনা করুন।

    “alg: none” আক্রমণ কী এবং আমি কীভাবে তা প্রতিরোধ করব?

    “alg: none” আক্রমণ সেই সব পার্সারকে কাজে লাগায় যেগুলো টোকেন header-এ উল্লেখিত অ্যালগরিদম যাচাই ছাড়াই গ্রহণ করে। একজন আক্রমণকারী header পরিবর্তন করে "alg": "none" করে দেয় এবং সিগনেচার মুছে ফেলে, যার ফলে একটি ভালনারেবল পার্সার টোকেনটিকে বৈধ হিসেবে গ্রহণ করে। আপনার ভেরিফিকেশন কোডে সবসময় অনুমোদিত অ্যালগরিদম স্পষ্টভাবে উল্লেখ করে এটি প্রতিরোধ করুন — কখনোই “none” গ্রহণ করবেন না বা টোকেনকে কোন অ্যালগরিদম ব্যবহার করবে তা নির্ধারণ করতে দেবেন না।