You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Cypress测试Angular项目Azure B2C登录后首次返回401错误

问题根因

  • 核心是Azure B2C登录完成后跳回你的Angular应用域名时,Cypress的上下文切换比应用的鉴权逻辑执行快,Angular的路由守卫、HTTP拦截器还没拿到B2C返回的身份凭证(token、cookie)就发起了校验请求,所以返回401。
  • 具体触发场景有两个:
    1. Azure B2C登录后的回调参数(code、id_token等)需要Angular的MSAL库处理完成后才会生成有效凭证,你现在的代码在点击next按钮后没有等待这个处理逻辑执行完成,直接触发了后续请求。
    2. Cypress默认限制第三方cookie写入,Azure B2C下发的跨域凭证首次没有被正确同步到你的应用域名下,刷新后浏览器重新拉取了存储的凭证就正常了。

解决方案

第一步:调整Cypress配置

首先在cypress.config.js里开启跨域相关配置,允许跨域cookie保存:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    experimentalSessionAndOrigin: true,
    chromeWebSecurity: false, // 关闭跨域安全限制适配B2C跳转
  }
})

第二步:优化测试用例逻辑

不要直接在点击登录按钮后不做等待就继续操作,增加等待MSAL处理完成的逻辑:

describe('login', () => {
  beforeEach(() => {
    cy.clearAllCookies()
    cy.clearAllLocalStorage()
    cy.clearAllSessionStorage()
  })
  it('get the access token test', () => {
    cy.visit('/')
    cy.get('button').click()
    // B2C登录页操作
    cy.get('input#email').type('myemail@gmail.com')
    cy.get('input#password').type('mypassword')
    cy.get('button#next').click()
    // 等待跳转回应用域名,且MSAL完成token处理
    cy.origin('你的Angular应用域名', () => {
      // 等待localStorage里出现MSAL的token,或者等待首页的特征元素出现
      cy.window().its('localStorage.msal.idtoken', { timeout: 10000 }).should('exist')
      cy.get('.nav-user-name', { timeout: 10000 }).should('be.visible')
    })
    // 后续业务操作逻辑
  })
})

如果还是出现首次401,可以在登录完成后主动触发一次重载:

// 放在点击next之后的等待逻辑里
cy.reload()

第三步:更稳定的免UI登录方案

如果只是需要拿到鉴权状态跑后续业务测试,建议直接调用Azure B2C的密码授权流接口拿token,写入存储跳过UI登录:

// 封装全局登录命令
Cypress.Commands.add('loginByB2C', () => {
  cy.request({
    method: 'POST',
    url: '你的B2C租户token端点',
    form: true,
    body: {
      grant_type: 'password',
      client_id: '你的应用clientId',
      scope: 'openid profile offline_access 你的API scope',
      username: 'myemail@gmail.com',
      password: 'mypassword',
    }
  }).then((res) => {
    // 把返回的token按照MSAL的存储格式写入localStorage
    window.localStorage.setItem('msal.idtoken', res.body.id_token)
    window.localStorage.setItem('msal.access_token', res.body.access_token)
  })
})
// 测试用例直接调用
it('get the access token test', () => {
  cy.loginByB2C()
  cy.visit('/')
  // 后续业务逻辑
})

内容的提问来源于stack exchange,提问作者Andy88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:15:03