ToolDeck

JWT Decoder Python — PyJWT দিয়ে JWT ডিকোড গাইড

·DevOps Engineer & Python Automation Specialist·পর্যালোচনা করেছেনMaria Santos·প্রকাশিত

বিনামূল্যে অনলাইন JWT ডিকোডার সরাসরি আপনার ব্রাউজারে ব্যবহার করুন — ইনস্টলের প্রয়োজন নেই।

JWT ডিকোডার অনলাইনে ব্যবহার করুন →

টোকেন-ভিত্তিক অথেন্টিকেশন ব্যবহার করে এমন প্রতিটি API কোনো না কোনো সময়ে আপনাকে একটি JWT দেয়, এবং ডেভেলপমেন্টের সময় সেটার ভেতরে কী আছে তা বের করা ক্রমাগত দরকার পড়ে। Python-এ JWT ডিকোডার সেই অস্বচ্ছ base64 স্ট্রিংকে একটি পঠনযোগ্য ক্লেইম ডিকশনারিতে রূপান্তরিত করে যা দিয়ে আপনি কাজ করতে পারেন। PyPI প্যাকেজটি হলো PyJWT — ইনস্টল করতে হয় pip install PyJWT দিয়ে কিন্তু import করতে হয় import jwt হিসেবে। এই গাইডে সম্পূর্ণ সিগনেচার যাচাইসহ jwt.decode()-এর ব্যবহার, দ্রুত পরীক্ষার জন্য গোপন কী ছাড়া ডিকোডিং, কোনো লাইব্রেরি ছাড়া ম্যানুয়াল base64 ডিকোডিং, RS256 পাবলিক কী যাচাই এবং প্রোডাকশন auth সিস্টেমে যে সাধারণ সমস্যাগুলো দেখা যায় — সব কিছুই এখানে দেখাব। দ্রুত একক পরীক্ষার জন্য অনলাইন JWT Decoder কোনো কোড ছাড়াই তাৎক্ষণিকভাবে এটি করে। সব উদাহরণ Python 3.10+ এবং PyJWT 2.x-কে লক্ষ্য করে তৈরি।

  • pip install PyJWT করুন, তারপর import jwt — প্যাকেজের নাম এবং import নাম আলাদা, যা প্রায় সবাইকে বিভ্রান্ত করে।
  • jwt.decode(token, key, algorithms=["HS256"]) একটি সাধারণ dict রিটার্ন করে যেখানে ক্লেইম থাকে। সবসময় algorithms স্পষ্টভাবে পাস করুন।
  • যাচাই ছাড়া ক্লেইম দেখতে: jwt.decode(token, options={"verify_signature": False}, algorithms=["HS256"])।
  • RSA/EC টোকেনের জন্য: pip install PyJWT cryptography — অপ্রতিসম অ্যালগরিদমের জন্য cryptography ব্যাকএন্ড আবশ্যক।
  • ম্যানুয়াল ডিকোডিং (base64 + json) কোনো লাইব্রেরি ছাড়া কাজ করে কিন্তু সিগনেচার ও মেয়াদ যাচাই এড়িয়ে যায়।

JWT ডিকোডিং কী?

একটি JSON Web Token হলো ডট দিয়ে বিভক্ত তিনটি base64url-এনকোড করা অংশ: একটি হেডার (অ্যালগরিদম ও টোকেনের ধরন), একটি পেলোড (ক্লেইম — ব্যবহারকারীর ID, ভূমিকা, মেয়াদ শেষের সময়), এবং একটি সিগনেচার। JWT ডিকোড করা মানে হেডার ও পেলোড অংশ বের করা, সেগুলো base64url-ডিকোড করা, এবং ফলাফল JSON-কে ক্লেইমের ডিকশনারিতে পার্স করা।

হেডারে থাকে টোকেন সাইন করতে কোন অ্যালগরিদম ব্যবহার হয়েছে এবং কখনো কখনো kid (কী ID) যা সঠিক যাচাই কী খুঁজে পেতে সাহায্য করে। পেলোডে থাকে প্রকৃত তথ্য: টোকেন কাকে ইস্যু করা হয়েছে (sub), কখন মেয়াদ শেষ হবে (exp), কোন সার্ভিসের জন্য (aud), এবং আপনার অ্যাপ্লিকেশনের সংজ্ঞায়িত কাস্টম ক্লেইম। সিগনেচার অংশ প্রমাণ করে টোকেন পরিবর্তন করা হয়নি, কিন্তু যাচাই করতে গোপন কী বা পাবলিক কী লাগে। ডিকোডিং এবং যাচাই আলাদা কাজ। সিগনেচার যাচাই ছাড়াও পেলোড ডিকোড করা যায় (ডিবাগিংয়ে কাজে আসে), কিন্তু অথরাইজেশন সিদ্ধান্তে কখনো অযাচাই ক্লেইম বিশ্বাস করবেন না।

Before · json
After · json
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfOGYyYSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxMTgxNTYwMH0.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
{
  "sub": "usr_8f2a",
  "role": "admin",
  "exp": 1711815600
}

jwt.decode() — PyJWT দিয়ে ডিকোড ও যাচাই

jwt.decode() হলো PyJWT লাইব্রেরির প্রধান ফাংশন। এটি এনকোড করা টোকেন স্ট্রিং, গোপন কী (HMAC অ্যালগরিদমের জন্য) বা পাবলিক কী (RSA/EC-এর জন্য), এবং একটি আবশ্যিক algorithms তালিকা গ্রহণ করে। ফাংশনটি সিগনেচার যাচাই করে, exp nbf-এর মতো স্ট্যান্ডার্ড ক্লেইম পরীক্ষা করে, এবং পেলোড Python ডিকশনারি হিসেবে রিটার্ন করে। কিছু ব্যর্থ হলে — ভুল সিগনেচার, মেয়াদোত্তীর্ণ টোকেন, ভুল অ্যালগরিদম — নির্দিষ্ট একটি এক্সেপশন তোলে।

ন্যূনতম কার্যকর উদাহরণ

Python 3.10+
import jwt

# A shared secret between the issuer and this service
SECRET_KEY = "k8s-webhook-signing-secret-2026"

# Encode a token first (simulating what an auth server would issue)
token = jwt.encode(
    {"sub": "usr_8f2a", "role": "admin", "team": "platform"},
    SECRET_KEY,
    algorithm="HS256"
)
print(token)
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3Jf...

# Decode and verify the token
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
print(payload)
# {'sub': 'usr_8f2a', 'role': 'admin', 'team': 'platform'}
print(payload["role"])
# admin

algorithms প্যারামিটারটি একটি তালিকা, একক স্ট্রিং নয়, এবং PyJWT 2.x-এ এটি আবশ্যিক। এটি একটি নিরাপত্তা বৈশিষ্ট্য: এটি না থাকলে আক্রমণকারী হেডারে alg: none দিয়ে টোকেন তৈরি করে সম্পূর্ণ যাচাই এড়িয়ে যেতে পারে। আপনার অ্যাপ্লিকেশন ঠিক কোন অ্যালগরিদম গ্রহণ করে তা সবসময় নির্দিষ্ট করুন। শুধু HS256 টোকেন ইস্যু করলে তালিকা হওয়া উচিত ["HS256"] — না ["HS256", "RS256", "none"]। তালিকা সংকীর্ণ রাখলে আক্রমণের সুযোগ কমে।

প্রথমদিকে আমাকে যা বিভ্রান্ত করেছিল: PyJWT 2.x-এ jwt.encode() bytes-এর পরিবর্তে string রিটার্ন করতে পরিবর্তিত হয়েছে। পুরনো Stack Overflow উত্তরে এনকোড করা টোকেনে .decode("utf-8") কল দেখলে বুঝবেন সেটি PyJWT 1.x যুগের কোড এবং ভার্সন 2.x-এ AttributeError দেবে। টোকেন ইতিমধ্যেই একটি string — সরাসরি ব্যবহার করুন।

মেয়াদসহ সম্পূর্ণ রাউন্ড-ট্রিপ

Python 3.10+ — encode then decode with exp
import jwt
from datetime import datetime, timedelta, timezone

SECRET_KEY = "webhook-processor-secret"

# Create a token that expires in 1 hour
payload = {
    "sub": "svc_payment_processor",
    "iss": "auth.internal.example.com",
    "aud": "https://api.example.com",
    "exp": datetime.now(timezone.utc) + timedelta(hours=1),
    "permissions": ["orders:read", "refunds:create"],
}

token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")

# Later, when the token arrives in a request header:
try:
    decoded = jwt.decode(
        token,
        SECRET_KEY,
        algorithms=["HS256"],
        audience="https://api.example.com",
        issuer="auth.internal.example.com",
    )
    print(f"Service: {decoded['sub']}")
    print(f"Permissions: {decoded['permissions']}")
except jwt.ExpiredSignatureError:
    print("Token expired — request re-authentication")
except jwt.InvalidAudienceError:
    print("Token not intended for this API")
except jwt.InvalidIssuerError:
    print("Token issued by unknown authority")
দ্রষ্টব্য:PyJWT এনকোডিংয়ের সময় স্বয়ংক্রিয়ভাবে datetime অবজেক্টকে Unix টাইমস্ট্যাম্পে রূপান্তরিত করে। ডিকোডিংয়ের সময় exp, iat, এবং nbf ক্লেইম datetime অবজেক্ট হিসেবে নয়, integer হিসেবে আসে। সেগুলো নিজে রূপান্তরিত করতে হবে datetime.fromtimestamp(payload["exp"], tz=timezone.utc) দিয়ে।

সিগনেচার যাচাই ছাড়া JWT ডিকোড করা

কখনো কখনো টোকেন যাচাইয়ের আগেই ক্লেইম পড়া দরকার হয়। একটি সাধারণ পরিস্থিতি: টোকেন হেডারে একটি kid (কী ID) ফিল্ড আছে, এবং যাচাই করার আগে JWKS এন্ডপয়েন্ট থেকে সঠিক পাবলিক কী আনতে হবে। PyJWT এটি verify_signature: False অপশন দিয়ে সমর্থন করে। তবুও algorithms তালিকা পাস করতে হয়, কিন্তু key আর্গুমেন্ট উপেক্ষা করা হয়।

Python 3.10+ — unverified decode
import jwt

token = (
    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNpZy0xNzI2In0"
    ".eyJzdWIiOiJ1c3JfM2M3ZiIsInNjb3BlIjoicmVhZDpvcmRlcnMiLCJpc3MiOiJhdXRoLmV4YW1wbGUuY29tIn0"
    ".signature_placeholder"
)

# Step 1: Read claims without verification to get routing info
unverified = jwt.decode(
    token,
    options={"verify_signature": False},
    algorithms=["RS256"]
)
print(unverified)
# {'sub': 'usr_3c7f', 'scope': 'read:orders', 'iss': 'auth.example.com'}

# Step 2: Read the header to find which key to use
header = jwt.get_unverified_header(token)
print(header)
# {'alg': 'RS256', 'typ': 'JWT', 'kid': 'sig-1726'}
# Now use header['kid'] to fetch the correct public key from your JWKS endpoint
সতর্কতা:অযাচাই টোকেন বিশ্বাসযোগ্য নয়। শুধুমাত্র রাউটিং সিদ্ধান্তের জন্য এই প্যাটার্ন ব্যবহার করুন (কোন কী আনতে হবে, কোন tenant খুঁজতে হবে)। অযাচাই ক্লেইমের ভিত্তিতে কখনো অথরাইজেশন সিদ্ধান্ত নেবেন না। আক্রমণকারী পেলোডে যা খুশি তাই রাখতে পারে।

এখানে একটি সূক্ষ্ম পার্থক্য আছে। jwt.get_unverified_header() শুধু হেডার পড়ে — প্রথম অংশ। verify_signature: False সহ jwt.decode() কল পেলোড পড়ে (দ্বিতীয় অংশ)। এই দুটি মিলিয়ে কোনো কী ছাড়াই টোকেনের সব তথ্য বের করা যায়। সিগনেচার যাচাই বন্ধ থাকলেও PyJWT টোকেনের সঠিক কাঠামো পরীক্ষা করে (তিনটি ডট-বিভক্ত অংশ, বৈধ base64, বৈধ JSON)। টোকেনের কাঠামো ত্রুটিপূর্ণ হলে আপনি যে অপশনই পাস করুন, DecodeError তোলে।

jwt.decode() প্যারামিটার রেফারেন্স

সম্পূর্ণ সিগনেচার হলো jwt.decode(jwt, key, algorithms, options, audience, issuer, leeway, require) algorithms এর পরের সব প্যারামিটার keyword-only।

প্যারামিটার
টাইপ
ডিফল্ট
বিবরণ
jwt
str | bytes
(আবশ্যক)
ডিকোড করার জন্য এনকোড করা JWT স্ট্রিং
key
str | bytes | dict
(আবশ্যক)
যাচাইয়ের জন্য গোপন কী (HMAC) অথবা পাবলিক কী (RSA/EC)
algorithms
list[str]
(আবশ্যক)
অনুমোদিত অ্যালগরিদম — যেমন ["HS256"], ["RS256"]। কখনো বাদ দেবেন না।
options
dict
{}
যাচাই ফ্ল্যাগ পরিবর্তন করুন: verify_signature, verify_exp, verify_aud ইত্যাদি
audience
str | list[str]
None
প্রত্যাশিত aud ক্লেইম — অমিল হলে InvalidAudienceError তোলে
issuer
str
None
প্রত্যাশিত iss ক্লেইম — অমিল হলে InvalidIssuerError তোলে
leeway
timedelta | int
0
exp এবং nbf পরীক্ষায় ঘড়ির পার্থক্য সহনশীলতার সেকেন্ড
require
list[str]
[]
যে ক্লেইমগুলো থাকা আবশ্যক — না থাকলে MissingRequiredClaimError তোলে

options dict PyJWT কী কী যাচাই করবে তার উপর সূক্ষ্ম নিয়ন্ত্রণ দেয়। কীগুলো আলাদা পরীক্ষার সাথে সংযুক্ত: verify_signature, verify_exp, verify_nbf, verify_iss, verify_aud, এবং verify_iat। আপনি স্পষ্টভাবে False না করা পর্যন্ত সব ডিফল্টে True। প্রোডাকশনে সবকিছু ডিফল্টে রাখুন। ডেভেলপমেন্টে পুরনো পরীক্ষামূলক টোকেন নিয়ে কাজ করার সময় মেয়াদ সাময়িকভাবে এড়াতে আলাদা পরীক্ষা বন্ধ করা যায়।

Python 3.10+ — using options and require
import jwt

# Require specific claims to be present — raises MissingRequiredClaimError if absent
payload = jwt.decode(
    token,
    SECRET_KEY,
    algorithms=["HS256"],
    options={"require": ["exp", "iss", "sub"]},
    issuer="auth.internal.example.com",
)

# During development only: skip expiry to test with old tokens
dev_payload = jwt.decode(
    token,
    SECRET_KEY,
    algorithms=["HS256"],
    options={"verify_exp": False},  # DO NOT use in production
)

base64 এবং json দিয়ে ম্যানুয়াল JWT ডিকোডিং

Python স্ট্যান্ডার্ড লাইব্রেরি ছাড়া আর কিছু ব্যবহার না করেই JWT পেলোড ডিকোড করা যায় — কোনো pip install লাগে না। বেশ কিছু পরিস্থিতিতে এটি সত্যিই কাজে আসে: ডিবাগিং স্ক্রিপ্টে যেখানে নির্ভরতা যোগ করা অতিরিক্ত মনে হয়, সীমাবদ্ধ CI পরিবেশে যেখানে শুধু স্ট্যান্ডার্ড লাইব্রেরি পাওয়া যায়, AWS Lambda ফাংশনে যেখানে কোল্ড স্টার্ট সময় কমাতে চান, বা JWT আসলে কীভাবে কাজ করে তা বোঝার জন্য। প্রক্রিয়াটি সহজ: ডটে বিভক্ত করুন, কাঙ্ক্ষিত অংশ নিন, base64 প্যাডিং যোগ করুন, ডিকোড করুন, এবং JSON পার্স করুন।

base64 এবং json উভয় মডিউলই Python স্ট্যান্ডার্ড লাইব্রেরিতে আছে, তাই 3.6 থেকে যেকোনো Python ইনস্টলেশনে এটি কাজ করে। নিচের ফাংশনগুলো হেডার (প্রথম অংশ) এবং পেলোড (দ্বিতীয় অংশ) আলাদাভাবে সামলায়:

Python 3.10+ — manual JWT decode without any library
import base64
import json

def decode_jwt_payload(token: str) -> dict:
    """Decode the JWT payload without signature verification.
    Works with any JWT — HS256, RS256, ES256, etc.
    """
    parts = token.split(".")
    if len(parts) != 3:
        raise ValueError(f"Expected 3 JWT segments, got {len(parts)}")

    payload_b64 = parts[1]
    # base64url uses - and _ instead of + and /
    # Python's urlsafe_b64decode handles this, but needs padding
    payload_b64 += "=" * (-len(payload_b64) % 4)
    payload_bytes = base64.urlsafe_b64decode(payload_b64)
    return json.loads(payload_bytes)


def decode_jwt_header(token: str) -> dict:
    """Decode the JWT header (algorithm, key ID, type)."""
    header_b64 = token.split(".")[0]
    header_b64 += "=" * (-len(header_b64) % 4)
    return json.loads(base64.urlsafe_b64decode(header_b64))


# Example usage
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfOGYyYSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxMTgxNTYwMH0.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"

header = decode_jwt_header(token)
print(f"Algorithm: {header['alg']}")
# Algorithm: HS256

claims = decode_jwt_payload(token)
print(f"Subject: {claims['sub']}")
print(f"Role: {claims['role']}")
# Subject: usr_8f2a
# Role: admin

প্যাডিং কৌশলটি (+= "=" * (-len(s) % 4)) হলো সেই অংশ যা সবাই ভুলে যায়। JWT base64url শেষের = বাদ দেয়, কিন্তু Python-এর urlsafe_b64decode সেগুলো দরকার। প্যাডিং ঠিক না করলে binascii.Error: Incorrect padding পাবেন।

দ্রষ্টব্য:ম্যানুয়াল ডিকোডিং সিগনেচার যাচাই করে না। যে কেউ JWT-এর পেলোড পরিবর্তন করে পুনরায় এনকোড করতে পারে। এই পদ্ধতি শুধু পরীক্ষা ও ডিবাগিংয়ের জন্য ব্যবহার করুন, অথরাইজেশন লজিকে কখনো নয়। যা গুরুত্বপূর্ণ তার জন্য প্রকৃত কী দিয়ে jwt.decode() ব্যবহার করুন।

API রেসপন্স ও টোকেন ফাইল থেকে JWT ডিকোড করা

দুটি সবচেয়ে সাধারণ বাস্তব পরিস্থিতি: HTTP রেসপন্স থেকে JWT বের করা (OAuth টোকেন এন্ডপয়েন্ট, লগইন API) এবং ফাইল থেকে টোকেন পড়া (সার্ভিস অ্যাকাউন্ট ক্রেডেনশিয়াল, Kubernetes মাউন্টেড সিক্রেট, ডিস্কে ক্যাশ করা টোকেন)। উভয়েই যথাযথ ত্রুটি সামলানো দরকার। নেটওয়ার্ক অনুরোধ ব্যর্থ হয়। ফাইল হারিয়ে যায়। ক্যাশ থেকে পড়তে পড়তে টোকেনের মেয়াদ শেষ হয়ে যায়।

নিচের উদাহরণগুলো HTTP কলের জন্য httpx ব্যবহার করে (পছন্দ হলে requests দিয়ে পরিবর্তন করুন, প্যাটার্ন একই) এবং ফাইল অপারেশনের জন্য pathlib.Path। প্রতিটি উদাহরণ সাধারণ except Exception এর বদলে নির্দিষ্ট PyJWT এক্সেপশন ধরে, যাতে প্রতিটি ব্যর্থতার ক্ষেত্রে সঠিকভাবে সাড়া দেওয়া যায়: মেয়াদ শেষে পুনরায় অথেন্টিকেট করুন, সিগনেচার ব্যর্থতায় সতর্কতা পাঠান, নেটওয়ার্ক টাইমআউটে পুনরায় চেষ্টা করুন।

API রেসপন্স থেকে JWT ডিকোড করা

Python 3.10+ — decode JWT from OAuth token endpoint
import jwt
import httpx  # or requests

TOKEN_ENDPOINT = "https://auth.example.com/oauth/token"
SECRET_KEY = "shared-webhook-signing-key"

def get_and_decode_token() -> dict:
    """Fetch an access token from the auth server and decode it."""
    try:
        response = httpx.post(
            TOKEN_ENDPOINT,
            data={
                "grant_type": "client_credentials",
                "client_id": "svc_order_processor",
                "client_secret": "cs_9f3a7b2e",
            },
            timeout=10.0,
        )
        response.raise_for_status()
    except httpx.HTTPError as exc:
        raise RuntimeError(f"Token request failed: {exc}") from exc

    token_data = response.json()
    access_token = token_data["access_token"]

    try:
        payload = jwt.decode(
            access_token,
            SECRET_KEY,
            algorithms=["HS256"],
            audience="https://api.example.com",
        )
        return payload
    except jwt.InvalidTokenError as exc:
        raise RuntimeError(f"Invalid token from auth server: {exc}") from exc


claims = get_and_decode_token()
print(f"Service: {claims['sub']}, Scopes: {claims.get('scope', 'none')}")

ফাইল থেকে JWT ডিকোড করা

Python 3.10+ — read and decode a cached token file
import jwt
from pathlib import Path
from datetime import datetime, timezone

TOKEN_PATH = Path("/var/run/secrets/service-account-token")
PUBLIC_KEY_PATH = Path("/etc/ssl/auth/public_key.pem")

def decode_token_from_file() -> dict:
    """Read a JWT from a file, verify with a PEM public key."""
    try:
        token = TOKEN_PATH.read_text().strip()
        public_key = PUBLIC_KEY_PATH.read_text()
    except FileNotFoundError as exc:
        raise RuntimeError(f"Missing file: {exc.filename}") from exc

    try:
        payload = jwt.decode(
            token,
            public_key,
            algorithms=["RS256"],
            audience="https://internal-api.example.com",
        )
    except jwt.ExpiredSignatureError:
        exp_time = jwt.decode(
            token,
            options={"verify_signature": False},
            algorithms=["RS256"],
        ).get("exp", 0)
        expired_at = datetime.fromtimestamp(exp_time, tz=timezone.utc)
        raise RuntimeError(f"Token expired at {expired_at.isoformat()}")
    except jwt.InvalidTokenError as exc:
        raise RuntimeError(f"Token verification failed: {exc}") from exc

    return payload


claims = decode_token_from_file()
print(f"Subject: {claims['sub']}, Issuer: {claims['iss']}")

কমান্ড-লাইনে JWT ডিকোডিং

কখনো কখনো স্ক্রিপ্ট না লিখে টার্মিনাল থেকেই একটি টোকেন দেখা দরকার হয়। হয়তো OAuth ফ্লো ডিবাগ করছেন এবং Authorization হেডারে কী আছে তা দেখতে চান, বা ব্রাউজার DevTools থেকে একটি টোকেন নিয়ে এর মেয়াদ পরীক্ষা করতে চান। Python-এর -c ফ্ল্যাগ এটিকে এক লাইনে সম্ভব করে। টোকেন পাইপ করুন এবং ফরম্যাট করা JSON হিসেবে ক্লেইম পান। কোনো স্ক্রিপ্ট ফাইল লাগবে না, কোনো ভার্চুয়াল পরিবেশ লাগবে না।

Bash
# Decode JWT payload from clipboard or variable (no verification)
echo "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOGYyYSIsInJvbGUiOiJhZG1pbiJ9.sig" \
  | python3 -c "
import sys, base64, json
token = sys.stdin.read().strip()
payload = token.split('.')[1]
payload += '=' * (-len(payload) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))
"
# {
#   "sub": "usr_8f2a",
#   "role": "admin"
# }
Bash
# Decode JWT header to check algorithm and key ID
echo "eyJhbGciOiJSUzI1NiIsImtpZCI6InNpZy0xNzI2In0.payload.sig" \
  | python3 -c "
import sys, base64, json
token = sys.stdin.read().strip()
header = token.split('.')[0]
header += '=' * (-len(header) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(header)), indent=2))
"
# {
#   "alg": "RS256",
#   "kid": "sig-1726"
# }
Bash
# If PyJWT is installed, verify and decode in one step
python3 -c "
import jwt, sys, json
token = sys.argv[1]
payload = jwt.decode(token, options={'verify_signature': False}, algorithms=['HS256'])
print(json.dumps(payload, indent=2))
" "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOGYyYSJ9.sig"

টার্মিনাল সেটআপ ছাড়া ভিজ্যুয়াল বিকল্প হিসেবে আপনার টোকেন ToolDeck JWT Decoder-এ পেস্ট করুন এবং তাৎক্ষণিকভাবে হেডার, পেলোড ও সিগনেচার যাচাইয়ের স্থিতি দেখুন।

python-jose এবং অন্যান্য বিকল্প

python-jose একটি বিকল্প JWT লাইব্রেরি যা JWS, JWE (এনক্রিপ্টেড টোকেন) এবং JWK সরাসরি সমর্থন করে। আপনার অ্যাপ্লিকেশনে এনক্রিপ্টেড JWT (JWE) সামলাতে হলে — যেখানে পেলোড নিজেই এনক্রিপ্ট করা, শুধু সাইন করা নয় — python-jose সঠিক পছন্দ কারণ PyJWT মোটেই JWE সমর্থন করে না। এই লাইব্রেরিতে JWKS কী সেট হ্যান্ডলিং আছে, যা Auth0, Okta বা Keycloak-এর মতো আইডেন্টিটি প্রোভাইডারের সাথে ইন্টিগ্রেশন সহজ করে যারা রোটেটিং কী সেট প্রকাশ করে। ডিকোড ইন্টারফেস PyJWT-এর প্রায় একই, তাই এদের মধ্যে পরিবর্তন করতে কোড সামান্যই বদলাতে হয়:

Python 3.10+ — python-jose
# pip install python-jose[cryptography]
from jose import jwt as jose_jwt

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOGYyYSIsInNjb3BlIjoib3JkZXJzOnJlYWQifQ.signature"

# Verified decode — same pattern as PyJWT
payload = jose_jwt.decode(
    token,
    "signing-secret-key",
    algorithms=["HS256"],
    audience="https://api.example.com",
)
print(payload)
# {'sub': 'usr_8f2a', 'scope': 'orders:read'}

# Unverified decode
claims = jose_jwt.get_unverified_claims(token)
header = jose_jwt.get_unverified_header(token)
print(f"Algorithm: {header['alg']}, Subject: {claims['sub']}")

আমার পরামর্শ: PyJWT দিয়ে শুরু করুন। এটি JWT ব্যবহারের ৯৫% ক্ষেত্র কভার করে, সবচেয়ে বড় কমিউনিটি আছে, এবং API পরিষ্কার। JWE সমর্থন বা JWKS হ্যান্ডলিং পছন্দ হলে python-jose-এ যান। তৃতীয় একটি উল্লেখযোগ্য বিকল্প হলো Authlib, যা JWT হ্যান্ডলিং একটি বৃহত্তর OAuth/OIDC ফ্রেমওয়ার্কের মধ্যে দেয়। ইতিমধ্যে OAuth ক্লায়েন্ট ফ্লোর জন্য Authlib ব্যবহার করলে এর authlib.jose.jwt মডিউল আলাদা JWT নির্ভরতা যোগ করা এড়িয়ে দেয়। অন্যথায়, শুধু টোকেন ডিকোডিংয়ের জন্য এটি একটি ভারী নির্ভরতা।

সিনট্যাক্স হাইলাইটিং সহ টার্মিনাল আউটপুট

টার্মিনালে raw JWT ক্লেইম পড়া দ্রুত পরীক্ষার জন্য ঠিক আছে, কিন্তু নিয়মিত টোকেন পেলোড ডিবাগ করার সময় (একটি অভ্যন্তরীণ auth গেটওয়ে তৈরির সময় আমি প্রতিদিন এটি করতাম) রঙিন আউটপুট উল্লেখযোগ্য পার্থক্য আনে। স্ট্রিং মান, সংখ্যা, বুলিয়ান এবং null আলাদা রঙে দেখায়, ফলে প্রতিটি অক্ষর না পড়েই একটি অনুপস্থিত অনুমতি বা ভুল মেয়াদ টাইমস্ট্যাম্প একনজরে ধরতে পারেন।

rich লাইব্রেরি (pip install rich) এ একটি print_json ফাংশন আছে যা JSON স্ট্রিং বা Python dict নিয়ে টার্মিনালে সম্পূর্ণ সিনট্যাক্স হাইলাইটিং সহ প্রিন্ট করে। PyJWT-এর সাথে মিলিয়ে দুই লাইনে JWT পরীক্ষার কর্মপ্রবাহ তৈরি করা যায়:

Python 3.10+ — rich terminal output
# pip install rich PyJWT
import jwt
from rich import print_json

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOGYyYSIsInJvbGUiOiJhZG1pbiIsInBlcm1pc3Npb25zIjpbIm9yZGVyczpyZWFkIiwicmVmdW5kczpjcmVhdGUiXSwiZXhwIjoxNzExODE1NjAwfQ.sig"

payload = jwt.decode(
    token,
    options={"verify_signature": False},
    algorithms=["HS256"]
)

# Colorized, indented JSON output in the terminal
print_json(data=payload)
# {
#   "sub": "usr_8f2a",           ← strings in green
#   "role": "admin",
#   "permissions": [
#     "orders:read",
#     "refunds:create"
#   ],
#   "exp": 1711815600            ← numbers in cyan
# }
দ্রষ্টব্য:rich আউটপুটে ANSI এস্কেপ কোড থাকে। ফাইলে লেখা বা API এন্ডপয়েন্ট থেকে রিটার্ন করবেন না — এটি শুধু টার্মিনাল প্রদর্শনের জন্য। সাধারণ টেক্সট আউটপুট দরকার হলে json.dumps() ব্যবহার করুন।

বড় টোকেন ব্যাচ নিয়ে কাজ

JWT টোকেন নিজে ছোট (সাধারণত ২ KB-এর কম), কিন্তু এমন পরিস্থিতি আসে যেখানে বাল্কে প্রক্রিয়া করতে হয়। নিরাপত্তা ঘটনার পর অডিট লগ বিশ্লেষণ। auth প্রোভাইডার পরিবর্তনের সময় সেশন মাইগ্রেশন স্ক্রিপ্ট। কমপ্লায়েন্স ব্যাচ যাচাইয়ে যেখানে প্রমাণ করতে হয় গত ৯০ দিনে ইস্যু করা প্রতিটি টোকেন সঠিক কী দিয়ে সাইন হয়েছে। NDJSON লগ ফাইলে দশ হাজার টোকেন থাকলে, লাইন-বাই-লাইন প্রক্রিয়া করলে পুরো ফাইল মেমোরিতে লোড করা এড়ানো যায় এবং ক্রমান্বয়ে ফলাফল জানানো যায়।

অডিট লগ থেকে ব্যাচে টোকেন যাচাই

Python 3.10+ — streaming token validation
import jwt
import json
from pathlib import Path

SECRET_KEY = "audit-log-signing-key"

def validate_token_log(log_path: str) -> dict:
    """Process an NDJSON file where each line has a 'token' field.
    Returns counts of valid, expired, and invalid tokens.
    """
    stats = {"valid": 0, "expired": 0, "invalid": 0}

    with open(log_path) as fh:
        for line_num, line in enumerate(fh, 1):
            line = line.strip()
            if not line:
                continue

            try:
                record = json.loads(line)
                token = record["token"]
            except (json.JSONDecodeError, KeyError):
                stats["invalid"] += 1
                continue

            try:
                jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
                stats["valid"] += 1
            except jwt.ExpiredSignatureError:
                stats["expired"] += 1
            except jwt.InvalidTokenError:
                stats["invalid"] += 1

    return stats


result = validate_token_log("auth-events-2026-03.ndjson")
print(f"Valid: {result['valid']}, Expired: {result['expired']}, Invalid: {result['invalid']}")
# Valid: 14832, Expired: 291, Invalid: 17

NDJSON টোকেন এক্সপোর্ট থেকে ক্লেইম বের করা

Python 3.10+ — extract and transform claims from token log
import base64
import json
from datetime import datetime, timezone

def extract_claims_stream(input_path: str, output_path: str):
    """Read tokens line by line, decode payloads, write flattened claims."""
    with open(input_path) as infile, open(output_path, "w") as outfile:
        for line in infile:
            line = line.strip()
            if not line:
                continue

            record = json.loads(line)
            token = record.get("access_token", "")
            parts = token.split(".")
            if len(parts) != 3:
                continue

            payload_b64 = parts[1] + "=" * (-len(parts[1]) % 4)
            claims = json.loads(base64.urlsafe_b64decode(payload_b64))

            # Flatten into an audit-friendly record
            flat = {
                "timestamp": record.get("timestamp"),
                "subject": claims.get("sub"),
                "issuer": claims.get("iss"),
                "expired_at": datetime.fromtimestamp(
                    claims.get("exp", 0), tz=timezone.utc
                ).isoformat(),
            }
            outfile.write(json.dumps(flat) + "\n")

extract_claims_stream("token-audit.ndjson", "claims-extract.ndjson")
দ্রষ্টব্য:কয়েকশো MB-এর নিচের ফাইলে লাইন-বাই-লাইন পড়া যথেষ্ট দক্ষ। খুব বড় টোকেন ডাম্পে পারফরম্যান্স সীমায় পৌঁছালে multiprocessing.Pool ব্যবহার করে একাধিক কোরে যাচাই বিতরণ করুন, কারণ প্রতিটি টোকেন স্বাধীন।

সাধারণ ভুল

এই চারটি ভুল কোড রিভিউ এবং Stack Overflow প্রশ্নে বারবার দেখা যায়। করাও সহজ, এবং PyJWT যে ত্রুটি বার্তা দেয় তা সবসময় সরাসরি কারণ বলে না। বিশেষত প্যাকেজ নামের গোলমালটা — ভুল লাইব্রেরি ইনস্টল হয়ে গেলে ঘণ্টার পর ঘণ্টা মাথা ঘামিয়েও বুঝতে পারবেন না আসল সমস্যাটা কোথায়।

PyJWT ও python-jwt প্যাকেজের নাম গুলিয়ে ফেলা

সমস্যা: pip install jwt বা pip install python-jwt চালালে সম্পূর্ণ ভিন্ন প্যাকেজ ইনস্টল হয়। তারপর import jwt ব্যর্থ হয় বা অপরিচিত API দেয়।

সমাধান: সবসময় pip install PyJWT দিয়ে ইনস্টল করুন। import হলো import jwt। সঠিক প্যাকেজ নিশ্চিত করতে pip show PyJWT দিয়ে যাচাই করুন।

Before · Python
After · Python
pip install jwt
# or
pip install python-jwt

import jwt  # wrong package — different API entirely
pip install PyJWT

import jwt  # correct — this is PyJWT
print(jwt.__version__)  # 2.x
algorithms প্যারামিটার বাদ দেওয়া

সমস্যা: PyJWT 1.x-এ algorithms ঐচ্ছিক ছিল এবং ডিফল্টে যেকোনো অ্যালগরিদম অনুমতি দিত। এটি একটি নিরাপত্তা দুর্বলতা তৈরি করত যেখানে আক্রমণকারী alg: none সেট করতে পারত। PyJWT 2.x-এ algorithms না থাকলে DecodeError তোলে।

সমাধান: সবসময় algorithms একটি স্পষ্ট তালিকা হিসেবে পাস করুন। শুধুমাত্র আপনার অ্যাপ্লিকেশন যে অ্যালগরিদম দিয়ে টোকেন ইস্যু করে তা ব্যবহার করুন।

Before · Python
After · Python
# PyJWT 2.x — this raises DecodeError
payload = jwt.decode(token, SECRET_KEY)
# DecodeError: algorithms must be specified
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
RS256-এর জন্য jwt.decode()-এ ভুল কী টাইপ ব্যবহার

সমস্যা: algorithms=["RS256"] সহ jwt.decode()-এ string secret পাস করলে InvalidSignatureError তোলে। RS256-এর জন্য PEM-এনকোড করা পাবলিক কী লাগে, shared secret string নয়।

সমাধান: ফাইল বা পরিবেশ ভেরিয়েবল থেকে PEM পাবলিক কী লোড করুন। cryptography প্যাকেজ ইনস্টল করুন: pip install PyJWT cryptography।

Before · Python
After · Python
# This fails — RS256 needs a public key, not a string secret
payload = jwt.decode(token, "my-secret", algorithms=["RS256"])
# InvalidSignatureError
public_key = open("public_key.pem").read()
payload = jwt.decode(token, public_key, algorithms=["RS256"])
ম্যানুয়াল ডিকোডিংয়ে base64 প্যাডিং ভুলে যাওয়া

সমস্যা: JWT base64url এনকোডিং শেষের = বাদ দেয়। Python-এর base64.urlsafe_b64decode প্যাডিং ছাড়া raw অংশ পাস করলে binascii.Error: Incorrect padding তোলে।

সমাধান: ডিকোডের আগে প্যাডিং যোগ করুন: segment += '=' * (-len(segment) % 4)। এই সূত্র সবসময় সঠিক সংখ্যক প্যাডিং অক্ষর দেয় (০, ১, ২, বা ৩)।

Before · Python
After · Python
import base64
payload_b64 = token.split(".")[1]
data = base64.urlsafe_b64decode(payload_b64)
# binascii.Error: Incorrect padding
import base64
payload_b64 = token.split(".")[1]
payload_b64 += "=" * (-len(payload_b64) % 4)
data = base64.urlsafe_b64decode(payload_b64)  # works

PyJWT বনাম বিকল্প — দ্রুত তুলনা

পদ্ধতি
সিগনেচার যাচাই
ক্লেইম যাচাই
কাস্টম টাইপ
ইনস্টল প্রয়োজন
PyJWT jwt.decode()
✓ (exp, aud, iss, nbf)
প্রযোজ্য নয় (dict রিটার্ন করে)
pip install PyJWT
PyJWT unverified decode
প্রযোজ্য নয়
pip install PyJWT
ম্যানুয়াল base64 ডিকোড
প্রযোজ্য নয়
না (stdlib)
python-jose jwt.decode()
প্রযোজ্য নয়
pip install python-jose
Authlib jwt.decode()
প্রযোজ্য নয়
pip install Authlib
PyJWT + cryptography
✓ (RSA/EC)
প্রযোজ্য নয়
pip install PyJWT cryptography

বেশিরভাগ Python অ্যাপ্লিকেশনের জন্য PyJWT শুরু করার সঠিক পছন্দ। এটি HMAC এবং (cryptography ব্যাকএন্ডসহ) RSA ও EC সিগনেচার যাচাই কভার করে। JWE (এনক্রিপ্টেড টোকেন) দরকার হলে python-jose বা Authlib-এ যান। ম্যানুয়াল base64 ডিকোডিং ডিবাগিংয়ে কাজ করে কিন্তু কোনো নিরাপত্তা নিশ্চয়তা দেয় না।

আমি কখন কোনটি বেছে নিই: স্ট্যান্ডার্ড ওয়েব সার্ভিসে HS256 বা RS256 যাচাইয়ের জন্য PyJWT। আর্কিটেকচারে এনক্রিপ্টেড টোকেন বা JWKS রোটেশন থাকলে python-jose। pip পাওয়া যায় না এমন পরিবেশে দ্রুত পরীক্ষার জন্য ম্যানুয়াল base64 (CI কন্টেইনার, সীমাবদ্ধ প্রোডাকশন হোস্ট, নির্ভরতা কমাতে চাওয়া AWS Lambda)। প্রকল্পে ইতিমধ্যে OAuth ক্লায়েন্ট ফ্লোর জন্য Authlib ব্যবহার হলে এবং আলাদা JWT লাইব্রেরি অতিরিক্ত হলে Authlib।

কোড-মুক্ত বিকল্পের জন্য যেকোনো টোকেন JWT Decoder-এ পেস্ট করুন এবং ক্লেইম যাচাইয়ের ফিডব্যাকসহ ডিকোড করা হেডার ও পেলোড দেখুন।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

Python-এ সিগনেচার যাচাই ছাড়া JWT কীভাবে ডিকোড করব?

jwt.decode()-এ options={"verify_signature": False} এবং algorithms=["HS256"] পাস করুন। এটি সিগনেচার পরীক্ষা না করেই পেলোড dict রিটার্ন করে। এটি শুধুমাত্র পরীক্ষা-নিরীক্ষার জন্য ব্যবহার করুন — সঠিক পাবলিক কী আনার আগে ক্লেইম পড়া, বা ডেভেলপমেন্টে ডিবাগিং করার সময়। যে টোকেন কোনো কিছুর অ্যাক্সেস নিয়ন্ত্রণ করে, তার যাচাই কখনো এড়িয়ে যাবেন না।

Python
import jwt

token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfOGYyYSIsInJvbGUiOiJhZG1pbiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

payload = jwt.decode(
    token,
    options={"verify_signature": False},
    algorithms=["HS256"]
)
print(payload)
# {'sub': 'usr_8f2a', 'role': 'admin'}

PyJWT এবং python-jwt-এর মধ্যে পার্থক্য কী?

PyJWT (pip install PyJWT, import jwt) হলো Python-এর সবচেয়ে জনপ্রিয় JWT লাইব্রেরি, প্রতি মাসে ৮ কোটিরও বেশি ডাউনলোড সহ। python-jwt (pip install python_jwt) একটি আলাদা, অনেক কম ব্যবহৃত লাইব্রেরি যার API ভিন্ন। কারো কোডে import jwt দেখলে বুঝবেন তারা PyJWT ব্যবহার করছেন। এই বিভ্রান্তি তৈরি হয় কারণ PyPI প্যাকেজের নাম (PyJWT) এবং import নাম (jwt) আলাদা। বিশেষ কোনো কারণ না থাকলে PyJWT-ই ব্যবহার করুন।

Python-এ RS256 দিয়ে JWT কীভাবে ডিকোড করব?

PyJWT এবং cryptography ব্যাকএন্ড উভয়ই ইনস্টল করুন: pip install PyJWT cryptography। তারপর PEM-এনকোড করা পাবলিক কী key আর্গুমেন্ট হিসেবে এবং algorithms=["RS256"] পাস করুন। PyJWT RSA সিগনেচার যাচাইয়ের কাজ cryptography লাইব্রেরিতে দেয়। cryptography প্যাকেজ ইনস্টল না থাকলে RSA বা EC অ্যালগরিদম ব্যবহার করতে গেলে PyJWT ত্রুটি দেয়।

Python
import jwt

public_key = open("public_key.pem").read()

payload = jwt.decode(
    token,
    public_key,
    algorithms=["RS256"],
    audience="https://api.example.com"
)

PyJWT কেন ExpiredSignatureError তোলে?

PyJWT ডিফল্টভাবে exp (মেয়াদ শেষের সময়) ক্লেইম পরীক্ষা করে। বর্তমান UTC সময় exp টাইমস্ট্যাম্পের পরে হলে jwt.ExpiredSignatureError তোলে। leeway প্যারামিটার দিয়ে ঘড়ির পার্থক্য সহনশীলতা যোগ করতে পারেন: jwt.decode(token, key, algorithms=["HS256"], leeway=timedelta(seconds=30))। এতে ৩০ সেকেন্ডের অতিরিক্ত সুযোগ পাওয়া যায়। মেয়াদ যাচাই সম্পূর্ণ বন্ধ করতে (প্রোডাকশনে সুপারিশযোগ্য নয়) options={"verify_exp": False} পাস করুন।

Python
import jwt
from datetime import timedelta

try:
    payload = jwt.decode(token, secret, algorithms=["HS256"], leeway=timedelta(seconds=30))
except jwt.ExpiredSignatureError:
    print("Token has expired — prompt re-authentication")

Python-এ কোনো লাইব্রেরি ছাড়া JWT ক্লেইম পড়া কি সম্ভব?

হ্যাঁ। টোকেনটি ডটে বিভক্ত করুন, দ্বিতীয় অংশ (পেলোড) নিন, দৈর্ঘ্য ৪-এর গুণিতক করতে = দিয়ে প্যাডিং যোগ করুন, তারপর base64url-ডিকোড করে JSON পার্স করুন। এটি ক্লেইম dict দেয় কিন্তু সিগনেচার যাচাই করে না। PyJWT ইনস্টল করা সম্ভব না এমন সীমাবদ্ধ পরিবেশে বা দ্রুত ডিবাগিং স্ক্রিপ্টে এটি উপযোগী।

Python
import base64, json

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3JfOGYyYSJ9.signature"
payload_b64 = token.split(".")[1]
payload_b64 += "=" * (-len(payload_b64) % 4)  # fix padding
claims = json.loads(base64.urlsafe_b64decode(payload_b64))
print(claims)  # {'sub': 'usr_8f2a'}

PyJWT দিয়ে audience ক্লেইম কীভাবে যাচাই করব?

jwt.decode()-এ audience প্যারামিটার পাস করুন: jwt.decode(token, key, algorithms=["HS256"], audience="https://api.example.com")। PyJWT টোকেনের aud ক্লেইমের সাথে আপনার দেওয়া মান তুলনা করে। টোকেনে aud ক্লেইম না থাকলে বা মান না মিললে jwt.InvalidAudienceError তোলে। আপনার সার্ভিস একাধিক API-এর টোকেন গ্রহণ করলে গ্রহণযোগ্য audience-এর তালিকাও পাস করতে পারেন।

Python
import jwt

payload = jwt.decode(
    token,
    secret,
    algorithms=["HS256"],
    audience=["https://api.example.com", "https://admin.example.com"]
)

সম্পর্কিত টুল

DV
Dmitri VolkovDevOps Engineer & Python Automation Specialist

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.

MS
Maria Santosপ্রযুক্তিগত পর্যালোচক

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.