JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self - contained way for securely transmitting information between parties as a JSON object. A JWT consists of three parts:
When a user logs in to an application, the server verifies the user’s credentials. If the credentials are valid, the server generates a JWT and sends it back to the client. The client then includes this JWT in the Authorization header of subsequent requests to the API. The server validates the JWT on each request to ensure that the user is authenticated and authorized to access the requested resources.
SPAs like React, Vue.js, or Angular often communicate with Flask APIs. JWTs are used to authenticate users and authorize access to protected endpoints. For example, a user logs in to a SPA, and the SPA sends the credentials to the Flask API. If the login is successful, the API returns a JWT, which the SPA stores and includes in subsequent requests.
Mobile apps also rely on Flask APIs for data. JWTs provide a secure way to authenticate users on mobile devices. When a user logs in to a mobile app, the app sends the credentials to the Flask API, receives a JWT, and uses it to access protected resources.
In a microservices architecture, different services need to communicate with each other securely. JWTs can be used to authenticate and authorize requests between microservices. A user authenticates with a gateway service, which generates a JWT. This JWT is then passed along to other microservices for authorization.
pip install flask flask-jwt-extended
from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
# Initialize Flask app
app = Flask(__name__)
# Set the secret key for signing JWTs
app.config['JWT_SECRET_KEY'] = 'super-secret-key'
jwt = JWTManager(app)
# Mock user database
users = {
'user1': 'password1'
}
# Login route
@app.route('/login', methods=['POST'])
def login():
# Get username and password from the request
data = request.get_json()
username = data.get('username')
password = data.get('password')
# Check if the user exists and the password is correct
if username in users and users[username] == password:
# Create an access token
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token), 200
else:
return jsonify({"msg": "Bad username or password"}), 401
# Protected route
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
# Get the identity of the current user
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200
if __name__ == '__main__':
app.run(debug=True)
JWTManager
is used to manage JWTs in the application./login
route checks the user’s credentials. If the credentials are valid, it creates an access token using create_access_token
and returns it to the client./protected
route is protected by the @jwt_required()
decorator. This decorator ensures that only requests with a valid JWT can access this route. The get_jwt_identity()
function is used to get the identity of the current user from the JWT.If the secret key used to sign JWTs is weak, an attacker can easily guess or brute - force it. This can lead to the attacker generating valid JWTs and accessing protected resources. Always use a strong, randomly generated secret key.
JWTs can have an expiration time. If the server does not verify the expiration time of the JWT, an attacker can use an expired token to access protected resources. Make sure to set an appropriate expiration time for JWTs and verify it on the server side.
Storing JWTs in local storage of a browser can be a security risk. If an attacker manages to execute a cross - site scripting (XSS) attack, they can steal the JWT from local storage. Consider using HTTP - only cookies to store JWTs instead.
Generate a long, random secret key and store it securely. You can use tools like openssl rand -hex 32
to generate a strong secret key.
Set an appropriate expiration time for JWTs. Short - lived tokens reduce the risk of an attacker using a stolen token for an extended period. You can set the expiration time when creating the access token.
from flask_jwt_extended import create_access_token
import datetime
# Create an access token with an expiration time of 15 minutes
expires = datetime.timedelta(minutes=15)
access_token = create_access_token(identity='user1', expires_delta=expires)
Always use HTTPS to encrypt the communication between the client and the server. This prevents man - in - the - middle attacks where an attacker can intercept and modify the JWT.
Validate the JWT on the server for every request to a protected endpoint. Check the signature, expiration time, and other claims to ensure the token is valid.
Securing Flask APIs with JWT is a powerful and widely used technique. By understanding the core concepts, typical usage scenarios, common pitfalls, and best practices, you can build secure and reliable APIs. JWTs provide a simple and effective way to authenticate and authorize users in various application architectures, including SPAs, mobile apps, and microservices.