Refresh TokensΒΆ

Flask-JWT-Extended supports refresh tokens out of the box. These are long lived tokens which can be used to create new access tokens once an old access token has expired. Refresh tokens cannot access an endpoint that is protected with jwt_required() and access tokens cannot access and endpoint that is protected with jwt_refresh_token_required().

By setting the access tokens to a shorter lifetime (see Configuration Options), and utilizing refresh tokens we can help reduce the damage that can be done if an access token is stolen. However, if an attacker gets their hands on the refresh token, they can keep generating new access tokens and accessing protected endpoints as though he was that user. We can help combat this by using the fresh token pattern, discussed in the next section.

Here is an example of using access and refresh tokens:

from flask import Flask, jsonify, request
from flask_jwt_extended import (
    JWTManager, jwt_required, create_access_token,
    jwt_refresh_token_required, create_refresh_token,

app = Flask(__name__)

app.config['JWT_SECRET_KEY'] = 'super-secret'  # Change this!
jwt = JWTManager(app)

@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username', None)
    password = request.json.get('password', None)
    if username != 'test' or password != 'test':
        return jsonify({"msg": "Bad username or password"}), 401

    # Use create_access_token() and create_refresh_token() to create our
    # access and refresh tokens
    ret = {
        'access_token': create_access_token(identity=username),
        'refresh_token': create_refresh_token(identity=username)
    return jsonify(ret), 200

# The jwt_refresh_token_required decorator insures a valid refresh
# token is present in the request before calling this endpoint. We
# can use the get_jwt_identity() function to get the identity of
# the refresh token, and use the create_access_token() function again
# to make a new access token for this identity.
@app.route('/refresh', methods=['POST'])
def refresh():
    current_user = get_jwt_identity()
    ret = {
        'access_token': create_access_token(identity=current_user)
    return jsonify(ret), 200

@app.route('/protected', methods=['GET'])
def protected():
    username = get_jwt_identity()
    return jsonify(logged_in_as=username), 200

if __name__ == '__main__':