Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Axios and Flask to use CORS with cookies

Frontend runs at localhost:3000 Server runs at localhost:9000

I am able to make a CORS requests without access to cookies.

Sample Axios Request

axios.post(SERVER+'/createUser', params)
        .then( resp=>{
            //not important
        });

(working: able to access resources from other server)

I was unable to save/send the HttpOnly cookie [session implementation] that the server localhost:9000 sets

Expected Process Flow

Call to localhost:9000/authenticate

localhost:9000/authenticate returns a response with a HttpOnly cookie

subsequent requests to localhost:9000 carry this cookie

To try to access this cookie with axios I added the header withCredentials:true referenced by the documentation for axios. For clarity:

let headers = {
    withCredentials:true
}
export function authenticate(creds){
    return dispatch => {
        axios.post(SERVER+'/authenticate', creds, headers)
            .then( resp => {
                //not important
            });
    };
}

After which I received the following error:

Failed to load http://localhost:9000/authenticate: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:3000' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

For clarity, the first (OPTIONS) request is sent and after a 'successful' response, the error is thrown. OPTIONS request: OPTIONS REQUEST RESPONSE INFO

My server uses Flask-Cors library, after reading the cookie documentation and a few other links, this is how the server is setup for CORS

... normal app init
app = Flask(__name__, static_url_path='/static')
...
cors = CORS(app, origins=["http://localhost:3000"], headers=['Content-Type'], expose_headers=['Access-Control-Allow-Origin'], supports_credentials=True)
...
@app.route('/authenticate', methods=['POST'])
def authenticate():
    ...

I only set the method as POST because (1) the cookie documentation also restricted it to POST and (2) the OPTIONS request seemingly goes through (as referenced by the image) and (3) when I do include OPTIONS as a possible method for the route, when the first request is sent it goes into the method and I have no idea what to return so if someone knows what is the correct response when the OPTIONS method is included please do post.

Other Links

https://github.com/axios/axios/issues/569

Why does my JavaScript get a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error when Postman does not?

CORS: Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true

Set-Cookie header has no effect

like image 226
steff_bdh Avatar asked Jun 27 '18 13:06

steff_bdh


1 Answers

The code looks like you are defining withCredentials as a HTTP header. But that's not exaclty how it works.

withCredentials is actually an option which will enable a http header, but it's not a http header in itself.

Try creating the promise like this:

const axiosWithCookies = axios.create({
  withCredentials: true
});
const promise = axiosWithCookies.get(url);

The resulting http header will actually look as follows. But you don't have to add this manually. This will be taken care of if you create the axios instance as above.

Cookie: JSESSIONID=...
like image 194
bvdb Avatar answered Nov 02 '22 21:11

bvdb