Jessi
Jessi

Reputation: 1468

Unable to set cookies in Chrome using Flask-JWT-Extended, React, and Axios

Background and Issues

I have a Flask back-end running in localhost:5000 and a React SPA running on localhost:3000. I was able to make them talk but when trying to store the token generated from Flask into Browser's cookies 1) response headers does not contain any cookies when doing console.log(response) after a successful POST from axios and 2) the cookies are not being set. But when inspecting the network > Login.js header, I could actually see the Set-Cookie key exists as response's header. I've tried multiple solutions from Google and StackOverflow but no solution seems to work here and I really can't figure out what is going on as the request is being made successfully, and Chrome is allowing third party software to set the cookies. And even I can see the tokens from Network > Login.js header.

Steps

1) Users enters in their username and password and hit login.

2) Axios POST call is made to Flask's back-end.

3) Process the data and generates a couple of tokens and set them into cookies.

4) Browser's cookie are set with few tokens. <- this part is not working.

Code

Flask back-end token generation using flask-jwt-extended

# app_config related to flask-jwt-extended
CORS_HEADERS = "Content-Type"
JWT_TOKEN_LOCATION = ["cookies"]
JWT_COOKIE_SECURE = False
JWT_COOKIE_CSRF_PROTECT = True



# post method from flask-restful for LoginAPI class
def post(self):
    email = request.json.get("email")
    password = request.json.get("password")

    # some processing here.....
    payload = {
        "email": email
    }

    access_token = create_access_token(identity=payload)
    refresh_token = create_refresh_token(identity=payload)

    response = jsonify({"status": True})
    set_access_cookies(response, access_token)
    set_refresh_cookies(response, refresh_token)

    return response

CORS using flask-cors

# in below code, I had some issues with putting wildcard (*) into origin, so I've specified to the React SPA's host and port.
CORS(authentication_blueprint, resources={r"/authentication/*": {"origins": "http://localhost:3000"}},
     supports_credentials=True)

React SPA - making a post call using axios

# also tried `axios.defaults.withCredentials = true;` but same result.
export const login = (email, password, cookies) => {
return dispatch => {
    const authData = {
        email: email,
        password: password
    };

    let url = 'http://127.0.0.1:5000/authentication/login/';

    axios.post(url, authData, {withCredentials: true)
        .then(
            response => {
                console.log(response)
            })
        .catch(err => {
            console.log(err)
        });

    dispatch(authSuccess(email, password));
    }
};

Below image is the response from successful post call in axios. I'm not sure whether it is normal but response's headers are not showing any of the cookies that I'm setting from the back-end.

enter image description here

And below image is from Network > header for login/

As shown, you can clearly see the token information with Set-Cookie key. I've also checked that they aren't secure.

enter image description here

And finally when I check my cookie tab from application > cookies, I do not see anything.

Upvotes: 1

Views: 2857

Answers (1)

Jessi
Jessi

Reputation: 1468

So the issues were coming from the localhost.

I have a Flask back-end running in localhost:5000 and a React SPA running on localhost:3000.

From above statement, to be very specific, I was running the back-end on localhost:5000 and running the React SPA on 127.0.0.1:3000.

Once I've changed the 127.0.0.1 to localhost, it worked like a charm.

And a side note, after playing around with CORS, I think it will be a lot easier to use Nginx and proxy_pass to pass the request coming from React SPA to back-end to avoid using CORS completely, because if one have to use the CORS in different environment such as test, staging and etcs, one would have to set up the CORS at the web server level e.g) Nginx anyway and it requires slightly different configuration that how I set up for local environment anyway.

Upvotes: 1

Related Questions