Andriy B.
Andriy B.

Reputation: 451

Edge browser doesn't redirect the call in case of CORS used

Please help me to find an appropriate solution for Edge browser.

I found that Edge browser doesn't follow the Location header in case of HTTP 302 Found response both for GET and POST requests.

In short, the same code (see the explanation below):


  1. page opened: https://example.com

  2. async GET call made to https://some-service.io/login with custom headers set

    Content-Type = application/json; charset=utf-8 
    X-Header = http://some-service.io/xxx-yyy-zzz

Note: different domains are used for the page and for the service

and with withCredentials enabled because of CORS, data attribute has an empty object (for axios call) or some dummy data (for javascript call) as we had an issue in Chrome/FF with headers for the redirected call:

Javascript version

function httpGetAsync(url, method, callback) {
    var xmlHttp = new XMLHttpRequest();

    xmlHttp.onreadystatechange = function ()
    {
        if (xmlHttp.readyState == XMLHttpRequest.DONE && xmlHttp.status == 200) {
            console.log('DONE');
            callback(xmlHttp.readyState + ':' + xmlHttp.status + ':' + xmlHttp.response);
            return;
        }

        console.log(xmlHttp.readyState + ':' + xmlHttp.status + ':' + xmlHttp.response);
        var headers = xmlHttp.getAllResponseHeaders();
        console.log('headers: ' + headers.toString());
    }

    xmlHttp.open(method, url, true); // true for asynchronous
    xmlHttp.withCredentials = true;
    xmlHttp.setRequestHeader('Accept', 'application/json');
    xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
    xmlHttp.setRequestHeader('X-Header', 'https://some-service.io/xxx-yyy-zzz');
    xmlHttp.send("foo=bar&lorem=ipsum");
}

httpGetAsync('https://some-service.io/login', 'GET', function (response) {
    console.log(response);
});

AXIOS version

        ...
        defaultHeaders['Content-Type'] = 'application/json;charset=UTF-8';
        defaultHeaders['X-Header'] = 'https://some-service.io/xxx-yyy-zzz';
        ...
        axios({
            method: 'GET',
            url: 'https://some-service.io/login',
            withCredentials: true,
            headers: defaultHeaders,
            data: {}
        }).then(response => {
        ...
  1. Server responds with HTTP 302, with Set-Cookie and Location: https://some-service.io/login/auth headers in the response, we need to send original headers and the cookies set with the redirected call to https://some-service.io/login/auth
  2. For the redirected call to https://some-service.io/login/auth server responds with HTTP 200, json-object returned in case if Content-Type is set in request headers:

    • Chrome/FF works perfectly, follow the redirects, the headers from the initial call are available for the redirected call as well, HTTP 200 returned with the valid json-object
    • Edge browser doesn't follow Location header value at all
    • IE 11 browser follow the redirect url from Location header but without Headers set in the initial call (added just for comparison)

RAW HTTP

Edge

-- OPTIONS (preflight)

OPTIONS https://some-service.io/login HTTP/1.1
Origin: https://example.com
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362
Access-Control-Request-Headers: content-type,database,dictionarydomain,language,site,x-referer-epay
Access-Control-Request-Method: GET
Accept: */*
Accept-Language: en-US,en;q=0.8,cs;q=0.6,ru;q=0.4,uk;q=0.2
Accept-Encoding: gzip, deflate, br
Host: some-service.io
Content-Length: 0
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache

-- GET Request

GET https://some-service.io/login HTTP/1.1
Origin: https://example.com
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.8,cs;q=0.6,ru;q=0.4,uk;q=0.2
Content-Type: application/json;charset=UTF-8
X-Header: https://some-service.io/xxx-yyy-zzz
Accept-Encoding: gzip, deflate, br
Host: some-service.io
DNT: 1
Connection: Keep-Alive

-- GET Response

HTTP/1.1 302 Found
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 10 Dec 2019 12:26:08 GMT
Expires: 0
Location: https://some-service.io/login/auth
Pragma: no-cache
Set-Cookie: JSESSIONID=CC10DD73C968C42C5A007D27342BF0B5; Path=/; Secure
Set-Cookie: __VCAP_ID__=32ee654d-2947-49e4-4909-9bc7; Path=/; HttpOnly; Secure
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Vcap-Request-Id: ef27c9ae-fa5b-45b6-5c6a-9537b159e533
X-Xss-Protection: 1; mode=block
Content-Length: 0
Connection: keep-alive

-- GET Request for redirected call (https://some-service.io/login/auth, missing)

Chrome

-- OPTIONS (preflight)

OPTIONS https://some-service.io/login HTTP/1.1
Host: some-service.io
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: https://example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Access-Control-Request-Headers: content-type,database,dictionarydomain,language,site,x-referer-epay
Accept: */*
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
Accept-Encoding: gzip, deflate, br
Accept-Language: en,ru-RU;q=0.9,ru;q=0.8,en-US;q=0.7,en-GB;q=0.6

-- GET Request

GET https://some-service.io/login HTTP/1.1
Host: some-service.io
Connection: keep-alive
Origin: https://example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, */*
X-Header: https://some-service.io/xxx-yyy-zzz
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
Accept-Encoding: gzip, deflate, br
Accept-Language: en,ru-RU;q=0.9,ru;q=0.8,en-US;q=0.7,en-GB;q=0.6
Cookie: JSESSIONID=998B805DAF1BBA4C76AB930702C49131; __VCAP_ID__=a3ed6e06-6e23-43ad-469a-e848

-- GET Response

HTTP/1.1 302 Found
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 10 Dec 2019 10:33:02 GMT
Expires: 0
Location: https://some-service.io/login/auth
Pragma: no-cache
Set-Cookie: __VCAP_ID__=32ee654d-2947-49e4-4909-9bc7; Path=/; HttpOnly
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Vcap-Request-Id: e207bdaa-20a6-48a1-7f97-b0688d2f1f98
X-Xss-Protection: 1; mode=block
Content-Length: 0
Connection: keep-alive

-- GET Request for redirected call (https://some-service.io/login/auth)

GET https://some-service.io/login/auth HTTP/1.1
Host: some-service.io
Connection: keep-alive
Origin: https://example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, */*
Database: master
X-Header: https://some-service.io/xxx-yyy-zzz
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
Accept-Encoding: gzip, deflate, br
Accept-Language: en,ru-RU;q=0.9,ru;q=0.8,en-US;q=0.7,en-GB;q=0.6
Cookie: JSESSIONID=998B805DAF1BBA4C76AB930702C49131; __VCAP_ID__=32ee654d-2947-49e4-4909-9bc7

-- GET Response

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Tue, 10 Dec 2019 10:35:35 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: __VCAP_ID__=a3ed6e06-6e23-43ad-469a-e848; Path=/; HttpOnly
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Vcap-Request-Id: ad084e82-1038-4953-5f40-cfcf4f4c10d3
X-Xss-Protection: 1; mode=block
Content-Length: 16
Connection: keep-alive

{"some-value":0}

Notes

    Sec-Fetch-Site: cross-site
    Sec-Fetch-Mode: cors

Upvotes: 3

Views: 2878

Answers (1)

Andriy B.
Andriy B.

Reputation: 451

In order to mitigate CORS implementation differences for different browsers, I decided to move CORS requests from FE side to BE side. Small transparent proxy has been implemented to serve requests from FE to BE and call Service from BE using RestClient (or HttpClient) component which works perfectly with CORS and redirected calls in comparison with direct calls from FE to Service.

Upvotes: 1

Related Questions