๐Ÿ“ Python

JWT Tokens with python-jose

P
Author
PyLand Team
๐Ÿ“…
Published
30.06.2026
โฑ๏ธ
Reading time
1 min
๐Ÿ‘๏ธ
Views
516
๐Ÿ†
Level
Expert

python-jose is a library for working with JSON Web Tokens (JWT).

Installation

pip install python-jose[cryptography]

Creating a token

import os
from datetime import datetime, timedelta, timezone

from jose import jwt

SECRET_KEY = os.environ["JWT_SECRET_KEY"]
ALGORITHM = "HS256"

def create_access_token(data: dict, expires_minutes: int = 30) -> str:
    payload = data.copy()
    now = datetime.now(timezone.utc)
    expire = now + timedelta(minutes=expires_minutes)
    payload["exp"] = expire
    payload["iat"] = now
    return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)

Decoding a token

from jose import JWTError, jwt

def decode_token(token: str) -> dict | None:
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except JWTError:
        return None

# Usage
token = create_access_token({"sub": "user_id_42", "role": "admin"})
payload = decode_token(token)
# {'sub': 'user_id_42', 'role': 'admin', 'exp': 1234567890, 'iat': ...}

Access and Refresh tokens

def create_tokens(user_id: int) -> dict:
    access_token = create_access_token(
        data={"sub": str(user_id), "type": "access"},
        expires_minutes=30,
    )
    refresh_token = create_access_token(
        data={"sub": str(user_id), "type": "refresh"},
        expires_minutes=60 * 24 * 7,  # 7 days
    )
    return {
        "access_token": access_token,
        "refresh_token": refresh_token,
        "token_type": "bearer",
    }

def refresh_access_token(refresh_token: str) -> str | None:
    payload = decode_token(refresh_token)
    if not payload or payload.get("type") != "refresh":
        return None
    return create_access_token({"sub": payload["sub"], "type": "access"})

RS256 (asymmetric cryptography)

from jose import jwt

# Generating keys:
# openssl genrsa -out private.pem 2048
# openssl rsa -in private.pem -pubout -out public.pem

with open("private.pem") as f:
    private_key = f.read()
with open("public.pem") as f:
    public_key = f.read()

# Sign with the private key
token = jwt.encode({"sub": "1"}, private_key, algorithm="RS256")

# Verify with the public key
payload = jwt.decode(token, public_key, algorithms=["RS256"])

JWT structure

eyJhbGciOiJIUzI1NiJ9  โ† Header (base64)
.eyJzdWIiOiIxIn0       โ† Payload (base64)
.abc123signature        โ† Signature (HMAC)

JWT is signed, not encrypted. Never store secrets in the payload!

Keep signing keys outside source control, rotate them deliberately, restrict accepted algorithms during decoding, and validate application-specific claims such as iss, aud, and token type when your system uses them.

Your reaction to the article

๐Ÿ’ฌ Comments (0)

๐Ÿ” Sign in to leave a comment
๐Ÿšช Login
๐Ÿ’ญ

No comments yet

Be the first to share your opinion about this article!

๐Ÿ”— Similar

Similar articles

Continue learning with these materials

๐Ÿ“

if __name__ == "__main__": the Python entry point

The if name == "main" guard defines a Python program's entry point: it distinguishes direct...

๐Ÿ“… 14.08.2026 ๐Ÿ‘๏ธ 44
๐Ÿ“

strip() and lower(): Preparing User Text ๐Ÿงน

A user may enter the correct word with extra spaces or different letter case. Python...

๐Ÿ“… 11.08.2026 ๐Ÿ‘๏ธ 50
๐Ÿ“

ord(), chr(), and Cyclic Letter Shifts in Python ๐Ÿ”

A string contains characters, but a computer stores every character as a numeric code. Python...

๐Ÿ“… 09.08.2026 ๐Ÿ‘๏ธ 89
๐ŸŽ“ Continue learning

Courses that cover this material

Visit the course to apply this material in practice.

FastAPI: From First Route to an AI-Powered Site Open course curriculum