Practical JWT Authentication with PyJWT and Django SimpleJWT
This article explains the JWT standard, its three-part structure, and demonstrates how to generate, decode, refresh, and handle exceptions for tokens using PyJWT, then shows integration of SimpleJWT in a Django REST framework project, along with security best‑practice tips.
What is JWT
JSON Web Token (JWT) is a lightweight, JSON‑based open standard (RFC 7519) for securely transmitting information between parties. Its main features are a simple structure, lightweight nature, and cross‑platform support, making it suitable for user authentication, data encryption, and stateless API access control.
JWT Structure
JWT consists of three parts separated by dots:
Header : describes the token type and signing algorithm.
Payload : contains claims such as user ID, expiration time, etc.
Signature : used to verify the token’s authenticity.
Example token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cTypical Use Cases
User authentication in front‑end/back‑end separated projects.
Authorization via role‑based access control.
Secure information transmission.
Using JWT with PyJWT
Install the library:
pip install PyJWT1. Basic Usage – Generating a Token
import jwt
import datetime
SECRET_KEY = 'mysecretkey'
def create_token(data):
payload = {
"data": data,
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1) # expires in 1 hour
}
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
return token
# Example
token = create_token({"user_id": 123})
print("Generated Token:", token)2. Decoding a Token
def decode_token(token):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
return "Token has expired"
except jwt.InvalidTokenError:
return "Invalid token"
# Example
decoded = decode_token(token)
print("Decoded Payload:", decoded)3. Adding Extra Claims
def create_token_with_roles(data, roles):
payload = {
"data": data,
"roles": roles,
"iat": datetime.datetime.utcnow(), # issued at
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=2) # expires in 2 hours
}
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
return token
# Example
token_with_roles = create_token_with_roles({"user_id": 456}, ["admin", "editor"])
print("Token with roles:", token_with_roles)
decoded_with_roles = decode_token(token_with_roles)
print("Decoded with roles:", decoded_with_roles)4. Refresh Token Pattern
To improve security, a dual‑token mechanism (Access Token + Refresh Token) is often used.
def create_refresh_token(data):
payload = {
"data": data,
"exp": datetime.datetime.utcnow() + datetime.timedelta(days=7) # expires in 7 days
}
refresh_token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
return refresh_token
def refresh_access_token(refresh_token):
try:
payload = jwt.decode(refresh_token, SECRET_KEY, algorithms=["HS256"])
new_access_token = create_token(payload["data"])
return new_access_token
except jwt.ExpiredSignatureError:
return "Refresh token has expired"
except jwt.InvalidTokenError:
return "Invalid refresh token"
# Example
refresh_token = create_refresh_token({"user_id": 123})
print("Refresh Token:", refresh_token)
new_access_token = refresh_access_token(refresh_token)
print("New Access Token:", new_access_token)5. Custom Exception Handling
def decode_token_with_exceptions(token):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
raise Exception("Token expired. Please log in again.")
except jwt.InvalidSignatureError:
raise Exception("Invalid token signature. Token might be tampered.")
except jwt.InvalidTokenError:
raise Exception("Invalid token. Please provide a valid token.")
# Example
try:
decoded_payload = decode_token_with_exceptions(token)
print("Decoded:", decoded_payload)
except Exception as e:
print("Error:", e)Practical Integration in Django
Install the SimpleJWT package for Django REST framework: pip install djangorestframework-simplejwt Configure the authentication classes in settings.py:
INSTALLED_APPS += ["rest_framework"]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}Add token endpoints to urls.py:
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]Testing:
Obtain a token by sending a POST request to /api/token/ with username and password.
Refresh the token by POSTing to /api/token/refresh/ with the refresh token.
Important Security Considerations
Do not store sensitive information inside the JWT payload.
Set appropriate expiration times to avoid long‑lived tokens.
Protect the signing key and use strong algorithms.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
