Last active
August 31, 2022 07:16
-
-
Save saschwarz/b7f115ab6a7765ff5e45b9b9461cf895 to your computer and use it in GitHub Desktop.
Automated Azure AD login and session token capture to json file for reading by Cypress commands. Heavily inspired by https://gist.github.com/pieterdv/82773fbe036719479d76ab0a4985dc3b
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
const API = Cypress.env('API'); | |
const headers = { | |
Authorization: '', | |
}; | |
Cypress.Commands.add('loginUser', () => { | |
return cy.readFile('aad-tokens.json') | |
.then(creds => { | |
// set auth headers so test setup calls are authorized | |
headers.Authorization = `Bearer ${creds['msal.idtoken']}`; | |
// put MS Azure AD creds in session storage | |
// so application under test will be logged in. | |
for (let key in creds) { | |
if ( | |
key.startsWith('msal.') || | |
key.startsWith('{"authority":') | |
) { | |
sessionStorage[key] = creds[key]; | |
} | |
} | |
}); | |
}); | |
// example of custom command using headers configured via loginUser | |
Cypress.Commands.add('APICreate', (url, instance) => { | |
Cypress.log({ | |
name: 'APICreate', | |
message: url + ' | ' + JSON.stringify(instance) | |
}) | |
return cy.request({ | |
method: 'POST', | |
headers: headers, | |
url: `${API}/${url}`, | |
body: instance | |
}).then(data => data.body); | |
}); |
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
const fs = require('fs'); | |
const puppeteer = require('puppeteer'); | |
const commander = require('commander'); | |
const inquirer = require('inquirer'); | |
const util = require('util'); | |
const readFile = util.promisify(fs.readFile); | |
const getAdToken = function(config) { | |
console.log(`Logging in ${config.email} at ${config.appURI}`); | |
return puppeteer.launch({ headless: true }).then(async browser => { | |
try { | |
const page = await browser.newPage(); | |
await page.goto(config.appURI); | |
await page.waitFor(3000); | |
await page.click('input[name=passwd]'); | |
await page.type('input[name=loginfmt]', config.email, { | |
delay: 50 | |
}); | |
await page.waitFor(500); | |
await page.click('input[type=submit]'); | |
await page.waitFor(500); | |
await page.click('input[name=passwd]'); | |
await page.waitFor(500); | |
await page.type('input[name=passwd]', config.password, { | |
delay: 50 | |
}); | |
await page.waitFor(500); | |
await page.click('input[type=submit]'); | |
await page.waitForSelector('.nav-link', { visible: true, delay: 3000 }); | |
const aadValues = await page.evaluate((conf) => { | |
for (let i = 0, len = sessionStorage.length; i < len; ++i) { | |
if ( | |
sessionStorage.key(i).startsWith('msal.') || | |
sessionStorage.key(i).startsWith('{"authority":') | |
) { | |
conf[sessionStorage.key(i)] = sessionStorage.getItem( | |
sessionStorage.key(i) | |
); | |
} | |
} | |
return conf; | |
}, config); | |
browser.close(); | |
fs.readFile('aad-tokens.json', 'utf8', (err, data) => { | |
fs.writeFile('aad-tokens.json', JSON.stringify(aadValues), { encoding: 'utf8' }, | |
(error) => { | |
if (error) { | |
console.log(error); | |
} | |
}); | |
}); | |
console.log(`aad-tokens.json updated`); | |
} catch (error) { | |
console.log(error); | |
browser.close(); | |
} | |
}); | |
}; | |
const promptUser = async function(defaults) { | |
const config = await inquirer.prompt([{ | |
name: 'appURI', | |
message: 'App URI:', | |
default: defaults.appURI | |
}, | |
{ | |
name: 'email', | |
message: 'Email:', | |
default: defaults.email | |
}, | |
{ | |
name: 'password', | |
message: 'Password:', | |
default: defaults.password | |
}, | |
]); | |
await fs.writeFile('./aad-tokens.json', | |
JSON.stringify(config), { encoding: 'utf8' }, | |
(error) => { | |
if (error) { | |
console.log(error); | |
} | |
}); | |
return config; | |
}; | |
const loginUser = function(prompt = false) { | |
Promise.resolve().then(async() => { | |
let config = await readFile('./aad-tokens.json', 'utf-8') | |
.then(file => JSON.parse(file)) | |
.catch(e => { | |
return { | |
appURI: 'http://localhost:4200/app/', | |
email: '', | |
password: '', | |
}; | |
}); | |
if (prompt) { | |
config = await promptUser(config); | |
} | |
getAdToken(config); | |
}); | |
}; | |
const main = () => { | |
commander | |
.option('--no-prompt', 'Do not prompt for input and accept values from aad-tokens.json', false) | |
.parse(process.argv); | |
loginUser(commander.prompt); | |
}; | |
module.exports = { | |
getAdToken: getAdToken, | |
loginUser: loginUser, | |
}; | |
main(); |
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
... | |
"scripts": { | |
"cypress": "node getadtoken.js --no-prompt && cypress open --env API=https://example.com/data/v4", | |
"login": "node getadtoken.js" | |
}, | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sorry @nikkieta I'm no longer working on that project and no longer have an environment to test.
Things to check:
that you actually have a valid token in the file
you see the token is in header of the test API calls when you inspect them in Cypress