Created
November 7, 2019 10:49
-
-
Save csuzw/845b589549b61d3a5fe18e49592e166f to your computer and use it in GitHub Desktop.
Azure AD Single Sign On with Cypress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This goes in cypress/plugins/index.js | |
const AzureAdSingleSignOn = require('./azure-ad-sso/plugin').AzureAdSingleSignOn | |
module.exports = (on, config) => { | |
on('task', {AzureAdSingleSignOn:AzureAdSingleSignOn}) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is an example of how you might use the plugin in your tests | |
describe('My spec', function() { | |
Cypress.Commands.add('setCookies', function () { | |
const options = { | |
username: Cypress.env('username'), | |
password: Cypress.env('password'), | |
loginUrl: Cypress.env('appUrl'), | |
postLoginSelector: '#myselector', | |
headless: true, | |
logs: false | |
} | |
cy.task('AzureAdSingleSignOn', options).then(result => { | |
cy.clearCookies() | |
result.cookies.forEach(cookie => { | |
cy.setCookie(cookie.name, cookie.value, { | |
domain: cookie.domain, | |
expiry: cookie.expires, | |
httpOnly: cookie.httpOnly, | |
path: cookie.path, | |
secure: cookie.secure | |
}) | |
Cypress.Cookies.preserveOnce(cookie.name) | |
}) | |
}) | |
}) | |
before(function() { | |
cy.setCookies(); | |
}) | |
it('Visits the site as logged in user', function() { | |
cy.visit(Cypress.env('appUrl')); | |
cy.contains(`Hello, ${Cypress.env('username')}!`) | |
}) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// I put this in cypress/plugins/azure-ad-sso directory | |
'use strict' | |
const puppeteer = require('puppeteer') | |
/** | |
* | |
* @param {options.username} string username | |
* @param {options.password} string password | |
* @param {options.loginUrl} string password | |
* @param {options.postLoginSelector} string a selector on the app's post-login return page to assert that login is successful | |
* @param {options.headless} boolean launch puppeteer in headless more or not | |
* @param {options.logs} boolean whether to log cookies and other metadata to console | |
* @param {options.getAllBrowserCookies} boolean whether to get all browser cookies instead of just for the loginUrl | |
*/ | |
module.exports.AzureAdSingleSignOn = async function AzureAdSingleSignOn(options = {}) { | |
validateOptions(options) | |
const browser = await puppeteer.launch({ headless: !!options.headless }) | |
const page = await browser.newPage() | |
await page.goto(options.loginUrl) | |
await typeUsername({ page, options }) | |
await typePassword({ page, options }) | |
const cookies = await getCookies({ page, options }) | |
await finalizeSession({ page, browser, options }) | |
return { | |
cookies | |
} | |
} | |
function validateOptions(options) { | |
if (!options.username || !options.password) { | |
throw new Error('Username or Password missing for login') | |
} | |
if (!options.loginUrl) { | |
throw new Error('Login Url missing') | |
} | |
if (!options.postLoginSelector) { | |
throw new Error('Post login selector missing') | |
} | |
} | |
async function typeUsername({ page, options } = {}) { | |
await page.waitForSelector('input[name=loginfmt]:not(.moveOffScreen)', { visible: true, delay: 10000 }) | |
await page.type('input[name=loginfmt]', options.username, { delay: 50 }) | |
await page.click('input[type=submit]') | |
} | |
async function typePassword({ page, options } = {}) { | |
await page.waitForSelector('input[name=Password]:not(.moveOffScreen),input[name=passwd]:not(.moveOffScreen)', { visible: true, delay: 10000 }) | |
await page.type('input[name=passwd]', options.password, { delay: 50 }) | |
await page.click('input[type=submit]') | |
} | |
async function getCookies({ page, options } = {}) { | |
await page.waitForSelector(options.postLoginSelector, { visible: true, delay: 10000 }) | |
const cookies = options.getAllBrowserCookies | |
? await getCookiesForAllDomains(page) | |
: await page.cookies(options.loginUrl) | |
if (options.logs) { | |
console.log(cookies) | |
} | |
return cookies | |
} | |
async function getCookiesForAllDomains(page) { | |
const cookies = await page._client.send('Network.getAllCookies', {}) | |
return cookies.cookies | |
} | |
async function finalizeSession({ page, browser, options } = {}) { | |
await browser.close() | |
} |
cy.task("azureSingleSignOn", options, { timeout: 200000 }).then(({ cookies }) => {
cy.log(cookies);
console.log(cookies);
cookies.forEach((cookie) => {
if (cookie) {
cy.setCookie(cookie.name, cookie.value, {
domain: cookie.domain,
expiry: cookie.expires,
httpOnly: cookie.httpOnly,
path: cookie.path,
secure: cookie.secure,
sameSite: "lax",
});
Cypress.Cookies.defaults({ preserve: cookie.name });
}
});
Why after set cookies and preserve that, When I tried cy.visit("/") its again going to sso azure login page? When I debug I saw cookies are remove automatically. What is the issue?
Able to run. connect puppeteer method. Launch method giving cookies but cypress remove those cookies on cy.visit("/").
const browser = await puppeteer.connect({
browserURL: `http://localhost:${debuggingPort}`,
defaultViewport: null,
});
Any updates on how this works with the new cy.session()
? I'm struggling to get it working because Cypress.Cookies.defaults
got removed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am also facing this issue as @WvdE described. its successfully logged in using puppeteer and giving me cypresserror:cy.task('AzureAdSingleSignOn') timed out after waiting 60000ms. Could you please help