This guide aims to provide an in-depth tutorial on how to set up flask-jwt-extended using cookies. There's a LOT of docs online but they are mostly...
For further actions, you may consider blocking this person and/or reporting abuse
Thanks a lot for the really comprehensive article!
Flask-JWT is very complicated to me, I just can't get some things.
For example, from my understanding, when the access token is expired, we just want to use the refresh token and generate a new access token - and this should be done completely transparent for the end user. I can't get how it's done in practice. Can you explain? Thanks!
Yep! This is one of the questions I was faced with which prompted me to write the guide.
Practically, the expired token should indeed be refreshed transparently. But that's a bit tough if you're using pure backend (which is what this guide focuses on). So what I like to do is mentioned in the
@expired_token_loader
and@jwt.refresh_token_required
decorators above.Basically I unset the user jwt in
@expired_token_loader
and redirect the user totoken/refresh
, which then refreshes the jwt and redirects the user toBASE_URL
. This happens fast enough to seem transparent to the user.Thanks for your response.
I don't see any code here redirecting back to the page (URL).
The function refresh() uses url variable but where is it from?
Thanks.
The
url
var is just a placeholder that you can change to any URL you'd like the user to be redirected to.Although I suppose I should change it to
BASE_URL
Sorry but it's still not clear for me. Do I understand properly that this function is called automatically, therefore it MUST know which URL to redirect next. You can provide BASE_URL but it's not the point because we want the redirection to be done to the same URL that fired refreshing token, right? How to gain it?
Thanks!
This is exactly the drawback of using just the backend for jwt, there's no simple way for
refresh
to know which url the user was on when the token expired. So it just redirects toBASE_URL
or any other URL you've set by default to a variableThanks. Because I was starting feeling that something is wrong with me - I just can't get some things here :) I actually found the way to pass the url to be redirected to (just attach as a query to it) but the problem when I try to call the method with @jwt_refresh_token_required I've got kicked back to @jwt.expired_token_loader function. I'm really puzzled about what's wrong with it because I managed to make it work for API calls but not for the backend.
Make sure you
unset_access_cookies()
before assigning new ones. Also make sure you're not "calling" the method by name (i.erefresh()
). You need toredirect()
to the refresh url insteadYes, I did so. But I have a feeling that I just can't set cookies on a protected route because @jwt_required decorator can't find any cookies YET and kick me out. I'm totally confused now :(
Whenever I'm sending a POST request from inside a logged in state from frontend, backend throws the error 'no auth header' with @jwt_required, where as it works perfectly fine with GET requests. Basically I wanted to use the function get_jwt_identity().
Why is this happening?
Here are the screenshots:
dev-to-uploads.s3.amazonaws.com/i/...
dev-to-uploads.s3.amazonaws.com/i/...
Yep! This is expected. You see, a POST request expects a csrf token with it. You've to manually ensure you pass the csrf token. Read this docs' Passing JWT to RESTful API resources.
Basically, ensure that the
form
you're POSTing has a hidden input field that contains the csrf token (you can pass that token from the backned). That's it!Since you're using ajax, you need to pass the extra header manually instead of rendering the token as an input field in the form. Read this for more info.
Two things.
1.) If I'm sending a post request on the same domain then why do I need CSRF Token? Is it not only for cross domain requests?
2.) Even if you do require CSRF Token on the same domain, this stills show no auth header:
dev-to-uploads.s3.amazonaws.com/i/...
1) Actually CSRF is supposed to be use for forms in the same domain. You see, a malicious person could easily post your form on another domain. This is why CSRF exists. Ofcourse you can disable it, at your own risk, with
JWT_COOKIE_CSRF_PROTECT
andJWT_CSRF_CHECK_FORM
.2) I'm guessing the
authToken
in your code has the wrong value. I don't see where you assign it so I can't tell for sure. Can you try using this instead-I couldn't figure it out with POST request in this case. I'll just use GET request which works fine.
Thank you so much for the help though! I immensely appreciate it
It would be great if you give the link to some repo with the working example because I can't find any on the Internet! So, I have a feeling I'm missing something but I can't figure out what is that because there are no working examples to look into.
Thanks a lot!
I added a gist with a working example!
Thanks for the example! I have to look into it.
I have a flask app with flask admin and flask-security.
Now I have to write rest apis.. I prefered Jwt-Extended with jwt in cookies.
For now I dont understand how can i get csrf token for Login api?
I tried many ways and it says csrf token missing
Very in-depth write up, and a great read! Well done and thank you for helping with this!!
Great article! How would we test this using Postman?
This tutorial focuses on a centralized backend solution to tackle JWT based authentication. Therefore it does not usually return a JSON response containing the tokens.
You'd ideally want to follow the official tutorials where the return a
jsonify
object with the tokens, they set up an API that is easier to work with using Postman. This might be helpful!