cordova-plugin-advanced-http icon indicating copy to clipboard operation
cordova-plugin-advanced-http copied to clipboard

[Bug] Cookies not being set/sent with redirected response/requests

Open longzheng opened this issue 5 years ago • 11 comments

I'm using an external API that is setting a cookie on a 302 redirect which this plugin does not seem to handle correctly.

I was able to always reproduce this issue in the following test case (I mocked these HTTP responses). I used a network capture tool like Charles to inspect the request/responses.

  1. Redirects are handled (disableRedirect is not enabled)
  2. GET http://www.mocky.io/v2/5bb2006d2e00009015927349 (redirects & sets cookie)
Location: https://www.mocky.io/v2/5185415ba171ea3a00704eed
Set-Cookie: redirected=true; Path=/; Secure; HTTPOnly
  1. (Redirected URL is automatically requested) GET https://www.mocky.io/v2/5185415ba171ea3a00704eed does not send any cookies as expected
  2. (Manual request) GET https://www.mocky.io/v2/5185415ba171ea3a00704eed does not send any cookies as expected

Testing with an endpoint that sets cookies on a normal response (without redirect) works correctly. The subsequent request sends the stored cookie. (e.g. GET https://www.mocky.io/v2/5bb1fe132e00008535927339)

I think this is a bug in the redirection handler/logic.

longzheng avatar Oct 01 '18 11:10 longzheng

I was also able to confirm if I enable disableRedirect, then the response cookie is correctly stored and sent in subsequent requests, however obviously I'd need to manually handle the redirects which isn't desirable.

longzheng avatar Oct 01 '18 12:10 longzheng

Also I only tested on iOS. Not sure if this affects Android.

longzheng avatar Oct 01 '18 12:10 longzheng

+1 on this. I have a situation similar to the OP. My login using POST is based on cookies and the portal returns a 302 found. This plugin does follow the redirect correctly, but ignores the cookies.

This problem is evident on both iOS and Android

pliablepixels avatar Oct 10 '18 13:10 pliablepixels

In my project I've worked-around this by

  • enabling disableRedirect
  • handle HTTP redirect status codes in http rejection
  • extract URL from Location header
  • call the redirected URL recursively

Which is roughly

this.http.get(url, {}, {}).then(
        data => {
          ...
        }, (error: HTTPResponse) => {
          // if response is a redirect
          if (error.status > 300 && error.status < 400) {
            this.handlRedirectResponse(error).then(
              ...
          }
        })

  private handlRedirectResponse(http: HTTPResponse) {
    // get redirect path
    let redirectPath: string = http.headers['location'];

    // fix up some redirect URL with spaces (it should have been urlencoded, but it's not)
    redirectPath = redirectPath.replace(/\s/g, '%20');

    // prepend the domain name
    let redirectUrl = `${this.apiDomain}${redirectPath}`

    return this.http.get(redirectUrl);
  }

It's a bit dirty but works.

longzheng avatar Oct 11 '18 11:10 longzheng

Hi longzheng, that's a good warkaround! I can confirm this is a problem, I'll need to fix.

silkimen avatar Oct 11 '18 12:10 silkimen

Thanks @longzheng I've done something similar but glad to see @silkimen plans to address this in the core code!

pliablepixels avatar Oct 11 '18 13:10 pliablepixels

+1 I can confirm this bug exists on both iOS and Android versions of the cordova plugin (using latest Ionic 3 framework). If it can help, this is the workaround I am using at the moment, following the idea of @longzheng :

this.http.disableRedirect(true);
return this.recursivePost(this.loginURL, body, headers);

and the extra function

recursivePost(url, body, headers) {
        return new Promise((resolve, reject) => {
            this.http.post(url, body, headers).then(
                response => {
                    resolve(JSON.parse(response.data));
                },
                error => {
                    if (error.status > 300 && error.status < 400) {
                        let redirectPath: string = error.headers['location'];
                        redirectPath = redirectPath.replace(/\s/g, '%20');
                        let redirectUrl = this.SERVER_URL + redirectPath;
                        resolve(this.recursivePost(redirectUrl, {}, headers));
                    }
                    else {
                        reject(JSON.parse(error.data));
                    }
                }
            )
        });
    }

mg-partec avatar Oct 19 '18 08:10 mg-partec

Just a note to say that this is still an issue, but I worked around it by catching the cookie from the header in the first response (before redirect) and calling the setCookie method directly hence it sends it with all subsequent requests

window.cordova.plugin.http.setCookie('/', cookieHeader, {})

monkeychops avatar Feb 19 '19 15:02 monkeychops

Hi ! Thanks for your work.. Any new about this todo ?

gatelli avatar Mar 27 '20 06:03 gatelli

Thanks to all for the solution! Not nice when the session cookie from the server is ignored that lightly...

one-github avatar Mar 08 '21 09:03 one-github