Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cy.request doesn't set cookie with specific domain #3221

Closed
seromenho opened this issue Jan 25, 2019 · 21 comments
Closed

cy.request doesn't set cookie with specific domain #3221

seromenho opened this issue Jan 25, 2019 · 21 comments
Assignees
Labels
topic: cookies 🍪 type: regression A bug that didn't appear until a specific Cy version release

Comments

@seromenho
Copy link

seromenho commented Jan 25, 2019

Current behavior:

baseURLis set to: http://localhost:3000
cy.request() is not setting cookies that comes with a domain.

screenshot from 2019-01-25 11-13-18

Desired behavior:

cy.request() should set cookies with specific domain.

Steps to reproduce: (app code and test code)

describe('Cookie', () => {
  Cypress.Cookies.debug(true);

  it('SHOULD set the cookie if it have domain', () => {
    cy.request({
      method: 'POST',
      url: 'http://localhost:3000/cookie-with-domain'
    })
      .then(()=> {
        cy.getCookie('domain-cookie')
          .should('have.property', 'value', '1');
      });
  });

  it('Does set the cookie', () => {
    cy.request({
      method: 'POST',
      url: 'http://localhost:3000/cookie-without-domain'
    })
      .then(()=> {
        cy.getCookie('cookie')
          .should('have.property', 'value', '1');
      });
  });

  it('Works fine on both', () => {
    cy.visit('http://localhost:3000/cookie-with-domain');
    cy.visit('http://localhost:3000/cookie-without-domain');
    cy.getCookie('domain-cookie')
      .should('have.property', 'value', '1');
    cy.getCookie('cookie')
      .should('have.property', 'value', '1');
  });
});

Using expressjs on the server and this:

  app.all('/cookie-with-domain', (req, res)=>{
    res.cookie('domain-cookie',1, { maxAge: 900000, httpOnly: true, domain: 'localhost'});
    res.send('Hello!');
  });

  app.all('/cookie-without-domain', (req, res)=>{
    res.cookie('cookie',1, { maxAge: 900000, httpOnly: true});
    res.send('Hello!');
  });

Versions

Cypress: 3.1.1
OS: Ubuntu 18.04
Browser: Chrome 71

@kuceb
Copy link
Contributor

kuceb commented Jan 25, 2019

@seromenho you are not on a domain when you used cy.getCookie(), since you never used cy.visit() in that test.

can you try adding cy.visit('/') above the calls to cy.request?

@kuceb kuceb added the stage: needs information Not enough info to reproduce the issue label Jan 25, 2019
@seromenho
Copy link
Author

@bkucera I found this because on my tests when I was visiting a page the cookie was not set.
But still you can see that the second test passes and I've also never used cy.visit() on that test.
I've added this to the tests and theres new screen shot and tests:
screenshot from 2019-01-25 16-32-07

describe('Cookie', () => {
  Cypress.Cookies.debug(true);

  it('SHOULD set the cookie if it have domain', () => {
    cy.request({
      method: 'POST',
      url: 'http://localhost:3000/cookie-with-domain'
    })
      .then(()=> {
        cy.visit('http://localhost:3000/');
        cy.getCookie('domain-cookie')
          .should('have.property', 'value', '1');
      });
  });

  it('Does set the cookie', () => {
    cy.request({
      method: 'POST',
      url: 'http://localhost:3000/cookie-without-domain'
    })
      .then(()=> {
        cy.visit('http://localhost:3000/');
        cy.getCookie('cookie')
          .should('have.property', 'value', '1');
      });
  });

  it('Works fine on both', () => {
    cy.visit('http://localhost:3000/cookie-with-domain');
    cy.visit('http://localhost:3000/cookie-without-domain');
    cy.getCookie('domain-cookie')
      .should('have.property', 'value', '1');
    cy.getCookie('cookie')
      .should('have.property', 'value', '1');
  });
});

@kuceb
Copy link
Contributor

kuceb commented Jan 28, 2019

@seromenho can you try running those tests independently of one another? you can put a .only on them like this:

it.only('some test', ()=>{ ...

also can you show the cookie headers on each request?

thanks for the screenshots

@seromenho
Copy link
Author

@bkucera same result.

@kuceb
Copy link
Contributor

kuceb commented Jan 29, 2019

can you show the cookie headers on each request?

i.e the "domain-cookie" vs the cookie without domain? That way we can hopefully reproduce this

@seromenho
Copy link
Author

@bkucera
1st

{
  "Request Body": null,
  "Request Headers": {
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
    "accept": "*/*",
    "accept-encoding": "gzip, deflate",
    "content-length": 0
  },
  "Request URL": "http://localhost:3033/cookie-with-domain",
  "Response Body": "Hello!",
  "Response Headers": {
    "x-powered-by": "Express",
    "access-control-allow-origin": "http://localhost:3033",
    "access-control-allow-credentials": "true",
    "set-cookie": [
      "domain-cookie=1; Max-Age=900; Domain=localhost; Path=/; Expires=Tue, 29 Jan 2019 16:18:52 GMT; HttpOnly"
    ],
    "content-type": "text/html; charset=utf-8",
    "content-length": "6",
    "etag": "W/\"6-aTQsXDnlrl8Ad67MMsD4GBH7gZM\"",
    "date": "Tue, 29 Jan 2019 16:03:52 GMT",
    "connection": "close",
    "vary": "Accept-Encoding"
  },
  "Response Status": 200
}

2nd:

{
  "Request Body": null,
  "Request Headers": {
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
    "accept": "*/*",
    "accept-encoding": "gzip, deflate",
    "content-length": 0
  },
  "Request URL": "http://localhost:3033/cookie-without-domain",
  "Response Body": "Hello!",
  "Response Headers": {
    "x-powered-by": "Express",
    "access-control-allow-origin": "http://localhost:3033",
    "access-control-allow-credentials": "true",
    "set-cookie": [
      "cookie=1; Max-Age=900; Path=/; Expires=Tue, 29 Jan 2019 16:22:41 GMT; HttpOnly"
    ],
    "content-type": "text/html; charset=utf-8",
    "content-length": "6",
    "etag": "W/\"6-aTQsXDnlrl8Ad67MMsD4GBH7gZM\"",
    "date": "Tue, 29 Jan 2019 16:07:41 GMT",
    "connection": "close",
    "vary": "Accept-Encoding"
  },
  "Response Status": 200
}

@kuceb kuceb added stage: investigating Someone from Cypress is looking into this and removed stage: needs information Not enough info to reproduce the issue labels Jan 29, 2019
@kuceb
Copy link
Contributor

kuceb commented Jan 29, 2019

thanks @seromenho, doesn't seem like a very high priority for us ATM, but I think this will get looked at along with #687

@jennifer-shehane jennifer-shehane added priority: low 🎗 stage: ready for work The issue is reproducible and in scope and removed stage: investigating Someone from Cypress is looking into this labels Jan 30, 2019
@TheOptimist
Copy link

TheOptimist commented Feb 4, 2019

For information, this issue appears to be complete killing my ability to use Cypress against our application (and appreciate that this could be a limitation due to how our app works).

During the tests we need to interact with our API as an Administrator to create specific organizations to isolate tests. Once that's done we shift to a specific tenant domain which responds correctly with a domain cookie in the response header. The tenant domain cookie isn't set, and we end up with unauthenticated errors.

I've tried working around this by parsing the set-cookie header and then setting a cookie with the following code (without any luck so far):

cy.setCookie(name, value, {options}).then( () => {  
  cy.getCookies();      // The new cookie are shown in the Cypress log  
  cy.request(somePath); // This call doesn't have the new cookie
})

I figured the above would work...but no luck yet.

@TheOptimist
Copy link

Put the use of the emotive "killing" down to a tough weekend banding my head against this. It's certainly made it tougher, and a little more long winded, but killing was a bit extreme.

To add something more constructive to the conversation, I have managed to work around this in my interaction with our backend API by ensuring that during a login call, we set the authorization token for a user, then force cy.request to use that with appropriate headers.

The final workaround is to set the cookie with JavaScript when the visit yields. It's not quite as the same as the domain part of the cookie isn't honoured but it does at least get us testing without having to login via the interface each time.

Keep up the good work! It's a pleasure working with Cypress, even with these frustrations :)

@rewop
Copy link

rewop commented Feb 13, 2019

It looks like I am facing the same problem. However to me it seems that the error only happen if Domain="localhost" is set. If the Domain= is present and set to something else cookies are set as expected.

Our work around is setting the cookie without domain

cy
    .request({
      url: `${backendHost}/api/v2/user`,
      method: 'POST',
      body: {
        email: `${uuid()}@test.ru`,
        ...details,
      },
      auth,
    })
    .then(response => {
      return cy.getCookie('session_id')
    })
    .then(({ headers, body }) => {
      const cookieHeader = headers['set-cookie'].map(cookie =>
        cookie.split('; ')[0].split('='),
      )[0];

      return cy.setCookie(cookieHeader[0], cookieHeader[1])
          .then(() => body);
    })

@seromenho
Copy link
Author

@rewop It doesn't seems to be only on localhost. Locally we are using custom domains and it doesn't work also. Domain on my sample was just for demo.
Your workaround of manually set the cookies works very well. We are doing that also for the time being.
Ty

@ianldgs
Copy link

ianldgs commented Apr 8, 2019

I can confirm that this happens not only with localhost but with any custom domains.
I was migrating tests to run on docker, and previously, the domain was lvh.me (a real domain, just has a DNS pointing at 127.0.0.1), which worked.

@TheRemjx01
Copy link

Any action to fix this yet? :(.

@jennifer-shehane
Copy link
Member

This issue is still in the 'ready for work' stage, which means no work has been done on this issue as of today, so we do not have an estimate on when this will be delivered.

@j-gurda
Copy link

j-gurda commented Jun 3, 2019

My workaround, which is similar to @rewop 's one:

Cypress.Commands.add('loginNoUi', (email, password) => {
    // Regular form POST
    cy.request({
        method: 'POST',
        form: true,
        followRedirect: false,
        url: '/login',
        body: {
            username: email,
            password: password
        }
    }).then((response) => {
        //Extract cookie value from response's "set-cookie" header.
        const token = response.headers['set-cookie'][0].replace('SM_SESSION=', '').split(';')[0];

        //Set the cookie explicitly
        cy.setCookie('SM_SESSION', token);

        // Attach 'Cookie' header manually and go to main page of application. It's possible to navigate everywhere from there.
        cy.visit('/', {headers: {'Cookie': `SM_SESSION=${token}`}});
    });
});

After that, I use the regular page navigation with a click() function and navigation works correctly.

In my opinion, there are two problems here:

  1. cy.request() does not set cookies automatically (login endpoint responds with HTTP 302 and cookie with domain name set)
  2. cy.visit() does not attach cookies automatically

I hope I saved someone hours of experimenting.

@TheMY3
Copy link

TheMY3 commented Jun 4, 2019

Same problem, but it happens only with .local domain for me and when I make a cookie accessible for all subdomains (.cypress.local) but when I set .cypress.biz (or any another domain) - all ok.
It started from 3.1.1 version and from this version I can't update Cypress.

I record gifs with small tests:

  1. Version 3.1.0 - all ok, I set 2 cookies an get 2 cookies.
    cypress-3 1 0

  2. Version 3.1.1+ (3.3.0) - I set 2 cookies an get 1 cookie, cookie with domain .cypress.local removed.
    cypress-3 3 0

Backend the same, I just type in /etc/hosts:

127.0.0.1 cypress.local cypress.biz

And tests was:

describe('Cookies bug', function() {
    Cypress.Cookies.debug(true)
    it('Domain .biz', function() {
        cy.visit('http://cypress.biz:8000/?page=set'); // set cookies
        cy.wait(2000); // just for me
        cy.visit('http://cypress.biz:8000/?page=get'); // get cookies
    })

    it('Domain .local', function() {
        cy.visit('http://cypress.local:8000/?page=set');
        cy.wait(2000);
        cy.visit('http://cypress.local:8000/?page=get');
    })
})

@j-gurda
Copy link

j-gurda commented Jun 4, 2019

@YaroslavMolchan domain name ending with ".local" may be the cause. In my case, I also use .local domain setup statically in /etc/hosts

@TheMY3
Copy link

TheMY3 commented Jun 5, 2019

@j-gurda its problem for me only if I set cookie for subdomains like .domain.local (starts from dot), now I create cookie only for current domain domain.local (without dot) and all works fine.

@jennifer-shehane
Copy link
Member

@YaroslavMolchan Thank you for narrowing this down to a specific version. Changes made in 3.1.1 involving cookies:

Fixed a bug where Cypress would error when a secure cookie flag was set and then expired from an HTTPS url without the subsequent secure flag. Due to the way Cypress was constructing the url, this would fail to actually remove the cookie. Fixes #1264, #1321, #1799.

This boils down to the changes made in this PR #2685 which I think boils down even further to this commit: b31782d

@jennifer-shehane jennifer-shehane added the type: regression A bug that didn't appear until a specific Cy version release label Jul 30, 2019
@ponsifiax
Copy link

Hello team,

Do you have any news about this regression?
Unfortunately, the workarounds are not the final solution.

Thanks for information.

@flotwig flotwig self-assigned this Dec 10, 2019
@flotwig
Copy link
Contributor

flotwig commented Dec 10, 2019

I just checked the reproducible example provided in the OP and it appears to be fixed starting with Cypress 3.5.0. Please upgrade your version of Cypress to the latest to get the fix for this issue.

@flotwig flotwig closed this as completed Dec 10, 2019
@jennifer-shehane jennifer-shehane removed the stage: ready for work The issue is reproducible and in scope label Feb 3, 2021
@cypress-io cypress-io locked as resolved and limited conversation to collaborators Feb 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
topic: cookies 🍪 type: regression A bug that didn't appear until a specific Cy version release
Projects
None yet
Development

No branches or pull requests