Skip to content

Commit

Permalink
fix: Remove isAUTFrame qualification from cross origin cookie check (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mschile authored Jul 29, 2022
1 parent 964ac37 commit 45ec63d
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 137 deletions.
284 changes: 154 additions & 130 deletions packages/driver/cypress/e2e/e2e/origin/commands/cookies.cy.ts
Original file line number Diff line number Diff line change
@@ -1,176 +1,200 @@
import { findCrossOriginLogs } from '../../../../support/utils'

context('cy.origin cookies', () => {
beforeEach(() => {
cy.visit('/fixtures/primary-origin.html')
cy.get('a[data-cy="cross-origin-secondary-link"]').click()
})
describe('cy.origin cookies', () => {
context('client side', () => {
beforeEach(() => {
cy.visit('/fixtures/primary-origin.html')
cy.get('a[data-cy="cross-origin-secondary-link"]').click()
})

it('.getCookie(), .getCookies(), and .setCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')
it('.getCookie(), .getCookies(), and .setCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')

cy.setCookie('foo', 'bar')
cy.setCookie('foo', 'bar')

cy.getCookie('foo').should('have.property', 'value', 'bar')
cy.getCookies().should('have.length', 1)
cy.getCookie('foo').should('have.property', 'value', 'bar')
cy.getCookies().should('have.length', 1)
})
})
})

it('.clearCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.getCookie('foo').should('not.be.null')
cy.clearCookie('foo')
cy.getCookie('foo').should('be.null')
it('.clearCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.getCookie('foo').should('not.be.null')
cy.clearCookie('foo')
cy.getCookie('foo').should('be.null')
})
})
})

it('.clearCookies()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.setCookie('faz', 'baz')
it('.clearCookies()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.setCookie('faz', 'baz')

cy.getCookies().should('have.length', 2)
cy.clearCookies()
cy.getCookies().should('be.empty')
cy.getCookies().should('have.length', 2)
cy.clearCookies()
cy.getCookies().should('be.empty')
})
})
})

context('#consoleProps', () => {
const { _ } = Cypress
let logs: Map<string, any>
context('#consoleProps', () => {
const { _ } = Cypress
let logs: Map<string, any>

beforeEach(() => {
logs = new Map()
beforeEach(() => {
logs = new Map()

cy.on('log:changed', (attrs, log) => {
logs.set(attrs.id, log)
cy.on('log:changed', (attrs, log) => {
logs.set(attrs.id, log)
})
})
})

it('.getCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')
cy.setCookie('foo', 'bar')
cy.getCookie('foo')
})
it('.getCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')
cy.setCookie('foo', 'bar')
cy.getCookie('foo')
})

cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('getCookie', logs, 'foobar.com')

expect(consoleProps.Command).to.equal('getCookie')
expect(consoleProps.Yielded).to.have.property('domain').that.includes('foobar.com')
expect(consoleProps.Yielded).to.have.property('expiry').that.is.a('number')
expect(consoleProps.Yielded).to.have.property('httpOnly').that.equals(false)
expect(consoleProps.Yielded).to.have.property('secure').that.equals(false)
expect(consoleProps.Yielded).to.have.property('name').that.equals('foo')
expect(consoleProps.Yielded).to.have.property('value').that.equals('bar')
expect(consoleProps.Yielded).to.have.property('path').that.is.a('string')
cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('getCookie', logs, 'foobar.com')

expect(consoleProps.Command).to.equal('getCookie')
expect(consoleProps.Yielded).to.have.property('domain').that.includes('foobar.com')
expect(consoleProps.Yielded).to.have.property('expiry').that.is.a('number')
expect(consoleProps.Yielded).to.have.property('httpOnly').that.equals(false)
expect(consoleProps.Yielded).to.have.property('secure').that.equals(false)
expect(consoleProps.Yielded).to.have.property('name').that.equals('foo')
expect(consoleProps.Yielded).to.have.property('value').that.equals('bar')
expect(consoleProps.Yielded).to.have.property('path').that.is.a('string')
})
})
})

it('.getCookies()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')
it('.getCookies()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')

cy.setCookie('foo', 'bar')
cy.getCookies()
})
cy.setCookie('foo', 'bar')
cy.getCookies()
})

cy.shouldWithTimeout(() => {
cy.shouldWithTimeout(() => {
// get the last 'getCookies' command, which is the one we care about for this test
const allGetCookieLogs = findCrossOriginLogs('getCookies', logs, 'foobar.com')
const allGetCookieLogs = findCrossOriginLogs('getCookies', logs, 'foobar.com')

const { consoleProps } = allGetCookieLogs.pop() as any
const { consoleProps } = allGetCookieLogs.pop() as any

expect(consoleProps.Command).to.equal('getCookies')
expect(consoleProps['Num Cookies']).to.equal(1)
expect(consoleProps.Command).to.equal('getCookies')
expect(consoleProps['Num Cookies']).to.equal(1)

// can't exactly assert on length() as this is a array proxy object
expect(consoleProps.Yielded.length).to.equal(1)
expect(consoleProps.Yielded[0]).to.have.property('expiry').that.is.a('number')
expect(consoleProps.Yielded[0]).to.have.property('httpOnly').that.equals(false)
expect(consoleProps.Yielded[0]).to.have.property('secure').that.equals(false)
expect(consoleProps.Yielded[0]).to.have.property('name').that.equals('foo')
expect(consoleProps.Yielded[0]).to.have.property('value').that.equals('bar')
expect(consoleProps.Yielded[0]).to.have.property('path').that.is.a('string')
// can't exactly assert on length() as this is a array proxy object
expect(consoleProps.Yielded.length).to.equal(1)
expect(consoleProps.Yielded[0]).to.have.property('expiry').that.is.a('number')
expect(consoleProps.Yielded[0]).to.have.property('httpOnly').that.equals(false)
expect(consoleProps.Yielded[0]).to.have.property('secure').that.equals(false)
expect(consoleProps.Yielded[0]).to.have.property('name').that.equals('foo')
expect(consoleProps.Yielded[0]).to.have.property('value').that.equals('bar')
expect(consoleProps.Yielded[0]).to.have.property('path').that.is.a('string')
})
})
})

it('.setCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')
it('.setCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.getCookies().should('be.empty')

cy.setCookie('foo', 'bar')
})
cy.setCookie('foo', 'bar')
})

cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('setCookie', logs, 'foobar.com')

expect(consoleProps.Command).to.equal('setCookie')
expect(consoleProps.Yielded).to.have.property('domain').that.includes('foobar.com')
expect(consoleProps.Yielded).to.have.property('expiry').that.is.a('number')
expect(consoleProps.Yielded).to.have.property('httpOnly').that.equals(false)
expect(consoleProps.Yielded).to.have.property('secure').that.equals(false)
expect(consoleProps.Yielded).to.have.property('name').that.equals('foo')
expect(consoleProps.Yielded).to.have.property('value').that.equals('bar')
expect(consoleProps.Yielded).to.have.property('path').that.is.a('string')
cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('setCookie', logs, 'foobar.com')

expect(consoleProps.Command).to.equal('setCookie')
expect(consoleProps.Yielded).to.have.property('domain').that.includes('foobar.com')
expect(consoleProps.Yielded).to.have.property('expiry').that.is.a('number')
expect(consoleProps.Yielded).to.have.property('httpOnly').that.equals(false)
expect(consoleProps.Yielded).to.have.property('secure').that.equals(false)
expect(consoleProps.Yielded).to.have.property('name').that.equals('foo')
expect(consoleProps.Yielded).to.have.property('value').that.equals('bar')
expect(consoleProps.Yielded).to.have.property('path').that.is.a('string')
})
})
})

it('.clearCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.getCookie('foo').should('not.be.null')
cy.clearCookie('foo')
})
it('.clearCookie()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.getCookie('foo').should('not.be.null')
cy.clearCookie('foo')
})

cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('clearCookie', logs, 'foobar.com')

expect(consoleProps.Command).to.equal('clearCookie')
expect(consoleProps.Yielded).to.equal('null')
expect(consoleProps['Cleared Cookie']).to.have.property('domain').that.includes('foobar.com')
expect(consoleProps['Cleared Cookie']).to.have.property('expiry').that.is.a('number')
expect(consoleProps['Cleared Cookie']).to.have.property('httpOnly').that.equals(false)
expect(consoleProps['Cleared Cookie']).to.have.property('secure').that.equals(false)
expect(consoleProps['Cleared Cookie']).to.have.property('name').that.equals('foo')
expect(consoleProps['Cleared Cookie']).to.have.property('value').that.equals('bar')
expect(consoleProps['Cleared Cookie']).to.have.property('path').that.is.a('string')
cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('clearCookie', logs, 'foobar.com')

expect(consoleProps.Command).to.equal('clearCookie')
expect(consoleProps.Yielded).to.equal('null')
expect(consoleProps['Cleared Cookie']).to.have.property('domain').that.includes('foobar.com')
expect(consoleProps['Cleared Cookie']).to.have.property('expiry').that.is.a('number')
expect(consoleProps['Cleared Cookie']).to.have.property('httpOnly').that.equals(false)
expect(consoleProps['Cleared Cookie']).to.have.property('secure').that.equals(false)
expect(consoleProps['Cleared Cookie']).to.have.property('name').that.equals('foo')
expect(consoleProps['Cleared Cookie']).to.have.property('value').that.equals('bar')
expect(consoleProps['Cleared Cookie']).to.have.property('path').that.is.a('string')
})
})
})

it('.clearCookies()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.setCookie('faz', 'baz')
it('.clearCookies()', () => {
cy.origin('http://foobar.com:3500', () => {
cy.setCookie('foo', 'bar')
cy.setCookie('faz', 'baz')

cy.getCookies().should('have.length', 2)
cy.clearCookies()
})
cy.getCookies().should('have.length', 2)
cy.clearCookies()
})

cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('clearCookies', logs, 'foobar.com')

cy.shouldWithTimeout(() => {
const { consoleProps } = findCrossOriginLogs('clearCookies', logs, 'foobar.com')
expect(consoleProps.Command).to.equal('clearCookies')
expect(consoleProps['Num Cookies']).to.equal(2)

expect(consoleProps.Command).to.equal('clearCookies')
expect(consoleProps['Num Cookies']).to.equal(2)
expect(consoleProps.Yielded).to.equal('null')

expect(consoleProps.Yielded).to.equal('null')
expect(consoleProps['Cleared Cookies'].length).to.equal(2)

expect(consoleProps['Cleared Cookies'].length).to.equal(2)
expect(consoleProps['Cleared Cookies'][0]).to.have.property('name').that.equals('foo')
expect(consoleProps['Cleared Cookies'][0]).to.have.property('value').that.equals('bar')

expect(consoleProps['Cleared Cookies'][0]).to.have.property('name').that.equals('foo')
expect(consoleProps['Cleared Cookies'][0]).to.have.property('value').that.equals('bar')
expect(consoleProps['Cleared Cookies'][1]).to.have.property('name').that.equals('faz')
expect(consoleProps['Cleared Cookies'][1]).to.have.property('value').that.equals('baz')

expect(consoleProps['Cleared Cookies'][1]).to.have.property('name').that.equals('faz')
expect(consoleProps['Cleared Cookies'][1]).to.have.property('value').that.equals('baz')
_.forEach(consoleProps['Cleared Cookies'], (clearedCookie) => {
expect(clearedCookie).to.have.property('httpOnly').that.equals(false)
expect(clearedCookie).to.have.property('secure').that.equals(false)
expect(clearedCookie).to.have.property('path').that.is.a('string')
})
})
})
})
})

context('server side', () => {
it('supports Set-Cookie response header through fetch request', () => {
cy.intercept('/dump-headers').as('headers')

_.forEach(consoleProps['Cleared Cookies'], (clearedCookie) => {
expect(clearedCookie).to.have.property('httpOnly').that.equals(false)
expect(clearedCookie).to.have.property('secure').that.equals(false)
expect(clearedCookie).to.have.property('path').that.is.a('string')
cy.origin('http://www.foobar.com:3500', () => {
cy.visit('/')
cy.window().then((win) => {
return cy.wrap(win.fetch('/set-cookie?cookie=foo=bar;'))
})

cy.window().then((win) => {
win.location.href = 'http://www.foobar.com:3500/dump-headers'
})

cy.wait('@headers')

cy.contains('"cookie":"foo=bar"')
cy.getCookie('foo').its('value').should('equal', 'bar')
})
})
})
Expand Down
8 changes: 8 additions & 0 deletions packages/driver/cypress/plugins/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,14 @@ const createApp = (port) => {
res.send(`<html><body><h1>Welcome, ${user}!</h1></body></html>`)
})

app.get('/set-cookie', (req, res) => {
const { cookie } = req.query

res
.append('Set-Cookie', cookie)
.sendStatus(200)
})

let _var = ''

app.get('/set-var', (req, res) => {
Expand Down
10 changes: 4 additions & 6 deletions packages/proxy/lib/http/response-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,14 +400,12 @@ const MaybePreventCaching: ResponseMiddleware = function () {
const checkIfNeedsCrossOriginHandling = (ctx: HttpMiddlewareThis<ResponseMiddlewareProps>) => {
const currentAUTUrl = ctx.getAUTUrl()

// A cookie needs cross origin handling if it's an AUT request and
// either the request itself is cross-origin or the origins between
// requests don't match, since the browser won't set them in that
// case and if it's secondary-origin -> primary-origin, we don't
// recognize the request as cross-origin
// A cookie needs cross origin handling if the request itself is
// cross-origin or the origins between requests don't match,
// since the browser won't set them in that case and if it's
// secondary-origin -> primary-origin, we don't recognize the request as cross-origin
return (
ctx.config.experimentalSessionAndOrigin
&& ctx.req.isAUTFrame
&& (
(currentAUTUrl && !cors.urlOriginsMatch(currentAUTUrl, ctx.req.proxiedUrl))
|| !ctx.remoteStates.isPrimaryOrigin(ctx.req.proxiedUrl)
Expand Down
1 change: 0 additions & 1 deletion packages/proxy/test/unit/http/response-middleware.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,6 @@ describe('http/response-middleware', function () {
req: {
proxiedUrl: 'http://www.foobar.com/login',
headers: {},
isAUTFrame: true,
...props.req,
},
incomingResStream: {
Expand Down

4 comments on commit 45ec63d

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 45ec63d Jul 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/linux-x64/develop-45ec63dbcdb37f3a27324373c4b55d592932ae5a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 45ec63d Jul 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/darwin-arm64/develop-45ec63dbcdb37f3a27324373c4b55d592932ae5a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 45ec63d Jul 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/linux-arm64/develop-45ec63dbcdb37f3a27324373c4b55d592932ae5a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 45ec63d Jul 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/win32-x64/develop-45ec63dbcdb37f3a27324373c4b55d592932ae5a/cypress.tgz

Please sign in to comment.