This guide covers the implementation of JWT token authentication in API security. JWT tokens are a critical component of modern API security, providing a stateless authentication mechanism that allows secure communication between clients and servers. Understanding how to properly implement and validate JWT tokens is essential for preventing unauthorized access to API endpoints.
The secret key is the foundation of JWT security. It is used to encode and decode tokens, ensuring that only authorized parties can create valid tokens. This key must be kept secure and should never be exposed in client-side code or public repositories.
SECRET_KEY = "your_random_long_secure_string_here"
The token_required decorator is a wrapper function that validates JWT tokens before allowing access to protected endpoints. This decorator intercepts requests and verifies that a valid token is present in the authorization header.
from functools import wraps
import jwt
from flask import request, jsonify
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = None
if 'Authorization' in request.headers:
token = request.headers['Authorization'].split(" ")[1]
if not token:
return jsonify({'message': 'Token is missing!'}), 403
try:
data = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
except jwt.ExpiredSignatureError:
return jsonify({'message': 'Token expired!'}), 401
except jwt.InvalidTokenError:
return jsonify({'message': 'Invalid token! Login again.'}), 401
return f(*args, **kwargs)
return decorated
The JWT token must be passed in the Authorization header of the HTTP request. The standard format follows the Bearer token scheme.
Authorization: Bearer <your_jwt_token_here>
authorization_header = request.headers.get('Authorization')
token = authorization_header.split(" ")[1]
The split operation divides the header value on the space character. Index [0] contains "Bearer", and index [1] contains the actual JWT token.
| Step | Validation Check | Error Response | HTTP Status |
|---|---|---|---|
| 1 | Token presence in header | "Token is missing!" | 403 Forbidden |
| 2 | Token signature verification | "Invalid token! Login again." | 401 Unauthorized |
| 3 | Token expiration check | "Token expired!" | 401 Unauthorized |
| 4 | Token structure validation | "Invalid token! Login again." | 401 Unauthorized |
Once the decorator is defined, it can be applied to any route that requires authentication. The decorator ensures that only requests with valid tokens can access the endpoint.
@app.route('/api/data', methods=['GET'])
@token_required
def get_data():
data = {"message": "This is protected data", "status": "success"}
return jsonify(data), 200
The current implementation uses an abort pattern which can be problematic. The code executes the protected function and only aborts if validation fails. This approach is vulnerable because:
# BAD: Function executes, then aborts on failure
@app.route('/api/data')
def get_data():
# Validation happens here
if not valid:
abort(403) # Abort after execution starts
return sensitive_data
# GOOD: Validate first, then execute
@app.route('/api/data')
@token_required
def get_data():
# Only executes if validation passes
return jsonify({"data": "protected"}), 200
A better implementation would use a "validate-then-execute" pattern:
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
# Validate token first
is_valid, error_response = validate_token()
# Only proceed if validation succeeds
if is_valid:
return f(*args, **kwargs)
else:
return error_response
return decorated
curl -X GET http://localhost:5000/api/data
Expected Response: 403 Forbidden - "Token is missing!"
curl -X GET http://localhost:5000/api/data -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Expected Response: 200 OK - Protected data returned
curl -X GET http://localhost:5000/api/data -H "Authorization: Bearer <expired_token>"
Expected Response: 401 Unauthorized - "Token expired!"
curl -X GET http://localhost:5000/api/data -H "Authorization: Bearer invalid_token_string"
Expected Response: 401 Unauthorized - "Invalid token! Login again."
๐ OWASP API Security Training Module
Secure Your APIs, Protect Your Data