Search code examples
google-chromeflaskcookiesflask-restful

Calling authentication API from different domain won't set cookies


I am running a Flask API which sets cookies (JWT) if username & password is correct.

I am requesting the API from https://example.ngrok.io and the API is located at https://myAPIDomain.com.

The Set-cookie header is present in the response header, but no cookies are set (viewing Chrome application cookie storage).

Here is the backend configuration:

response.headers['Access-Control-Allow-Origin'] = request.headers['Origin']
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'cache-control')
response.headers.add('Access-Control-Allow-Headers', 'X-Requested-With')
response.headers.add('Access-Control-Allow-Headers', 'Authorization')
response.headers.add('Access-Control-Allow-Headers', 'set-cookie')
response.headers.add('Access-Control-Allow-Headers', 'user-agent')
response.headers.add('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')

Setting cookie in backend: resp.headers.add("set-cookie",'cookieKey:cookieValue; Domain=myAPIDomain.com; Max-Age=3600; Secure; Path=/; SameSite=None')

Also tried not specifying the domain: resp.headers.add("set-cookie",'cookieKey:cookieValue; Domain; Max-Age=3600; Secure; Path=/; SameSite=None')

None of these solutions worked.

Here is a picture of the response headers in Chrome: https://i.sstatic.net/XT3XC.jpg

The cookies that the API is supposed to set is used for future API endpoint authentication. So when I send another request:

var myHeaders2 = new Headers();
myHeaders2.append("Content-Type", "application/json");

var requestOptions2 = {
  method: 'GET',
  headers: myHeaders,
  redirect: 'follow',
  credentials: 'include'
};

fetch("https://myAPIDomain.com/endpointWhichRequiresCookies", requestOptions2)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

But cookies are not sent (obviously since chrome is not setting the cookies). Here is what the backend receives: https://codebeautify.org/online-json-editor/cb81fb64

I know a workaround would be to reply with cookies to frontend as JSON reply and frontend sends the cookies as different headers (since you cannot send "cookie" header from frontend), but this is not the best solution for us.

The only reason we are calling the API from ngrok is because we are doing localhost testing.

The cookies are being set with Postman, so I do not think the backend is at fault here.

Any ideas? We have been at this for days now, without being able to solve the issue.


Solution

  • Found the solution!

    We are sending two requests:

    1. Login Post request with username & password (using Fetch POST)
    2. Request to get information from backend (using Fetch GET) - Backend will use the cookies that were set in request #1 to authenticate the request.

    Problem was that we didn't send request #1 with credentials: "include", because we didn't think it was needed for the first request. Our second request always had credentials: "include", but apparently Chrome will disregard the cookies if you do not set credentials: "include" on both requests.