与多个 B2C 租户共享单个 WebApp 和 API 部署

Sharing single WebApp and API deployment with multiple B2C Tenants

当前情景: Web 应用程序和 Web API 使用 AAD B2C 进行身份验证并且工作正常。每个客户都有一个独特的租户。 OpenIdConnectAuthenticationOptions(网络应用程序)和 OAuthBearerAuthenticationOptions(api)在应用程序 Startup 中设置。

如此处所述:Token based authentication for both Web App and Web API using Azure AD B2C

不幸的是,Web 应用程序和 API 都必须为每个客户部署,以将它们分开。

要求: 为多个客户使用相同的 Web 应用程序和 API,而不是为每个客户部署它们。每个客户的 Web 应用程序都会有不同的 URL。

问题 1(Web 应用程序):如何根据请求将用户重定向(用于身份验证)到正确的租户 URL?

即基于 Request.Url 而不是在应用程序 Startup.

上从数据库(或内存)动态设置 OpenIdConnectAuthenticationOptions(租户、applicationId、signInPolicy 等)

问题 2 (API):如何使用正确的租户验证收到的令牌?

即根据收到的令牌 clientId 即时设置 OAuthBearerAuthenticationOptions 配置,而不是在应用程序 Startup

根据我认为的假设,其中有几件事是行不通的。

  • 首先,B2C没有倍数的概念"tenants"。 B2C本质上是 您的租户中的目录,不能进一步分离。你 在你的租户中可以有多个 B2C 目录,比如每个 客户,但您不能在一个 单个 B2C 目录。

  • 其次,如果您的应用程序确实连接到多个 B2C 目录,您需要管理连接器、应用程序 ID、密钥 等每一个。然后由您的应用程序确定哪个 一个根据一些数据使用(URL 访问等)。

关于您如何吸引用户,我还想问几个问题?他们可以自己注册吗?他们有自己的用户商店吗?

如果您真的想将每个组织的用户帐户分开(并且他们还没有 SAML/OIDC 身份提供者),那么我会执行以下操作:

通过这种方式,您的应用程序只需要信任和维护单个 B2C 目录,如果您有拥有自己的 OIDC 或 SAML 端点的客户,他们将成为目录中的声明提供者,而不是单独的 B2C 实例.

根据@ManishJoisar 的要求,这是我很久以前解决问题的方法。这是一个旧的 .net 框架 4.8 代码示例。

请注意,如今,B2C v2 策略通过自定义策略提供了更好的联合实施。

public void ConfigureAuth(IAppBuilder app)
    {

        int index = 2000;
        foreach (var record in SystemConfig.ApiToWebUrl)
        {
            app.MapWhen(
                    context => System.Web.HttpContext.Current.Request.Url.BaseURL() == record.Key,
                    config =>
                    {
                        var customer = SystemConfig.GetWebSettings(true)[record.Value];
                        config.UseOAuthBearerAuthentication(CreateBearerOptionsFromPolicy(index, customer.B2CSignInPolicyId,
                                                customer.B2CAadInstance, customer.B2CTenant, customer.B2CApplicationId));
                    }
                );

            index++;
        }
    }

    public OAuthBearerAuthenticationOptions CreateBearerOptionsFromPolicy(int index, string b2cPlicyName,
                    string b2cInstance, string b2cTenant, string b2cClientId)
    {
        TokenValidationParameters tvps = new TokenValidationParameters
        {
            // This is where you specify that your API only accepts tokens from its own clients
            ValidAudience = b2cClientId,
            AuthenticationType = string.Format("{0}_{1}", b2cPlicyName, index)
        };

        var aadInstance = string.Format("https://{0}{1}", b2cTenant.Split('.')[0], ".b2clogin.com/{0}/{1}/v2.0/.well-known/openid-configuration");

        var config = String.Format(aadInstance, b2cTenant, b2cPlicyName);

        return new OAuthBearerAuthenticationOptions
        {
            // This SecurityTokenProvider fetches the Azure AD B2C metadata & signing keys from the OpenIDConnect metadata endpoint
            AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider(config)),
            Provider = new CustomOAuthBearerProvider()
        };
    }