JWT
What is JWT ?

- JWT stands for JSON Web Token. It’s an open standard (RFC 7519) used for securely transmitting information between parties as a JSON object.
- JWT is a token format often used after authentication to maintain sessions.
Key Points About JWT
-
Structure: A JWT consists of three parts:
- Header: Specifies the token type (JWT) and the signing algorithm (e.g., HS256).
- Payload: Contains the claims (data), such as user ID, roles, or expiration time.
- Signature: Ensures the token hasn’t been tampered with. It’s created by hashing the header and payload with a secret key.
-
Format:
header.payload.signature(each part is Base64URL encoded). -
Purpose: Commonly used for authentication and authorization in web applications. For example:
- After a user logs in, the server issues a JWT.
- The client sends this token in the
Authorizationheader for subsequent requests. - The server verifies the token instead of storing session data.
-
Advantages:
- Stateless: No need to store session on the server.
- Compact: Easy to transmit via URL, header, or body.
- Secure: If signed and optionally encrypted properly.
-
Common Use Cases:
- API authentication.
- Single Sign-On (SSO).
- Mobile and SPA (Single Page Application) authentication.
Do you want me to show an example of how to create and verify a JWT in Python using PyJWT, or explain how JWT differs from OAuth tokens?
Minimal sample using JWT (Using HS256)
HS256: Share secret key (less secure)

Install PyJWT package
pip install PyJWT
!pip install PyJWT
Implement issue JWT (encode)
import jwt
from datetime import datetime, timedelta, timezone
# Algorithm to encrype
ALGORITHM = "HS256"
# Use a strong secret from env/config
SECRET_KEY = "super-strong-secret-change-me"
def create_jwt(user_id: str) -> str:
now = datetime.now(timezone.utc)
payload = {
"user_id": user_id, # subject (user id)
"issue_date": int(now.timestamp()), # issued at
"expired": int((now + timedelta(minutes=15)).timestamp()), # expiration
"iss": "your-app", # issuer
"aud": "your-client", # audience
"roles": ["user"] # custom claim
}
token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
return token
token = create_jwt("haiht")
print("JWT (HS256):", token)
Verify a token (decode)
import jwt
def verify_jwt(token: str) -> dict:
try:
decoded = jwt.decode(
token,
SECRET_KEY,
algorithms=["HS256"],
audience="your-client",
issuer="your-app",
)
return decoded # dict with claims
except jwt.ExpiredSignatureError:
raise ValueError("Token has expired.")
except jwt.InvalidAudienceError:
raise ValueError("Invalid audience.")
except jwt.InvalidIssuerError:
raise ValueError("Invalid issuer.")
except jwt.InvalidTokenError as e:
raise ValueError(f"Invalid token: {e}")
# Example usage
# claims = verify_jwt("haiht")
print(f"Token above: {token}")
claims = verify_jwt(token)
print("Verified claims:", claims)
Minimal using (Public/Private key) Example
- Using
RS256

Install extra encryption package
pip install "pyjwt[crypto]"
!pip install "pyjwt[crypto]"
Create public/private key pair
# Private key
openssl genrsa -out private.pem 2048
# Public key
openssl rsa -in private.pem -pubout -out public.pem
You can run directly in Jupyter Notebook by adding !
# Private key
!openssl genrsa -out private.pem 2048
# Public key
!openssl rsa -in private.pem -pubout -out public.pem
Encode with private key
import jwt
from datetime import datetime, timedelta, timezone
def read_file(path: str) -> str:
with open(path, "r", encoding="utf-8") as f:
return f.read()
PRIVATE_KEY = read_file("private.pem")
# print(PRIVATE_KEY)
def create_jwt_rs256(user_id: str) -> str:
now = datetime.now(timezone.utc)
payload = {
"user_id": user_id,
"": int(now.timestamp()),
"exp": int((now + timedelta(minutes=15)).timestamp()),
"iss": "your-app",
"aud": "your-client",
"scope": "read:profile",
}
token = jwt.encode(payload, PRIVATE_KEY, algorithm="RS256")
return token
token = create_jwt_rs256("haiht")
print("JWT (RS256):", token)
JWT (RS256): eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiaGFpaHQiLCIiOjE3NjQ3NDQzMTQsImV4cCI6MTc2NDc0NTIxNCwiaXNzIjoieW91ci1hcHAiLCJhdWQiOiJ5b3VyLWNsaWVudCIsInNjb3BlIjoicmVhZDpwcm9maWxlIn0.bU6cqzAJqs0NiwGhqY5ByuhEwfLEiePAZMJbqz15BXnkZQHKePzClVUNWnMTw9XP8d2nWeekAU2AK1nA3i7KPoMPjBF650nvKIsnLOKwcS2GKWtcR8RNcYKXZJ4BCnrwRBv0H8Wq1ElCIjWknB7CqmYR36njYr5i6S1DmHLc58FUmgteO8SIC3HWX5YPwSxsxItkOOF4H-IIzFXsO0OnLD8X5CRo089Uu9E9rrBi_kIny7fyLKpkbsnkRA8Qr_QfLlAj4rZe_rGgVPCn-5BzM02uDhyWnstEe6ov6lwiDlCsHLlWizjxq2Jumt3BFVIUF76Jp-jYapeSwnT8r2LYnQ
Decode with public key
import jwt
def read_file(path: str) -> str:
with open(path, "r", encoding="utf-8") as f:
return f.read()
PUBLIC_KEY = read_file("public.pem")
def verify_jwt_rs256(token: str) -> dict:
try:
decoded = jwt.decode(
token,
PUBLIC_KEY,
algorithms=["RS256"],
audience="your-client",
issuer="your-app",
)
return decoded
except jwt.ExpiredSignatureError:
raise ValueError("Token has expired.")
except jwt.InvalidAudienceError:
raise ValueError("Invalid audience.")
except jwt.InvalidIssuerError:
raise ValueError("Invalid issuer.")
except jwt.InvalidTokenError as e:
raise ValueError(f"Invalid token: {e}")
# token = create_jwt_rs256("uhaiht")
print(f"Token above {token}")
claims = verify_jwt_rs256(token)
print("Verified claims:", claims)
Token above eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiaGFpaHQiLCIiOjE3NjQ3NDQzMTQsImV4cCI6MTc2NDc0NTIxNCwiaXNzIjoieW91ci1hcHAiLCJhdWQiOiJ5b3VyLWNsaWVudCIsInNjb3BlIjoicmVhZDpwcm9maWxlIn0.bU6cqzAJqs0NiwGhqY5ByuhEwfLEiePAZMJbqz15BXnkZQHKePzClVUNWnMTw9XP8d2nWeekAU2AK1nA3i7KPoMPjBF650nvKIsnLOKwcS2GKWtcR8RNcYKXZJ4BCnrwRBv0H8Wq1ElCIjWknB7CqmYR36njYr5i6S1DmHLc58FUmgteO8SIC3HWX5YPwSxsxItkOOF4H-IIzFXsO0OnLD8X5CRo089Uu9E9rrBi_kIny7fyLKpkbsnkRA8Qr_QfLlAj4rZe_rGgVPCn-5BzM02uDhyWnstEe6ov6lwiDlCsHLlWizjxq2Jumt3BFVIUF76Jp-jYapeSwnT8r2LYnQ
Verified claims: {'user_id': 'haiht', '': 1764744314, 'exp': 1764745214, 'iss': 'your-app', 'aud': 'your-client', 'scope': 'read:profile'}