Search code examples
pythonflaskcookiesflask-jwt-extended

Cookies not being set with Flask JWT extended


I'm using flask-jwt-extended and try to send a cookie. Unfortunately I doesn't get stored in the browser, I can find it in the header though:

Set-Cookie: refresh_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTM0NjUwNDgsIm5iZiI6MTU5MzQ2NTA0OCwianRpIjoiMjk3ZmQ2NTgtZDBmMi00ZjNlLWI0MGItNWViZDEzYzFjYWFhIiwiZXhwIjoxNTk2MDU3MDQ4LCJpZGVudGl0eSI6eyJpZCI6MSwicm9sbGUiOiJhZG1pbmlzdHJhdG9yIn0sInR5cGUiOiJyZWZyZXNoIiwiY3NyZiI6IjlmM2EzNGU2LTFjYzYtNDI4MC04NzEzLThkYmRiYTUyNzg2ZiJ9.Dcow66aWcChwvYHorP1Tk57bTT25ZP3k2Dlvuo9Vngs; Secure; HttpOnly; Path=/auth/refresh

It looks malformed to me: "Secure" should be "True" for instance, I'm suspecting this is the reason why it doesn't get stored (this question is addressing the same problem, but I did not manage to solve it with the answer provided there).

init.py (relevant parts):

from flask_jwt_extended import JWTManager
from flask_cors import CORS
from config import Config
jwt = JWTManager()

def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)
    app.config['JWT_TOKEN_LOCATION'] = ['cookies']
    app.config['JWT_COOKIE_SECURE'] = True
    app.config['JWT_ACCESS_COOKIE_PATH'] = '/auth'
    app.config['JWT_REFRESH_COOKIE_PATH'] = '/auth/refresh'
    app.config['JWT_COOKIE_CSRF_PROTECT'] = True
    app.config['JWT_COOKIE_SECURE'] = True
    app.config['JWT_CSRF_CHECK_FORM'] = True
    app.config['JWT_SECRET_KEY'] = "change this" 
    CORS(app, supports_credentials=True)
    jwt.init_app(app)
 

routes.py (relevant parts):

@bp.route('/login', methods=['POST'])
def login():
    ...
    resp = jsonify(access_token=access_token,
                       refresh_token=refresh_token)

    set_access_cookies(resp, access_token)
    set_refresh_cookies(resp, refresh_token)
    return resp, 200

I took the example in the official repo of the extension as inspiration. What am I doing wrong here?


Solution

  • It turned out to be an Angular mistake - "withCredentials: true" was missing.

    login(email: string, password: string): Observable<TokenPair> {
            const url: string = `${this.BASE_URL}` + '/auth/login';
            return this.http.post<TokenPair>(
                url,
                JSON.stringify({ email, password }),
                {
                    withCredentials: true,
                },
            );
        }