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

如何在Azure B2C中阻止未激活用户登录(Angular8+.NET Core场景)

优化Azure B2C用户授权前的登录拦截方案

你现在的做法确实会带来糟糕的用户体验——用户明明完成了登录流程,却被立刻登出,感觉像是系统出了问题。我们可以从身份验证流程的源头入手,在用户拿到登录令牌之前就拦截,而不是事后补救。下面是几个优先级从高到低的最优方案:

方案一:使用Azure B2C自定义策略(推荐)

这是最彻底的解决方案,直接在Azure B2C的身份验证流程中检查用户的extension_isActive属性,不符合条件的用户根本无法完成登录,连令牌都拿不到。

实现步骤:

  1. 在自定义策略中添加用户属性读取步骤
    在你的B2C自定义策略的UserJourney节点里,添加一个OrchestrationStep,用于读取用户的extension_isActive自定义属性:
    <OrchestrationStep Order="3" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>extension_isActive</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>
    
  2. 添加验证步骤,阻止非激活用户
    紧接着上面的步骤,添加一个验证步骤,检查extension_isActive是否为true,如果不是则终止流程并返回错误:
    <OrchestrationStep Order="4" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="true">
          <Value>extension_isActive</Value>
          <Value>True</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange Id="BlockInactiveUser" TechnicalProfileReferenceId="BlockInactiveUserProfile" />
      </ClaimsExchanges>
    </OrchestrationStep>
    
  3. 定义错误提示的TechnicalProfile
    创建一个返回错误页面的TechnicalProfile,告诉用户需要等待管理员授权:
    <TechnicalProfile Id="BlockInactiveUserProfile">
      <DisplayName>Block Inactive User</DisplayName>
      <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <Metadata>
        <Item Key="ContentDefinitionReferenceId">api.error</Item>
        <Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account is pending admin authorization. Please contact support for assistance.</Item>
      </Metadata>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="extension_isActive" />
      </OutputClaims>
    </TechnicalProfile>
    

这样,非激活用户在登录时会被直接导向B2C的错误提示页面,根本不会进入你的应用。

方案二:后端API层面拦截(次选)

如果暂时不想修改B2C自定义策略,可以在你的.NET Core后端API中添加全局授权检查,确保只有isActive=true的用户能访问API,同时前端在登录后先验证权限,再进入应用。

后端实现:

  1. 创建自定义授权策略
    在Startup.cs(或Program.cs,取决于.NET Core版本)中添加自定义授权要求:
    services.AddAuthorization(options =>
    {
        options.AddPolicy("ActiveUser", policy =>
            policy.RequireClaim("extension_isActive", "true"));
    });
    
  2. 全局应用策略
    把这个策略应用到所有API端点:
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers().RequireAuthorization("ActiveUser");
    });
    

或者在控制器/方法上添加[Authorize(Policy = "ActiveUser")]属性。

前端改进:

在MSAL登录成功后,先调用一个简单的API端点(比如/api/auth/check-active)来验证权限,而不是直接进入应用组件:

subscribeToBroadCastServiceOnLogin() {
  this.broadcastService.subscribe("msal:loginSuccess", async (success) => {
    try {
      const response = await this.http.get('/api/auth/check-active').toPromise();
      // 验证通过,进入应用
      this.router.navigate(['/dashboard']);
    } catch (error) {
      // 验证失败,提示并登出
      window.alert("Your login is awaiting authorization from site Admin");
      this.authService.logout();
    }
  });
}

这个方案比你原来的做法体验更好,因为用户还没进入应用就会被拦截,而且后端API也能确保只有激活用户能访问资源。

方案三:前端提前检查令牌声明(临时方案)

如果以上两种方案都暂时无法实施,可以在MSAL登录成功后,立刻解析ID Token的声明并判断,在进入组件前就处理:

subscribeToBroadCastServiceOnLogin() {
  this.broadcastService.subscribe("msal:loginSuccess", (success) => {
    const isActive = success.idToken.claims["extension_3datttttxxxxxxxxxxxxxxxxxxxxxxxxx_isActive"];
    if (!isActive) {
      window.alert("Your login is awaiting authorization from site Admin");
      this.authService.logout();
      // 阻止路由跳转
      this.router.navigate(['/unauthorized']);
      return;
    }
    // 正常进入应用
    this.router.navigate(['/dashboard']);
  });
}

这个方案只是比你原来的做法提前了拦截时机,但本质还是用户完成登录后再被登出,体验不如前两个方案。

总结一下,自定义策略是最优解,它从身份验证的源头阻止非激活用户,体验最好也最安全;后端拦截是可靠的次选,能同时保护API和优化前端体验;前端提前检查是临时过渡方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:22:44