0

I am trying to send a post request to a Flask server that uses flask_jwt_extended tokens. I don’t want the page to refresh after each submit and I managed to do this using jquery. But I am unable to send CSRF token in a way that flask_jwt_extended can authenticate user.

function myfunction(action, id, csrf_token){
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://127.0.0.1:5000/accept", true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({
        action: action,
        id: id,
            csrf_token: csrf_token
        }));
}

$(document).ready(function() {
    $(document).on('click', '#my-form', function(event) {
            var action =  $(event.target).attr('value');
            var f = $(this);
            csrf_token = f.find('input[id=csrf_token]');
            myfunction(action, f.find('[name=song_id]').val(), csrf_token)
      return false;
     });
});
@app.route('/accept', methods=["POST"])
@jwt_required
def accept():
    user = get_jwt_identity()
    ...

When I try the following I get a 401 error, which is not surprising as I am not passing the csrf token as in a form. If I simply submit a post request on the form, it works fine.

EDIT: On my backend I am using the following setting for flask_jwt_extended:

app.secret_key = 'loginner'
app.config['JWT_SECRET_KEY'] = 'super-secret'
app.config['JWT_TOKEN_LOCATION'] = ['cookies', 'headers']
app.config['JWT_BLACKLIST_ENABLED'] = True
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh']
app.config['JWT_COOKIE_CSRF_PROTECT'] = False # the bearer request works when this is False, but ideally it would be True
app.config['JWT_CSRF_CHECK_FORM'] = True

And I am getting the identify in the following:

@app.route('/accept', methods=["POST"])
@jwt_required
def accept():
    user = get_jwt_identity()
    ...

It works as expected when app.config['JWT_COOKIE_CSRF_PROTECT'] = False

msche
  • 66
  • 9

1 Answers1

0

Your question does not specify how you are handling the JWT on the client side, but the basic answer is that you need to pass an Authorization header with your request (see more near the bottom of the page in your flask_jwt_extended docs). There may be some confusion in that CSRF and identity are not the same thing. CSRF just helps your frontend and API understand that they can trust each other. A package like flask_jwt_extended helps your backend identify the user and authorize requests.

In your client example above, you would add another header line as such:

// the 'jwt' variable refers to however you have stored the token. Change as needed
xhr.setRequestHeader('Authorization', 'Bearer ' + jwt);
Riley Pagett
  • 363
  • 1
  • 7