-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
fix: duplicate and expired cookies #25761
Changes from all commits
d13c0f6
2b97638
9b6db60
3a05675
27c6076
70b709c
91c3c7c
dcdb11c
844c831
bd62d4f
38a65a6
7b90551
4a9cfb5
8927a3c
864baff
868c52c
0d0dbd6
f545ab1
5b0a9bf
ea31a02
b93ce75
48b9550
2df76b7
3431437
c1d8360
22c46f3
fd23fb1
913e317
331dd69
17de188
c3c1088
d44b202
173bda0
dca9773
86a8cd8
ea29a59
4352ef5
a67c06d
dff7db1
6106b1f
0b9e237
95589fd
ef902f1
d5a2876
3a676ab
8567812
3ec78f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
// FIXME: currently cookies aren't cleared properly in headless mode with webkit between tests, as the below tests (excluding cy.origin) pass headfully locally. | ||
describe('misc cookie tests', { browser: '!webkit' }, () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason we can add these tests to the existing e2e/cookie_behavior spec? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. main reason is just how large the spec already is. I almost think we should rename it, just not sold on something yet There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I'd rather have one place to look for tests related to a topic so it's easier to see if we have coverage rather than searching multiple files 🤷🏻♀️ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, but considering how flaky that spec currently is, I don't want real issues to get lost in the noise. Not a great reason, but I also think the two specs are accomplishing two different things. This one is more for expiry and duplication bug fixes, and the cookie behavior tests are mostly checking attachment for xhr/fetch requests. Would it be better to break the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe group the various cookie tests under a cookie directory? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm gonna have a follow up to this PR that is going to address types, as well as refactoring some of these tests and addressing some of the cookie behavior flake |
||
// NOTE: For this test to work correctly, we need to have a FQDN, not localhost (www.foobar.com). | ||
// FIXES: https://github.com/cypress-io/cypress/issues/25174 (cookies are duplicated with prepended dot (.)) | ||
it('does not duplicate cookies with a prepended dot for cookies that are stored inside the server side cookie jar (host only)', () => { | ||
cy.visit('https://www.foobar.com:3502/fixtures/trigger-cross-origin-redirect-to-self.html') | ||
|
||
// does a 302 redirect back to www.foobar.com primary-origin page, but sets a sameSite=None cookie | ||
cy.get('[data-cy="cookie-cross-origin-redirects-host-only"]').click() | ||
|
||
cy.getCookies({ domain: 'www.foobar.com' }).then((cookies) => { | ||
expect(cookies).to.have.length(1) | ||
|
||
const singleCookie = cookies[0] | ||
|
||
expect(singleCookie).to.have.property('name', 'foo') | ||
expect(singleCookie).to.have.property('value', 'bar') | ||
expect(singleCookie).to.have.property('domain', 'www.foobar.com') | ||
}) | ||
}) | ||
|
||
it('does not duplicate cookies with a prepended dot for cookies that are stored inside the server side cookie jar (non-host only)', () => { | ||
cy.visit('https://www.foobar.com:3502/fixtures/trigger-cross-origin-redirect-to-self.html') | ||
|
||
// does a 302 redirect back to www.foobar.com primary-origin page, but sets a sameSite=None cookie | ||
cy.get('[data-cy="cookie-cross-origin-redirects"]').click() | ||
|
||
cy.getCookies({ domain: 'www.foobar.com' }).then((cookies) => { | ||
expect(cookies).to.have.length(1) | ||
|
||
const singleCookie = cookies[0] | ||
|
||
expect(singleCookie).to.have.property('name', 'foo') | ||
expect(singleCookie).to.have.property('value', 'bar') | ||
expect(singleCookie).to.have.property('domain', '.www.foobar.com') | ||
}) | ||
}) | ||
|
||
/** | ||
* FIXES: | ||
* https://github.com/cypress-io/cypress/issues/25205 (cookies set with expired time with value deleted show up as set with value deleted) | ||
* https://github.com/cypress-io/cypress/issues/25495 (session cookies set with expired time with value deleted show up as set with value deleted) | ||
* https://github.com/cypress-io/cypress/issues/25148 (cannot log into azure, shows cookies are disabled/blocked) | ||
*/ | ||
describe('expiring cookies', { browser: '!webkit' }, () => { | ||
before(() => { | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
window.makeRequest = Cypress.require('../../../support/utils').makeRequestForCookieBehaviorTests | ||
}) | ||
}) | ||
|
||
describe('removes cookies that are set with an expired expiry time from the server side cookie jar / browser via CDP', () => { | ||
it('works with Max-Age=0', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=bar; Domain=.foobar.com;`)) | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=deleted; Domain=.foobar.com; Max-Age=0;`)) | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
|
||
it('works with expires=Thu, 01-Jan-1970 00:00:01 GMT', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=bar; Domain=.foobar.com;`)) | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=deleted; Domain=.foobar.com; expires=Thu, 01-Jan-1970 00:00:01 GMT;`)) | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
|
||
it('works with expires=Tues, 01-Jan-1980 00:00:01 GMT', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=bar; Domain=.foobar.com;`)) | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=deleted; Domain=.foobar.com; expires=Tues, 01-Jan-1980 00:00:01 GMT; Max-Age=0;`)) | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
|
||
it('work with expires=Thu, 01-Jan-1970 00:00:01 GMT and Max-Age=0', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=bar; Domain=.foobar.com;`)) | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
return cy.wrap(window.makeRequest(win, `/set-cookie?cookie=foo=deleted; Domain=.foobar.com; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0;`)) | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('removes cookies that are set with an expired expiry time from the document.cookie patch / browser via CDP', () => { | ||
it('works with Max-Age=0', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=bar' | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0;' | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
|
||
it('works with expires=Thu, 01-Jan-1970 00:00:01 GMT', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=bar' | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=deleted; Max-Age=0' | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
|
||
it('works with expires=Tues, 01-Jan-1980 00:00:01 GMT', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=bar' | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=deleted; expires=Tues, 01-Jan-1980 00:00:01 GMT' | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
|
||
it('expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0', () => { | ||
cy.visit(`https://www.foobar.com:3502/fixtures/primary-origin.html`) | ||
|
||
cy.visit(`https://app.foobar.com:3503/fixtures/secondary-origin.html`) | ||
cy.origin(`https://app.foobar.com:3503`, () => { | ||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=bar' | ||
}) | ||
|
||
cy.getCookie('foo').its('value').should('eq', 'bar') | ||
|
||
cy.window().then((win) => { | ||
win.document.cookie = 'foo=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0' | ||
}) | ||
|
||
cy.getCookie('foo').should('eq', null) | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
</head> | ||
<body> | ||
<a data-cy="cookie-cross-origin-redirects-host-only">Trigger Cross Origin Redirect Loop that sets host only cookie</a> | ||
<a data-cy="cookie-cross-origin-redirects">Trigger Cross Origin Redirect Loop that sets non host only cookie</a> | ||
<script> | ||
function setHref (dataCy, redirect, cookie) { | ||
const redirectEncoded = encodeURIComponent(redirect) | ||
const cookieEncoded = encodeURIComponent(cookie) | ||
|
||
document.querySelector(`[data-cy="${dataCy}"]`).href = ( | ||
`/set-same-site-none-cookie-on-redirect?redirect=${redirectEncoded}&cookie=${cookieEncoded}` | ||
) | ||
} | ||
setHref('cookie-cross-origin-redirects-host-only', `${window.location.origin}/fixtures/primary-origin.html`, 'foo=bar') | ||
setHref('cookie-cross-origin-redirects', `${window.location.origin}/fixtures/primary-origin.html`, `foo=bar; domain=.${window.location.hostname}`) | ||
</script> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to change the logic here for the duplicate cookie work to apply the actual cookie domain or default
hostOnly
domain to the set cookie here. This is to make sure the cookie doesn't double up with a non host only equivalent in CDP. This should be fine for two reasons: