Home > OS >  Flask JWT-extended not recognizing access token, only when GET method is used
Flask JWT-extended not recognizing access token, only when GET method is used

Time:04-29

Hi everyone!

I'm building a website, and I'm stuck with sending a form. My problem is that it sends the access_token_cookie, but triggers the unauthorized_token_callback. I saw the request and the respone and the request contains the token, but the code pretends like it's not even there.

I can't wrap my head around it, and I need some good tips.

Here is the JWT configuration, the secret keys are not included in this snippet:

application.config['JWT_TOKEN_LOCATION'] = ['cookies', 'headers', 'json', 'query_string']
application.config['JWT_COOKIE_SECURE'] = False #! Needs to be changed in production
application.config['JWT_COOKIE_CSRF_PROTECT'] = True
application.config['JWT_CSRF_CHECK_FORM'] = True
application.config['JWT_COOKIE_SAMESITE'] = 'Strict'
application.config['CSRF_COOKIE_NAME'] = 'csrf_token'
application.config['JWT_ACCESS_CSRF_HEADER_NAME'] = ['X-CSRF-TOKEN-ACCESS', 'X-CSRFToken']
application.config['JWT_CSRF_IN_COOKIES'] = True

I'm using a custom decorator, that restricts the user access based on the role of the user:

def Xrole_required(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        verify_jwt_in_request()
        role = dth.get_user_by_email(get_jwt_identity()).roles.role_name
        if(role != 'required_role'):
            flash('Xrole required', 'error')
            return Response(render_template('404.html', title='Not Logged In'), 404, mimetype='text/html')
        else:
            return fn(*args, **kwargs)
    
    return wrapper

Whenever I remove the decorator, it redirects me with no problem, but using it says that I'm not logged in. I use this decorator on other places and there it works perfectly fine.

The interesting thing is, that this works on every GET request, but it does not, on other methods. Here is the form, so you can see it:

<form  action="{{ url_for('MyEndpoint_name', show='active') }}" method="POST">
  <div >
    <label for="desc" >Description</label>
    <input id="desc" name="desc" type="text" required >
  </div>
  <div >
    <label>Text</label>
    <input type="text" >
  </div>
  <div >
    <label>Number</label>
    <input type='number' value="0" min="0" >
  </div>
    <button type="button"  data-bs-dismiss="modal">Cancel</button>
    <button type="submit" >Submit</button>
</form>

And here is the resource that handles the request:

class MyResource(Resource):
    
    @Xrole_required
    def post(self, show):
        #here comes the code, this is only for test
        return redirect(url_for('/redirect_page'), 303)

Did I make a mistake in here somewhere, or did I miss some crucial part of the documentation?

Please note, that I don't want to use XMLHttpRequest, because it would be an overkill, I have a lot of js already and these are simple forms.

CodePudding user response:

You are probably running into a CSRF problem. Make sure to set JWT_CSRF_CHECK_FORM to True and include the CRSF token in a hidden field in your form by using https://flask-jwt-extended.readthedocs.io/en/stable/api/#flask_jwt_extended.get_csrf_token

  • Related