cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.42k stars 3.14k forks source link

third party cookies are not added to web requests in restored `cy.session()` #28691

Open moosbruggerj opened 5 months ago

moosbruggerj commented 5 months ago

Current behavior

Cookies belonging to third party apps are not added to requests after a session restore. However, inspecting the session storage with Cypress.session.getCurrentSessionData() lists all expected cookies domains.

Tested in Firefox v121 and chromium v120.

Example session data from repro below for the `restore` session ```json { "id": "restore", "localStorage": [], "sessionStorage": [], "cookies": [ { "domain": "auth.local", "httpOnly": false, "hostOnly": true, "name": "sessionid", "path": "/", "sameSite": "lax", "secure": false, "value": "1" } ] } ```
Example session data from repro below for the `login` session ```json { "id": "login", "cookies": [ { "domain": "auth.local", "httpOnly": false, "hostOnly": true, "name": "sessionid", "path": "/", "sameSite": "lax", "secure": false, "value": "6" } ], "localStorage": [], "sessionStorage": [] } ```

The cypress tests run against web.local which authenticates against auth.local. The actual domain names don't seem to be important, as long as they are different.

Request headers of logout request with restored session ``` GET /logout HTTP/1.1 Host: auth.local:8002 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://web.local:8001/ Connection: keep-alive Upgrade-Insecure-Requests: 1 X-Cypress-Is-AUT-Frame: true ```

Desired behavior

Cookies are always added to web requests for other domains.

Test code to reproduce

Spec file login.cy.ts

The can login test succeeds, as expected. The cannot restore test fails, because /logout returns a 401 response instead of the redirection to the web server.

const authServer = "auth.local";

function login(id: string) {
  cy.session(id, () => {
    cy.visit("/");
    cy.intercept("/").as("home");
    cy.contains("Login").click();
    cy.wait("@home");
    cy.getCookie("sessionid", { domain: authServer })
      .should("exist")
      .should("not.eq", "");

  });
}

function logout() {
  cy.visit("/");

  cy.intercept("/").as("home");
  cy.contains("Logout").click();
  cy.wait("@home");
  cy.getCookie("sessionid", { domain: authServer })
    .its("value")
    .should("equal", "");
}

beforeEach(() => {
  Cypress.session.clearAllSavedSessions();
});

it("can login", () => {
  login("login");
  logout();
});

it("cannot restore", () => {
  login("restore");
  login("restore");
  logout();
});

Web server

Web server is running on port 8001 with hostname web.local

web server code `web.js` ```javascript import http from "http"; const host = "web.local"; const port = 8001; const authServer = "http://auth.local:8002"; const requestListener = function (req, res) { res.setHeader("Content-Type", "text/html"); res.writeHead(200); res.end( `Login
Logout`, ); }; const server = http.createServer(requestListener); server.listen(port, host, () => { console.log("server is running"); }); ```

Auth server

Authentication server is running on port 8002 with hostname auth.local.

Auth server code `auth.js` ```js import http from "http"; const host = "auth.local"; const port = 8002; const webServer = "http://web.local:8001"; let sessid = 0; const requestListener = function (req, res) { switch (req.url) { case "/login": login(req, res); break; case "/logout": logout(req, res); break; default: res.writeHead(404); res.end(); break; } }; function login(req, res) { console.log("login"); res.setHeader("Location", webServer); res.setHeader("Set-Cookie", `sessionid=${sessid++}`); res.writeHead(302); res.end(); } function logout(req, res) { const cookies = req.headersDistinct["cookie"] ?? []; console.log("logout"); console.log(cookies); res.setHeader("Location", webServer); res.setHeader("Set-Cookie", "sessionid="); if (cookies.some((c) => c.indexOf("sessionid=") > -1)) { res.writeHead(302); } else { res.writeHead(401); } res.end(); } const server = http.createServer(requestListener); server.listen(port, host, () => { console.log("server is running"); }); ```

Environment

The auth and the web server need to be on different domains. I used hosts file redirection.

# /etc/hosts
127.0.0.1 web.local
127.0.0.1 auth.local
// cypress.config.ts
import { defineConfig } from "cypress";

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // implement node event listeners here
    },
    baseUrl: "http://web.local:8001/",
  },
});

Cypress Version

13.6.2

Node version

v21.4.0

Operating System

Ubuntu 20.04

Debug Logs

https://pastebin.com/LpQHTG15

Other

No response

senpl commented 1 month ago

Can U provide simplified example to run that reproduce that error. Is it still present in latest version ???