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?
Update:
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...