vimalloc / flask-jwt-extended

An open source Flask extension that provides JWT support (with batteries included)!
http://flask-jwt-extended.readthedocs.io/en/stable/
MIT License
1.56k stars 239 forks source link

Flask-JWT-Extended always assuming token is a refresh token #550

Closed solsahar closed 8 months ago

solsahar commented 8 months ago

Hello! I'm trying to use Flask-JWT-Extended to set JWT tokens using cookies. I set the tokens like this:

jwt_token = create_access_token(identity=username, 
                                additional_claims=additional_claims,
                                  expires_delta=timedelta(minutes=10))
refresh_token = create_refresh_token(identity=username, 
                                     additional_claims=additional_claims, 
                                     expires_delta=timedelta(days=29))
response = make_response(render_template('login_callback.html', access_token=access_token))
set_access_cookies(response, 
                    jwt_token,
                    max_age=timedelta(minutes=10))

set_refresh_cookies(response,
                    refresh_token,
                    max_age=timedelta(days=29))

I then have a protected method called at /layers defined like this:

@dashboard_blueprint.route('/layers')
@jwt_required(locations=["cookies"])
def chatbot_layers():
    claims = get_jwt()
    user_id = claims['user_id']
    return render_template('layers.html', layers=layers[user_id])

On the front end, I noticed I was getting 422 UNPROCESSABLE ENTITY errors with a response json lookling like this: {"msg":"Only non-refresh tokens are allowed"}

I was confused as to why this was happening, and after lots of debugging, I decided to turn to the source code. On line 361 of view_decorators.py, I added 2 new debug statements:

print(f"Verifying! Looking for refresh: {refresh}")
print(f'Decoded: {decoded_token} | Cookies: {request.cookies} | Encoded Token: {encoded_token}')

I noticed that in the decoded token, it seems that 'type' seems to always be refresh. I checked the encoded token, and confirmed that the encoded token is my access token (not refresh token).

Is this a bug? Am I doing it incorrectly?

Thank you!

vimalloc commented 8 months ago

Hrm... at a glance your code all looks ok. I'm pretty sure there isn't a bug with this extension, just due to how frequently it's being used and the test coverage around everything, but I wont rule it out.

Looking at the code in this extension:

My first thought is that maybe the additional_claims that you are passing in is overriding the JWT type. Can you confirm what kind of data is being passed in there?

If you were able to make a minimal and reproducible example that I could run locally that reproduces this error, that would also go a long way towards tracking this down!

Thanks!

solsahar commented 8 months ago

Hey! I finally figured out the issue. The issue was that when I refreshed the token, I passed the claims from the refresh token to the new access token. This overwrote the type and other information. Thank you for the help!