0

So I'm able to create aa JWT on login using flask-jwt-extended

I set the expiration to 5 minutes. So I have routes in my VueJS app and when they are called(beforeeach) I make a call to "/api/check" to make sure that the token is valid.

All other API calls are via axios to the backend.

What I'm not understanding that since the cookie is HTTP only I can't check the expiation with javascript...does that mean I have to ping the backend every X minutes along with with every axios call to refresh the cookie then make the actual API call?

Seems like a lot of overhead. Lots of code out there on the nuts and bolts however not much on the actual steps behind the issue I'm having...understanding...

Thanks

BostonMacOSX
  • 1,369
  • 2
  • 17
  • 38
  • https://stackoverflow.com/a/46284627/272689 has some info that might be helpful when it comes to token refreshing. – vimalloc Jul 17 '20 at 04:33

3 Answers3

1

You could have the backend automatically refresh the cookie if it is close to expiring without having to do anything extra on the frontend. Something like this (untested)

@app.after_request
def refresh_jwt_if_near_expiring(response):
    expires_time = get_raw_jwt().get('exp')
    if not expires_time:
        return response
    
    # Change the time delta based on your app and exp config. 
    target_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
    if (target_time > expires_time):
        access_token = create_access_token(identity=get_jwt_identity())
        set_access_cookies(response, access_token)

    return response

Then if the user is inactive for X many minutes they get logged out, otherwise they keep getting a new token as needed. If they do wait too long and get logged out, the backend returns a 401 and your frontend can prompt them to log in again.

vimalloc
  • 3,869
  • 4
  • 32
  • 45
  • if I'm using CSRF whiich token do II need to send in the refresh or the access CSRF...tthis seems like a blank check which will react to any token coming in the door...without checking for prrotections... – BostonMacOSX Jul 17 '20 at 12:39
  • With this setup you don’t need a refresh token, you can implicitly keep refreshing the access token before it expires without the need for a secondary token. For CSRF protection you absolutely still want to have that setup, but that is no different then your normal CSRF protection while using flask-jwt-extended with cookies. – vimalloc Jul 17 '20 at 13:20
  • I guess I should still make the route JWT protected then......or check that it is a valid JWT before just creating a new one... – BostonMacOSX Jul 17 '20 at 19:42
  • `get_raw_jwt()` and `get_jwt_identity()` will return `None` unless you have hit a protected endpoint and the provided JWT was validated and not expired. – vimalloc Jul 17 '20 at 19:45
  • and issn't target_time going to always be greaterr than the expires time after a certain time just alway refreshing the token? – BostonMacOSX Jul 17 '20 at 20:05
  • You will want to tweak the target time to whatever your app requires. In the past I’ve done something like set the expires time to 60 minutes and the target time to 30 minutes. – vimalloc Jul 17 '20 at 20:06
  • thanks I didn't know an expired token would automatically return null no matter what....happens....so this would indeed log out a user .... sorry takes me a few times for ideas to sink in..... – BostonMacOSX Jul 17 '20 at 23:18
  • vimalloc - noted that expired_time and target_time can't be compared.....they have to both be epoch time to be compared..... – BostonMacOSX Jul 20 '20 at 23:08
0

A backend service which decomposes the jwt and returns the expiration time would do the trick.

  • so I call that eevryytime I call anything else...so two calls everry time? – BostonMacOSX Jul 17 '20 at 00:26
  • You just need to call that when the JWT changes. The JWT will still be stored in a Http Only Cookie, but you can store the expiration in a way that is accesible from the front end. – Facundo Garcia Jul 17 '20 at 00:46
0

in my opinion you don't need route "/api/check" to make sure tokens are valid. just add a decorator @jwt_required

@api.route('/api/user')
@jwt_required
def api_user():
    result = #your logic
    return jsonify(result), 200
DhaniPro
  • 59
  • 1
  • 8