Bill Mayo wanted to run the Cypress single-sign-on example app but it was throwing an origin error.
Making the example work has nothing to do with the cy.origin()
command, here are the steps to run this example.
Updated link 5 Jan 2024
The link to this example has changed it's now https://github.com/cypress-io/cypress-example-recipes/tree/master/examples/logging-in__single-sign-on
Making it work
download the repo (entire examples repo) and install dependencies in the project root yarn
or npm i
.
The package.json
has a restriction on Node version in this section
"engines": {
"node": "^18.16.0"
},
but the current LTS version of Node is 20.10.0
, so if like me you have that version, delete that section of package.json
.
switch to the logging-in__single-sign-on
sub-folder and edit the scripts in package.json
the start
script doesn't seem to work, the auth server did not start (maybe a Windows issue)
add new scripts to start the app server and the auth server separately:
"scripts": {
...
"start:app:server": "node app_server.js --port 7074",
"start:auth:server": "node auth_server.js --port 7075",
run three terminal sessions, in each run
yarn start:app:server
yarn start:auth:server
yarn cypress:open
run the spec that is in this project, it completes and passes
The code for single-sign-on test example
Since the link may change again, here is the abbreviated test code
const _ = Cypress._
const url = require('url')
describe('Logging In - Single Sign on', function () {
Cypress.Commands.add('loginBySingleSignOn', (overrides = {}) => {
Cypress.log({name: 'loginBySingleSignOn'})
const options = {
method: 'POST',
url: 'http://auth.corp.com:7075/login',
qs: {
redirectTo: 'http://localhost:7074/set_token',
},
form: true,
body: {
username: 'jane.lane',
password: 'password123',
},
}
_.extend(options, overrides)
cy.request(options)
})
context('Use redirectTo and a session cookie to login', function () {
it('is 403 unauthorized without a session cookie', function () {
cy.visit('/dashboard')
cy.get('h3').should('contain', 'You are not logged in and cannot access this page')
cy.url().should('include', 'unauthorized')
})
it('can authenticate with cy.request', function () {
cy.getCookie('cypress-session-cookie').should('not.exist')
cy.loginBySingleSignOn().then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body).to.include('<h1>Welcome to the Dashboard!</h1>')
})
cy.getCookie('cypress-session-cookie').should('exist')
cy.visit('/dashboard')
cy.get('h1').should('contain', 'Welcome to the Dashboard')
})
})
context('Manually parse id_token and set on local storage to login', function () {
it('knows when there is no session token', function () {
cy.visit('/')
cy.get('#main').should('contain', 'No session token set!')
})
const responseToToken = (resp) => {
const uri = url.parse(resp.redirectedToUrl, true)
expect(uri.query).to.have.property('id_token')
return uri.query.id_token
}
it('can parse out id_token and set on local storage', function () {
cy.loginBySingleSignOn({ followRedirect: false })
.then(responseToToken)
.then((id_token) => {
cy.intercept('/config').as('getConfig')
cy.visit('/', {
onBeforeLoad (win) {
win.localStorage.setItem('id_token', id_token)
},
})
cy.wait('@getConfig')
.its('response.body')
.should('deep.eq', {foo: 'bar', some: 'config', loggedIn: true})
cy.get('#main')
.invoke('text')
.should((text) => {
const json = JSON.parse(text)
expect(json).to.deep.eq({foo: 'bar', some: 'config', loggedIn: true})
})
})
})
describe('Log in once for speed', () => {
before(function () {
cy.loginBySingleSignOn({ followRedirect: false })
.then(responseToToken)
.as('token') // saves under "this.token"
})
beforeEach(function () {
cy.on('window:before:load', (win) => {
win.localStorage.setItem('id_token', this.token)
})
})
it('opens page as logged in user', () => {
cy.visit('/')
cy.contains('"loggedIn":true')
})
it('config returns logged in: true', function () {
cy.intercept('/config', (req) => {
delete req.headers['if-none-match']
}).as('getConfig')
cy.visit('/')
cy.wait('@getConfig').then((xhr) => {
expect(xhr.request.headers, 'request includes token header')
.to.have.property('x-session-token', this.token)
expect(xhr.response.body, 'response body')
.to.deep.equal({foo: 'bar', loggedIn: true, some: 'config'})
})
})
})
}
)
})