Dav*_*ndo 5 adfs ui-testing azure azure-ad-msal cypress
这些是我关于如何使用 MSAL.js 和 ADFS(在我们的示例中是本地部署)以及与令牌创建和本地存储过程关联的架构对 Azure AD 单页应用程序进行 UI 测试的注释。
教程中:“它使用 ROPC 身份验证流程来获取测试用户帐户的令牌,并在运行测试之前将它们注入到浏览器本地存储中。这样,MSAL.js 就不会尝试获取令牌,因为它已将令牌存储在缓存中”。
观看精彩视频后: https://www.youtube.com/watch ?v=OZh5RmCztrU
...并浏览此处的存储库: https://github.com/juunas11/AzureAdUiTestAutomation
我一直试图将本地 ADFS 与 MSAL.js 2.0 和会话存储的使用与上述教程和代码相匹配。因此,如果您使用以/adfs/oauth2/token结尾的 Azure 链接 (而不是 oAuth /oauth2/v2.0/token ),请按照以下步骤操作!
我所做的大部分更改来自 auth.js:https://github.com/juunas11/AzureAdUiTestAutomation/blob/main/UiTestAutomation.Cypress/cypress/support/auth.js
只需按照教程复制该内容,然后更改以下内容:
const buildRefreshTokenEntity = (homeAccountId: string, accessToken: string) => {
return {
clientId,
credentialType: 'RefreshToken',
environment,
homeAccountId,
secret: accessToken,
};
};
Run Code Online (Sandbox Code Playgroud)
const injectTokens = (tokenResponse: any) => {
const scopes = ['profile', 'openid'];
const idToken: JwtPayload = decode(tokenResponse.id_token) as JwtPayload;
const localAccountId = idToken.sub; // in /oauth2/v2.0/token this would be: idToken.oid || idToken.sid; however we are using /adfs/oauth2/token
const realm = ''; // in /oauth2/v2.0/token this would be: idToken.tid; however we are using /adfs/oauth2/token
const homeAccountId = `${localAccountId}`; // .${realm}`;
const homeAccountIdLowerCase = `${localAccountId}`.toLowerCase(); // .${realm}`;
const usernameFromToken = idToken.upn; // in /oauth2/v2.0/token this would be: idToken.preferred_username; however we are using /adfs/oauth2/token
const name = ''; // in /oauth2/v2.0/token this would be: idToken.name; however we are using /adfs/oauth2/token
const idTokenClaims = JSON.stringify(idToken);
const accountKey = `${homeAccountIdLowerCase}-${environment}-${realm}`;
const accountEntity = buildAccountEntity(homeAccountId, realm, localAccountId, idTokenClaims, usernameFromToken, name);
const idTokenKey = `${homeAccountIdLowerCase}-${environment}-idtoken-${clientId}-${realm}-`;
const idTokenEntity = buildIdTokenEntity(homeAccountId, tokenResponse.id_token, realm);
const accessTokenKey = `${homeAccountIdLowerCase}-${environment}-accesstoken-${clientId}-${realm}-${scopes.join(' ')}`;
const accessTokenEntity = buildAccessTokenEntity(
homeAccountId,
tokenResponse.access_token,
tokenResponse.expires_in,
tokenResponse.expires_in, // ext_expires_in,
realm,
scopes,
);
const refreshTokenKey = `${homeAccountIdLowerCase}-${environment}-refreshtoken-${clientId}-${realm}`;
const refreshTokenEntity = buildRefreshTokenEntity(homeAccountId, tokenResponse.access_token);
// localStorage was not working, needs to be in sessionStorage
sessionStorage.setItem(accountKey, JSON.stringify(accountEntity));
sessionStorage.setItem(idTokenKey, JSON.stringify(idTokenEntity));
sessionStorage.setItem(accessTokenKey, JSON.stringify(accessTokenEntity));
sessionStorage.setItem(refreshTokenKey, JSON.stringify(refreshTokenEntity));
};
Run Code Online (Sandbox Code Playgroud)
export const login = (cachedTokenResponse: any) => {
let tokenResponse: any = null;
let chainable: Cypress.Chainable = cy.visit('/'); // need to visit root to be able to store Storage against this site
if (!cachedTokenResponse) {
chainable = chainable.request({
url: authority + '/adfs/oauth2/token', // was this '/oauth2/v2.0/token',
method: 'POST',
body: {
grant_type: 'password',
client_id: clientId,
// client_secret: clientSecret,
scope: ['profile openid'].concat(apiScopes).join(' '),
username,
password,
},
form: true,
});
***... MORE CODE OMITTED***
Run Code Online (Sandbox Code Playgroud)
打字稿使用:
"types": ["node", "cypress"],
Run Code Online (Sandbox Code Playgroud)
现在,当我运行 Cypress 时,我可以在我的网站上导航,并且我已经通过了身份验证!希望这可以帮助您节省一两个小时!
| 归档时间: |
|
| 查看次数: |
2898 次 |
| 最近记录: |