JWT Decoder Python — Dekódování JWT s PyJWT

·DevOps Engineer & Python Automation Specialist·ZkontrolovánoMaria Santos·Publikováno

Používejte bezplatný JWT Decoder přímo v prohlížeči — bez instalace.

Vyzkoušet JWT Decoder online →

Každé API využívající autentizaci na základě tokenů vám v určitém okamžiku předá JWT a zjistit, co se v něm skrývá, je úkol, který při vývoji narazíte neustále. JWT dekodér v Pythonu vezme ten neprůhledný base64 řetězec a převede ho na čitelný slovník claims, se kterým pak skutečně pracujete. Balíček na PyPI, který hledáte, je PyJWT — nainstalujete ho pomocí pip install PyJWT, ale importujete jako import jwt. Tento průvodce probírá jwt.decode() s úplným ověřením podpisu, dekódování bez tajného klíče pro rychlou inspekci, ruční dekódování base64 bez jakékoliv knihovny, ověření veřejného klíče RS256 a časté chyby, na které jsem narazil v produkčních auth systémech. Pro rychlé jednorázové ověření provede online JWT Decoder vše okamžitě bez jediného řádku kódu. Všechny příklady cílí na Python 3.10+ a PyJWT 2.x.

  • pip install PyJWT, pak import jwt — název balíčku a název importu se liší, na což skoro každý narazí.
  • jwt.decode(token, key, algorithms=["HS256"]) vrátí prostý slovník s claims. Vždy explicitně předávejte algorithms.
  • Pro inspekci claims bez ověření: jwt.decode(token, options={"verify_signature": False}, algorithms=["HS256"]).
  • Pro RSA/EC tokeny: pip install PyJWT cryptography — backend cryptography je pro asymetrické algoritmy povinný.
  • Ruční dekódování (base64 + json) funguje bez jakékoliv knihovny, ale přeskakuje veškeré ověřování podpisu a vypršení platnosti.

Co je dekódování JWT?

JSON Web Token se skládá ze tří base64url-zakódovaných segmentů oddělených tečkami: hlavičky (algoritmus a typ tokenu), payload (claims — ID uživatele, role, čas vypršení platnosti) a podpisu. Dekódovat JWT znamená extrahovat segmenty hlavičky a payload, base64url-dekódovat je a naparsovat výsledný JSON na slovník claims.

Hlavička říká, který algoritmus byl použit k podpisu tokenu, a někdy obsahuje kid (ID klíče) pro nalezení správného ověřovacího klíče. Payload obsahuje skutečná data: komu byl token vydán (sub), kdy vyprší (exp), pro kterou službu je určen (aud), plus libovolné vlastní claims vaší aplikace. Segment podpisu dokazuje, že token nebyl pozměněn, ale k jeho ověření potřebujete tajný klíč nebo veřejný klíč. Dekódování a ověřování jsou oddělené operace. Payload lze dekódovat bez ověření podpisu (užitečné pro ladění), ale nikdy nedůvěřujte neověřeným claims při rozhodování o autorizaci.

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

jwt.decode() — Dekódování a ověření pomocí PyJWT

jwt.decode() je hlavní funkce z knihovny PyJWT. Přijímá zakódovaný řetězec tokenu, tajný klíč (pro HMAC algoritmy) nebo veřejný klíč (pro RSA/EC) a povinný seznam algorithms. Funkce ověří podpis, zkontroluje standardní claims jako exp a nbfa vrátí payload jako Pythoní slovník. Pokud cokoliv selže — neplatný podpis, vypršelý token, nesprávný algoritmus — vyvolá specifickou výjimku.

Minimální funkční příklad

Python 3.10+
import jwt

# Sdílené tajemství mezi vydavatelem a touto službou
SECRET_KEY = "k8s-webhook-signing-secret-2026"

# Zakódování tokenu (simulace toho, co vydá auth server)
token = jwt.encode(
    {"sub": "usr_8f2a", "role": "admin", "team": "platform"},
    SECRET_KEY,
    algorithm="HS256"
)
print(token)
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3Jf...

# Dekódování a ověření tokenu
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
print(payload)
# {'sub': 'usr_8f2a', 'role': 'admin', 'team': 'platform'}
print(payload["role"])
# admin

Parametr algorithms je seznam, nikoliv jediný řetězec, a v PyJWT 2.x je povinný. Jde o bezpečnostní opatření: bez něj by útočník mohl vytvořit token s alg: none v hlavičce a zcela obejít ověření. Vždy přesně specifikujte, které algoritmy vaše aplikace přijímá. Pokud vydáváte pouze HS256 tokeny, seznam by měl být ["HS256"] — ne ["HS256", "RS256", "none"]. Udržování seznamu úzkého zmenšuje plochu pro útok.

Jedna věc, která mě na začátku zmátla: PyJWT 2.x změnil jwt.encode() tak, aby vracel řetězec místo bytů. Pokud čtete staré odpovědi na Stack Overflow, které volají .decode("utf-8") na zakódovaném tokenu, tento kód pochází z éry PyJWT 1.x a na verzi 2.x vyvolá AttributeError. Token je již řetězec — používejte ho přímo.

Úplný cyklus s vypršením platnosti

Python 3.10+ — zakódování pak dekódování s exp
import jwt
from datetime import datetime, timedelta, timezone

SECRET_KEY = "webhook-processor-secret"

# Vytvoření tokenu s platností 1 hodinu
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")

# Když token přijde v hlavičce požadavku:
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")
Poznámka:PyJWT převádí objekty datetime na Unix timestampy automaticky při zakódování. Při dekódování přicházejí claims exp, iat a nbf jako celá čísla, nikoliv jako objekty datetime. Převod je třeba provést ručně pomocí datetime.fromtimestamp(payload["exp"], tz=timezone.utc).

Dekódování JWT bez ověření podpisu

Někdy potřebujete přečíst claims před tím, než lze token ověřit. Typický scénář: hlavička tokenu obsahuje pole kid (ID klíče) a před ověřením je nutné načíst odpovídající veřejný klíč z JWKS endpointu. PyJWT to podporuje pomocí volby verify_signature: False. Seznam algorithms stále předáváte, ale argument key je ignorován.

Python 3.10+ — dekódování bez ověření
import jwt

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

# Krok 1: Čtení claims bez ověření pro získání informací o směrování
unverified = jwt.decode(
    token,
    options={"verify_signature": False},
    algorithms=["RS256"]
)
print(unverified)
# {'sub': 'usr_3c7f', 'scope': 'read:orders', 'iss': 'auth.example.com'}

# Krok 2: Čtení hlavičky pro zjištění, který klíč použít
header = jwt.get_unverified_header(token)
print(header)
# {'alg': 'RS256', 'typ': 'JWT', 'kid': 'sig-1726'}
# Nyní použijte header['kid'] k načtení správného veřejného klíče z JWKS endpointu
Varování:Neověřené tokeny nejsou důvěryhodné. Tento vzor používejte pouze pro rozhodnutí o směrování (který klíč načíst, jakého tenanta vyhledat). Nikdy nečiňte rozhodnutí o autorizaci na základě neověřených claims. Útočník může do payload vložit cokoliv.

Je zde jemný rozdíl. jwt.get_unverified_header() čte pouze hlavičku — první segment. Volání jwt.decode() s verify_signature: False čte payload (druhý segment). Dohromady lze z tokenu bez klíče extrahovat vše. PyJWT stále ověřuje, že token má správnou strukturu (tři segmenty oddělené tečkami, platný base64, platný JSON) i při vypnutém ověřování podpisu. Pokud je token strukturálně poškozený, vyvolá DecodeError bez ohledu na předané volby.

Referenční přehled parametrů jwt.decode()

Úplná signatura je jwt.decode(jwt, key, algorithms, options, audience, issuer, leeway, require). Všechny parametry za algorithms jsou pouze klíčové argumenty (keyword-only).

Parametr
Typ
Výchozí
Popis
jwt
str | bytes
(povinný)
Zakódovaný JWT řetězec ke dekódování
key
str | bytes | dict
(povinný)
Tajný klíč (HMAC) nebo veřejný klíč (RSA/EC) pro ověření
algorithms
list[str]
(povinný)
Povolené algoritmy — např. ["HS256"], ["RS256"]. Nikdy nevynechávejte.
options
dict
{}
Přepínače ověření: verify_signature, verify_exp, verify_aud atd.
audience
str | list[str]
None
Očekávaná hodnota aud — vyvolá InvalidAudienceError při neshodě
issuer
str
None
Očekávaná hodnota iss — vyvolá InvalidIssuerError při neshodě
leeway
timedelta | int
0
Tolerance posunu hodin v sekundách pro kontroly exp a nbf
require
list[str]
[]
Povinné claims — vyvolá MissingRequiredClaimError při jejich absenci

Slovník options poskytuje detailní kontrolu nad tím, která ověření PyJWT provádí. Klíče odpovídají jednotlivým kontrolám: verify_signature, verify_exp, verify_nbf, verify_iss, verify_aud a verify_iat. Všechny jsou ve výchozím nastavení True, pokud je explicitně nenastavíte na False. V produkci nechte všechny na výchozích hodnotách. Jednotlivé kontroly vypínám pouze při vývoji, kdy pracuji se zastaralými testovacími tokeny a potřebuji dočasně obejít kontrolu vypršení platnosti.

Python 3.10+ — použití options a require
import jwt

# Vyžadování přítomnosti konkrétních claims — vyvolá MissingRequiredClaimError při jejich absenci
payload = jwt.decode(
    token,
    SECRET_KEY,
    algorithms=["HS256"],
    options={"require": ["exp", "iss", "sub"]},
    issuer="auth.internal.example.com",
)

# Pouze při vývoji: přeskočení vypršení platnosti pro testování se starými tokeny
dev_payload = jwt.decode(
    token,
    SECRET_KEY,
    algorithms=["HS256"],
    options={"verify_exp": False},  # DO NOT use in production
)

Ruční dekódování JWT pomocí base64 a json

JWT payload lze dekódovat pouze pomocí standardní knihovny Pythonu — bez pip install. To se hodí v několika situacích: ladicí skripty, kde přidání závislosti není na místě, omezená CI prostředí, kde je dostupná pouze standardní knihovna, funkce AWS Lambda, kde chcete minimalizovat čas studeného startu, nebo jednoduše pochopení toho, co JWT skutečně je pod kapotou. Postup je přímočarý: rozdělte podle teček, vezměte požadovaný segment, doplňte base64 padding, dekódujte a naparsujte JSON.

Moduly base64 a json jsou součástí standardní knihovny Pythonu, takže tento přístup funguje na jakékoliv instalaci Pythonu od verze 3.6. Níže uvedené funkce zpracovávají hlavičku (první segment) i payload (druhý segment) samostatně:

Python 3.10+ — ruční dekódování JWT bez knihovny
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

Trik s paddingem (+= "=" * (-len(s) % 4)) je část, na kterou každý zapomíná. JWT base64url vynechává koncové znaky =, ale Pythoní urlsafe_b64decode je vyžaduje. Bez opravy paddingu dostanete binascii.Error: Incorrect padding.

Poznámka:Ruční dekódování neověřuje podpis. Kdokoliv může změnit payload JWT a znovu ho zakódovat. Tento přístup používejte pouze pro inspekci a ladění, nikdy pro autorizační logiku. Pro vše, na čem záleží, používejte jwt.decode() s reálným klíčem.

Dekódování JWT z API odpovědí a souborů tokenů

Dva nejčastější scénáře v praxi: extrakce JWT z HTTP odpovědi (OAuth token endpoint, přihlašovací API) a čtení tokenů ze souborů (přihlašovací údaje servisního účtu, Kubernetes mounted secrets, tokeny uložené v cache na disku). Obojí vyžaduje správné ošetření chyb. Síťové požadavky selhávají. Soubory mohou chybět. Tokeny vyprší mezi jejich uložením do cache a jejich přečtením.

Níže uvedené příklady používají httpx pro HTTP volání (zaměňte za requests pokud preferujete, vzor je totožný) a pathlib.Path pro operace se soubory. Každý příklad zachytává specifické výjimky PyJWT místo obecného except Exception, takže na každý typ selhání lze reagovat přiměřeně: znovu se přihlásit při vypršení, upozornit při selhání podpisu, opakovat při vypršení síťového limitu.

Dekódování JWT z API odpovědi

Python 3.10+ — dekódování JWT z OAuth token endpointu
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')}")

Dekódování JWT ze souboru

Python 3.10+ — čtení a dekódování souboru s tokenem v cache
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']}")

Dekódování JWT z příkazové řádky

Někdy potřebujete jen nahlédnout do tokenu v terminálu bez psaní skriptu. Možná ladíte OAuth tok a chcete vidět, co je v hlavičce Authorization, nebo jste zachytili token v DevTools prohlížeče a chcete zkontrolovat jeho vypršení platnosti. Příznak -c v Pythonu z toho udělá jednořádkovou záležitost. Přesměrujte token a získejte claims jako naformátovaný JSON. Žádný soubor skriptu, žádné virtuální prostředí.

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"

Pro vizuální alternativu bez nastavování terminálu vložte svůj token do nástroje ToolDeck JWT Decoder a okamžitě uvidíte hlavičku, payload a stav ověření podpisu.

python-jose a ostatní alternativy

python-jose je alternativní JWT knihovna s nativní podporou JWS, JWE (šifrované tokeny) a JWK. Pokud vaše aplikace potřebuje pracovat se šifrovanými JWT (JWE) — kde je samotný payload zašifrován, nejen podepsán — python-jose je správná volba, protože PyJWT JWE vůbec nepodporuje. Knihovna má také vestavěnou podporu sady klíčů JWKS, což zjednodušuje integraci s poskytovateli identity jako Auth0, Okta nebo Keycloak, kteří zpřístupňují rotující sady klíčů. Rozhraní pro dekódování je téměř totožné s PyJWT, takže přechod mezi nimi vyžaduje minimální změny kódu:

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']}")

Moje doporučení: začněte s PyJWT. Pokrývá 95 % případů použití JWT, má největší komunitu a jeho API je přehledné. Přejděte na python-jose, pokud potřebujete podporu JWE nebo preferujete jeho práci s JWKS. Třetí možností, která stojí za zmínku, je Authlib, který zahrnuje zpracování JWT jako součást většího OAuth/OIDC frameworku. Pokud již Authlib pro OAuth klientské toky používáte, jeho modul authlib.jose.jwt vás ušetří přidávání druhé JWT závislosti. Jinak jde o těžkou závislost jen kvůli dekódování tokenů.

Výstup terminálu se zvýrazněním syntaxe

Čtení JWT claims v terminálu bez formátování je v pořádku pro rychlé kontroly, ale pokud pravidelně ladíte payloady tokenů (dělal jsem to denně při budování interní auth brány), barevný výstup dělá zásadní rozdíl. Hodnoty řetězců, čísla, logické hodnoty a null se vykreslují v odlišných barvách, takže chybějící oprávnění nebo nesprávné časové razítko vypršení platnosti vidíte na první pohled bez čtení každého znaku.

Knihovna rich (pip install rich) obsahuje funkci print_json, která přijímá buď JSON řetězec nebo Pythoní slovník a vypíše ho s plným zvýrazněním syntaxe do terminálu. V kombinaci s PyJWT získáte dvouřádkový pracovní postup pro inspekci JWT:

Python 3.10+ — výstup terminálu rich
# 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
# }
Poznámka:Výstup rich obsahuje ANSI escape kódy. Nezapisujte ho do souborů ani nevracejte z API endpointů — je určen pouze pro zobrazení v terminálu. Pro prostý textový výstup používejte json.dumps().

Práce s velkými dávkami tokenů

JWT tokeny jsou samy o sobě malé (typicky pod 2 KB), ale existují scénáře, kdy je zpracováváte hromadně. Analýza auditního logu po bezpečnostním incidentu. Skripty pro migraci relací při přechodu na jiného poskytovatele autentizace. Hromadná validace pro účely compliance, kdy je nutné prokázat, že každý token vydaný za posledních 90 dní byl podepsán správným klíčem. Pokud máte desítky tisíc tokenů v souboru NDJSON logu, zpracování řádek po řádku zamezí načítání celého souboru do paměti a umožní průběžně hlásit výsledky.

Hromadná validace tokenů z auditního logu

Python 3.10+ — streamová validace tokenů
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

Extrakce claims z NDJSON exportu tokenů

Python 3.10+ — extrakce a transformace claims z logu tokenů
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")
Poznámka:Pro soubory do několika stovek MB je čtení řádek po řádku dostatečně efektivní. Pokud narazíte na výkonnostní limity u velmi velkých výpisů tokenů, zvažte použití multiprocessing.Pool pro distribuci validace mezi procesory, protože každý token je nezávislý.

Časté chyby

Tyto čtyři chyby se opakovaně objevují při code review a v dotazech na Stack Overflow. Každá z nich se dělá snadno a chybová zpráva od PyJWT ne vždy ukazuje přímo na příčinu. Problém s pojmenováním balíčku sám o sobě může způsobit hodiny zbytečného ladění, když někdo nainstaluje nesprávnou knihovnu a dostane zcela neočekávané API.

Záměna názvů balíčků PyJWT a python-jwt

Problém: Spuštěním pip install jwt nebo pip install python-jwt nainstalujete zcela jiný balíček. Příkaz import jwt pak selže nebo poskytne API, které neznáte.

Řešení: Vždy instalujte pomocí pip install PyJWT. Import je import jwt. Správný balíček ověřte pomocí 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
Vynechání parametru algorithms

Problém: V PyJWT 1.x byl parametr algorithms volitelný a ve výchozím nastavení povoloval jakýkoliv algoritmus. To vytvářelo bezpečnostní zranitelnost, kdy útočník mohl nastavit alg: none. PyJWT 2.x nyní vyvolá DecodeError, pokud algorithms chybí.

Řešení: Vždy předávejte algorithms jako explicitní seznam. Používejte pouze algoritmy, se kterými vaše aplikace skutečně vydává tokeny.

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"])
Použití jwt.decode() s nesprávným typem klíče pro RS256

Problém: Předání řetězcového tajemství funkci jwt.decode() s algorithms=["RS256"] vyvolá InvalidSignatureError. RS256 vyžaduje PEM-zakódovaný veřejný klíč, nikoliv sdílený tajný řetězec.

Řešení: Načtěte PEM veřejný klíč ze souboru nebo proměnné prostředí. Nainstalujte balíček 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"])
Zapomenutý base64 padding při ručním dekódování

Problém: JWT base64url kódování odstraňuje koncové znaky =. Python's base64.urlsafe_b64decode vyvolá binascii.Error: Incorrect padding, pokud předáte surový segment bez opravy paddingu.

Řešení: Před dekódováním doplňte padding: segment += '=' * (-len(segment) % 4). Tento vzorec vždy vypočítá správný počet znaků paddingu (0, 1, 2 nebo 3).

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 vs. alternativy — rychlé srovnání

Metoda
Ověří podpis
Validuje claims
Vlastní typy
Vyžaduje instalaci
PyJWT jwt.decode()
✓ (exp, aud, iss, nbf)
N/A (vrací dict)
pip install PyJWT
PyJWT bez ověření
N/A
pip install PyJWT
Ruční dekódování base64
N/A
Ne (stdlib)
python-jose jwt.decode()
N/A
pip install python-jose
Authlib jwt.decode()
N/A
pip install Authlib
PyJWT + cryptography
✓ (RSA/EC)
N/A
pip install PyJWT cryptography

PyJWT je správný výchozí bod pro většinu Pythoních aplikací. Pokrývá HMAC a (s backendem cryptography) ověření RSA a EC podpisů. Pokud potřebujete JWE (šifrované tokeny), přejděte na python-jose nebo Authlib. Ruční dekódování base64 funguje pro ladění, ale neposkytuje žádné záruky bezpečnosti.

Kdy sáhnu po každé možnosti: PyJWT pro jakoukoliv standardní webovou službu s ověřením HS256 nebo RS256. python-jose když architektura zahrnuje šifrované tokeny nebo rotaci JWKS. Ruční base64 pro rychlou inspekci v prostředích bez pip (CI kontejnery, omezené produkční hostitele, studené starty AWS Lambda, kde chcete minimalizovat závislosti). Authlib když projekt ho již používá pro OAuth klientské toky a přidání další JWT knihovny by bylo nadbytečné.

Pro alternativu bez kódu vložte libovolný token do nástroje JWT Decoder a zobrazte dekódovanou hlavičku a payload s ověřením claims.

Časté dotazy

Jak dekódovat JWT v Pythonu bez ověření podpisu?

Předejte options={"verify_signature": False} a algorithms=["HS256"] funkci jwt.decode(). Ta vrátí slovník payload bez kontroly podpisu. Toto použijte pouze pro inspekci — čtení claims před načtením správného veřejného klíče nebo ladění ve vývoji. Nikdy nevynechávejte ověření u tokenů, které chrání přístup k čemukoliv.

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'}

Jaký je rozdíl mezi PyJWT a python-jwt?

PyJWT (pip install PyJWT, import jwt) je nejpopulárnější JWT knihovna pro Python s více než 80 miliony stažení měsíčně. python-jwt (pip install python_jwt) je samostatná, mnohem méně používaná knihovna s odlišným API. Pokud vidíte import jwt v cizím kódu, používá PyJWT. Záměna vzniká kvůli tomu, že název balíčku na PyPI (PyJWT) se liší od názvu importu (jwt). Zůstaňte u PyJWT, pokud nemáte konkrétní důvod přejít jinam.

Jak dekódovat JWT s RS256 v Pythonu?

Nainstalujte PyJWT spolu s backendem cryptography: pip install PyJWT cryptography. Poté předejte PEM-zakódovaný veřejný klíč jako argument key a algorithms=["RS256"]. PyJWT deleguje ověření RSA podpisu na knihovnu cryptography. Bez nainstalovaného balíčku cryptography vyvolá PyJWT chybu při pokusu o použití algoritmů RSA nebo EC.

Python
import jwt

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

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

Proč PyJWT vyvolává ExpiredSignatureError?

PyJWT ve výchozím nastavení kontroluje claim exp (vypršení platnosti). Pokud aktuální čas UTC překročí časové razítko exp, vyvolá jwt.ExpiredSignatureError. Toleranci posunu hodin lze přidat parametrem leeway: jwt.decode(token, key, algorithms=["HS256"], leeway=timedelta(seconds=30)). To poskytne 30sekundovou rezervu. Pro úplné vypnutí kontroly vypršení platnosti (nedoporučuje se pro produkci) předejte 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")

Lze v Pythonu číst JWT claims bez jakékoliv knihovny?

Ano. Rozdělte token podle teček, vezměte druhý segment (payload), doplňte ho znaky = na délku dělitelnou 4, poté ho base64url-dekódujte a naparsujte JSON. Tím získáte slovník claims, ale podpis se neověří. Hodí se v omezených prostředích, kde nelze nainstalovat PyJWT, nebo pro rychlé ladicí skripty.

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'}

Jak ověřit claim audience pomocí PyJWT?

Předejte parametr audience funkci jwt.decode(): jwt.decode(token, key, algorithms=["HS256"], audience="https://api.example.com"). PyJWT porovná claim aud v tokenu s vámi zadanou hodnotou. Pokud token claim aud neobsahuje nebo se hodnota neshoduje, vyvolá jwt.InvalidAudienceError. Jako přijatelné audience lze také předat seznam, pokud vaše služba přijímá tokeny určené pro více API.

Python
import jwt

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

Související nástroje

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 SantosTechnický recenzent

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.