I'm new to both Cypress and Azure AD, but I've been following the steps described here to create Cypress tests on an existing Angular app that uses Azure AD. It mentions that they are using ADAL, but our app uses MSAL, which it says should be similar. However, I'm struggling to get it to work. Here's my login function so far:
const tenant = 'https://login.microsoftonline.com/{my_tenant_id}/';
const tenantUrl = `${tenant}oauth2/token`;
const clientId = '{my_app_id}';
const clientSecret = '{my_secret}';
const azureResource = 'api://{my_app_id}';
const knownClientApplicationId = '{client_application_id_from_manifest}';
const userId = '{user_identifier}';
export function login() {
cy.request({
method: 'POST',
url: tenantUrl,
form: true,
body: {
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
resource: azureResource
}
}).then(response => {
const Token = response.body.access_token;
const ExpiresOn = response.body.expires_on;
const key = `{"authority":"${tenant}","clientId":"${knownClientApplicationId}","scopes":${knownClientApplicationId},"userIdentifier":${userId}}`;
const authInfo = `{"accessToken":"${Token}","idToken":"${Token}","expiresIn":${ExpiresOn}}`;
window.localStorage.setItem(`msal.idtoken`, Token);
window.localStorage.setItem(key, authInfo);
}
Cypress.Commands.add('login', login);
When I run this, an access token is returned. When I examine the local storage after a normal browser request, it has many more fields, such as msal.client.info
(the authInfo
value in the code above should also contain this value), but I've no idea where to get this information from.
The end result is that the POST request seems to return successfully, but the Cypress tests still consider the user to be unauthenticated.
The existing app implements a CanActivate
service that passes if MsalService.getUser()
returns a valid user. How can I convince this service that my Cypress user is valid?
After some experimentation with the local storage values, it looks like only two values are required to get past the login:
msal.idtoken
msal.client.info
The first I already have; the second one I'm not sure about, but it appears to return the same value every time. For now, I'm hard coding that value into my tests, and it seems to work somewhat:
then(response => {
const Token = response.body.access_token;
window.localStorage.setItem(`msal.idtoken`, Token);
window.localStorage.setItem(`msal.client.info`, `{my_hard_coded_value}`);
});
The only minor issue now is that the MsalService.getUser()
method returns slightly different values than the app is expecting (e.g. displayableId
and name
are missing; idToken.azp
and idToken.azpacr
are new). I'll investigate further...
This solution got me a successful request but I still couldn't get past the login screen on my app, after some searching I found this great tutorial video that got me past the login screen! I am using the msal-react
& msal-browser
npm packages.
https://www.youtube.com/watch?v=OZh5RmCztrU
Repo for the code is here:
https://github.com/juunas11/AzureAdUiTestAutomation/tree/main/UiTestAutomation.Cypress/cypress
I want to thank you for all of the groundwork you've done to figure out which variables to set when working with MSAL! I think I can help with figuring out where clientInfo comes from. It looks like it is generated from the clientId, which explains why it is always the same value:
static createClientInfoFromIdToken(idToken:IdToken, authority: string): ClientInfo {
const clientInfo = {
uid: idToken.subject,
utid: ""
};
return new ClientInfo(CryptoUtils.base64Encode(JSON.stringify(clientInfo)), authority);
}
See source here: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/70b87bcd27bfe67789c92b9bc046b45733f490ed/lib/msal-core/src/ClientInfo.ts
I was able to use your code and just added import * as MSAL from "@azure/msal-browser"
and window.localStorage.setItem(`msal.client.info`, MSAL.clientInfo);
Worked like a charm for me!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With