有没有办法以编程方式登录到在 PKCE 流程上使用 AzureAD 和 Cypress?

Mat*_*ski 3 automated-tests azure oauth-2.0 cypress pkce

我想使用 cypress.js ( https://www.cypress.io/ ) 来验证自己(React 应用程序)。有没有办法用 PKCE 以编程方式完成它?当我阅读和研究所有示例时 - 所有示例都使用隐式流

我试图使用类似的解决方案https://www.npmjs.com/package/react-adal,但没有成功,因为它需要隐式流程,turned on 我也在尝试这样做: https: //xebia.com/blog/how-to-use-azure-ad-single-sign- on-with-cypress/没有成功

我希望以编程方式登录 cypress 并将用户信息和 access_token 保存到 sessionStorage 以便能够执行另一个 api 调用

小智 8

我还没有找到一种方法来使用 PKCE 本身以编程方式执行此操作,但是使用 MSAL 2.0 库(@azure/msal-browser在 npm 上),我能够提前填写帐户缓存,因此它认为它已经登录。该过程看起来像这:

\n
    \n
  1. 使用cy.taskROPC 流向 Azure AD 发送请求以获取令牌。\n
    const scopes = [\n    'openid',\n    'profile',\n    'user.read',\n    'email',\n    'offline_access' // needed to get a refresh token\n];\nconst formdata = new URLSearchParams({\n    'grant_type': 'password',\n    'scope': scopes.join(' '),\n    'client_info': 1, // returns an extra token that MSAL needs\n    'client_id': aadClientId,\n    'client_secret': aadClientSecret,\n    'username': aadUsername,\n    'password': aadPassword,\n});\nconst response = await fetch(`https://login.microsoft.com/${aadTenantId}/oauth2/v2.0/token`, {\n    method: 'POST',\n    headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n    },\n    body: formdata.toString(),\n});\nconst tokens = await response.json();\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
  3. 将令牌转换为 MSAL 想要的缓存条目(基于在真实浏览器中观察)\n
    // The token tells us how many seconds until expiration;\n// MSAL wants to know the timestamp of expiration.\nconst cachedAt = Math.round(new Date().getTime()/1000);\nconst expiresOn = cachedAt + tokens.expires_in;\nconst extendedExpiresOn = cachedAt + tokens.ext_expires_in;\n\n// We can pull the rest of the data we need off of the ID token body\nconst id_token = JSON.parse(Buffer.from(tokens.id_token.split('.')[1], 'base64').toString('utf-8'));\n\nconst clientId = id_token.aud;\nconst tenantId = id_token.tid;\nconst userId = id_token.oid;\nconst name = id_token.name;\nconst username = id_token.preferred_username;\n\nconst environment = 'login.windows.net'; // \xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f\nconst homeAccountId = `${userId}.${tenantId}`;\n\nconst cacheEntries = {};\n\n// client info\ncacheEntries[`${homeAccountId}-${environment}-${tenantId}`] = JSON.stringify({\n  authorityType: 'MSSTS',\n  clientInfo: tokens.client_info,\n  environment,\n  homeAccountId,\n  localAccountId: userId,\n  name,\n  realm: tenantId,\n  username,\n});\n\n// access token\ncacheEntries[`${homeAccountId}-${environment}-accesstoken-${clientId}-${tenantId}-${token.scope}`] = JSON.stringify({\n  cachedAt: cachedAt.toString(),\n  clientId,\n  credentialType: "AccessToken",\n  environment,\n  expiresOn: expiresOn.toString(),\n  extendedExpiresOn: extendedExpiresOn.toString(),\n  homeAccountId,\n  realm: tenantId,\n  secret: tokens.access_token,\n  target: tokens.scope,\n});\n\n// id token\ncacheEntries[`${homeAccountId}-${environment}-idtoken-${clientId}-${tenantId}-`] = JSON.stringify({\n  clientId,\n  credentialType: "IdToken",\n  environment,\n  homeAccountId,\n  realm: tenantId,\n  secret: tokens.id_token,\n});\n\n// refresh token\ncacheEntries[`${homeAccountId}-${environment}-refreshtoken-${clientId}--`] = JSON.stringify({\n  clientId,\n  credentialType: "RefreshToken",\n  environment,\n  homeAccountId,\n  secret: tokens.refresh_token,\n});\n
    Run Code Online (Sandbox Code Playgroud)\n
  4. \n
  5. 用于cy.window将它们存储在 sessionStorage 或 localStorage 中,具体取决于 MSAL 的配置方式。\n
    cy.task('login').then(cacheEntries => {\n    cy.window().then(window => {\n        for (let entry in cacheEntries) {\n            window.sessionStorage.setItem(entry, cacheEntries[entry]);\n        }\n    });\n});\n
    Run Code Online (Sandbox Code Playgroud)\n
  6. \n
\n

它非常脆弱,而且不太漂亮,但它很有效!当然,Cypress 登录的用户需要禁用 MFA。

\n