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

Azure AD B2C跨子域微软账号SSO无缝登录问题求助

Azure AD B2C自定义策略跨子域微软账号SSO解决方案

核心问题分析

本地账号跨子域SSO正常,但微软账号登录后切换子域需重新验证,本质是外部身份提供者(微软账号)的会话未与B2C跨子域SSO cookie正确绑定,同时MSAL客户端缓存未跨域共享导致子域应用无法读取登录状态。

解决方案步骤

1. 调整自定义策略:确保微软IDP会话与B2C跨域SSO关联

在微软账号的<TechnicalProfile>配置中,添加会话管理设置,确保登录后B2C将外部IDP的会话信息写入跨子域的SSO cookie:

<TechnicalProfile Id="MSA-OIDC">
  <DisplayName>Microsoft Account</DisplayName>
  <Protocol Name="OpenIdConnect" />
  <Metadata>
    <!-- 保留原有元数据 -->
    <Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>
    <Item Key="PersistentSSO">true</Item>
  </Metadata>
  <SessionManagement ReferenceId="SM-CrossDomainSSO" />
</TechnicalProfile>

<!-- 新增跨域会话管理配置 -->
<TechnicalProfile Id="SM-CrossDomainSSO">
  <DisplayName>Cross-Domain Session Management</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.SSO.SessionManagementProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="CookieDomain">.test.myDomain.com</Item>
    <Item Key="SessionExpiryType">Absolute</Item>
    <Item Key="SessionExpiryInSeconds">86400</Item>
  </Metadata>
</TechnicalProfile>
  • CookieDomain设置为根测试域.test.myDomain.com,确保cookie可被所有子域读取
  • PersistentSSO启用持久化会话,避免会话随浏览器关闭失效

2. 统一MSAL客户端配置:实现跨子域缓存共享

修改React应用的MSAL配置,确保所有子域应用使用相同的缓存策略和域设置:

const msalConfig = {
  auth: {
    clientId: "YOUR_CLIENT_ID",
    authority: "https://test.myDomain.com/YOUR_TENANT_ID/YOUR_POLICY",
    redirectUri: window.location.origin, // 自动适配子域origin
    postLogoutRedirectUri: window.location.origin,
    navigateToLoginRequestUrl: false // 避免跳转干扰自动SSO
  },
  cache: {
    cacheLocation: "localStorage", // 替代sessionStorage,实现跨子域共享
    storeAuthStateInCookie: true,
    cookieDomain: ".test.myDomain.com" // MSAL缓存cookie跨子域共享
  }
};
  • cacheLocation设为localStorage:sessionStorage是域隔离的,localStorage可跨子域访问(需主域名一致)
  • cookieDomain设置为根测试域,确保MSAL的认证状态cookie可被所有子域读取

3. 优化应用登录逻辑:静默获取令牌而非强制跳转

在App.tsx中调整登录逻辑,优先尝试静默获取令牌,仅在失败时触发无交互重定向:

const App = () => {
  const { instance, accounts } = useMsal();

  useEffect(() => {
    const fetchTokenSilently = async () => {
      if (accounts.length === 0) {
        try {
          // 尝试静默获取令牌,触发B2C跨域SSO验证
          const response = await instance.acquireTokenSilent({
            scopes: ["YOUR_API_SCOPES"],
            account: instance.getAllAccounts()[0] || undefined
          });
          // 令牌获取成功,处理后续认证逻辑
        } catch (error) {
          // 仅在静默失败时,触发无交互SSO重定向
          if (error instanceof InteractionRequiredAuthError) {
            instance.loginRedirect({
              scopes: ["YOUR_API_SCOPES"],
              prompt: "none" // 关键:设置prompt=none,避免显示登录页
            });
          }
        }
      }
    };

    fetchTokenSilently();
  }, [instance, accounts]);

  // 其余应用逻辑
};
  • prompt: "none"是核心:告诉B2C如果已有有效会话,直接返回令牌,无需用户交互
  • 优先调用acquireTokenSilent,利用跨域cookie读取B2C会话状态

4. 验证浏览器Cookie配置

确保以下cookie存在于.test.myDomain.com域下:

  • x-ms-cpim-sso:B2C的SSO会话cookie,需带有HttpOnly、Secure、SameSite=None属性
  • msal.{clientId}.token等MSAL缓存cookie:需带有Secure、SameSite=None,且域为.test.myDomain.com

常见问题排查

  • ssoSilent跨域iframe报错:检查子域应用的CSP策略,添加frame-src https://test.myDomain.com;或改用loginRedirect({ prompt: "none" })替代iframe静默方式
  • acquireTokenSilent无账号记录:确保MSAL的cacheLocation为localStorage且cookieDomain配置正确,子域应用能读取到主域的缓存数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:35:21