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

.NET Core 6应用如何基于URL动态加载AzureAdB2C配置

动态加载Azure AD B2C配置(基于子域名)

我有一个基于.NET Core 6.0开发的应用,需求是根据访问的URL(例如不同子域名aaaa.test.com、bbbb.test.com等)动态加载对应的Azure AD B2C配置,且配置不存储在appsettings.json中,而是从SQL等数据源动态获取。

我已经找到基于appsettings.json配置多套Azure AD B2C参数的方案,但需要更灵活的动态加载方式,目前尝试多种方法均未成功,以下是我尝试过的代码片段:

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "TokenLogin";
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie("TokenLogin", options =>
{
    options.ExpireTimeSpan = DateTime.Now.Subtract(DateTime.UtcNow).Add(TimeSpan.FromDays(2));
    options.Cookie.MaxAge = options.ExpireTimeSpan;
    options.SlidingExpiration = true;
})
.AddMicrosoftIdentityWebApp(options =>
{
    builder.Configuration.Bind("AzureADB2C", options);


    //-------> 我尝试过的操作
    //var xxx = builder.Services.BuildServiceProvider().GetService<IHttpContextAccessor>().HttpContext;
    //var authOptions = xxx.RequestServices.GetRequiredService<IOptionsMonitor<AzureADB2C>>();
    ////var authOptions = xxx.RequestServices.GetRequiredService<AzureADB2C>();

    //options.Instance = authOptions.CurrentValue.Instance;
    //options.ClientId = authOptions.CurrentValue.ClientId;
    //options.CallbackPath = authOptions.CurrentValue.CallbackPath;
    //options.Domain = authOptions.CurrentValue.Domain;
    //options.SignUpSignInPolicyId = authOptions.CurrentValue.SignUpSignInPolicyId;
    //options.ResetPasswordPolicyId = authOptions.CurrentValue.ResetPasswordPolicyId;
    //options.EditProfilePolicyId = authOptions.CurrentValue.EditProfilePolicyId;

    
    //options.SignInScheme = OpenIdConnectDefaults.AuthenticationScheme;
    //options.Events ??= new OpenIdConnectEvents();
    //options.Events.OnRedirectToIdentityProvider += OnRedirectToIdentityProviderFunc;
    //options.Events.OnRedirectToIdentityProvider = context =>
    //{
        // Your code here
        //return Task.CompletedTask;
    //};

    //options.Instance = authOptions.Instance;
    //options.ClientId = authOptions.ClientId;
    //options.CallbackPath = authOptions.CallbackPath;
    //options.Domain = authOptions.Domain;
    //options.SignUpSignInPolicyId = authOptions.SignUpSignInPolicyId;
    //options.ResetPasswordPolicyId = authOptions.ResetPasswordPolicyId;
    //options.EditProfilePolicyId = authOptions.EditProfilePolicyId;

    //authOptions.OnChange(newOptions => {
    //    if (!settingsWereLoaded)
    //    {
    //        //options.Instance = authOptions.CurrentValue.Instance;
    //        //options.ClientId = authOptions.CurrentValue.ClientId;
    //        //options.Domain = authOptions.CurrentValue.Domain;
    //        options.Instance = "https://xxxx.b2clogin.com/tfp/";
    //        options.ClientId = "XXXXX-XXXX-XXXX-XXXX-XXXX";
    //        options.Domain = "XXXX.onmicrosoft.com";

    //        settingsWereLoaded = true;
    //    }
    //});
});

解决方案

1. 注册HttpContext访问服务

首先确保能在认证事件中获取当前请求信息,注册IHttpContextAccessor:

builder.Services.AddHttpContextAccessor();

2. 实现配置获取服务

创建从SQL读取子域名对应B2C配置的服务:

public interface IAdB2cConfigService
{
    Task<AzureADB2COptions> GetConfigBySubdomain(string subdomain);
}

public class AdB2cConfigService : IAdB2cConfigService
{
    private readonly YourDbContext _dbContext;

    public AdB2cConfigService(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<AzureADB2COptions> GetConfigBySubdomain(string subdomain)
    {
        var config = await _dbContext.B2cConfigs
            .FirstOrDefaultAsync(c => c.Subdomain.Equals(subdomain, StringComparison.OrdinalIgnoreCase));
        
        if (config == null)
            throw new InvalidOperationException($"未找到{subdomain}对应的B2C配置");

        return new AzureADB2COptions
        {
            Instance = config.Instance,
            ClientId = config.ClientId,
            Domain = config.Domain,
            SignUpSignInPolicyId = config.SignUpSignInPolicyId,
            ResetPasswordPolicyId = config.ResetPasswordPolicyId,
            EditProfilePolicyId = config.EditProfilePolicyId,
            CallbackPath = "/signin-oidc"
        };
    }
}

注册该服务:

builder.Services.AddScoped<IAdB2cConfigService, AdB2cConfigService>();

3. 动态配置认证事件

在认证服务配置中,通过OnRedirectToIdentityProvider事件动态替换B2C参数:

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "TokenLogin";
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie("TokenLogin", options =>
{
    options.ExpireTimeSpan = TimeSpan.FromDays(2); // 简化原代码的时间计算逻辑
    options.Cookie.MaxAge = options.ExpireTimeSpan;
    options.SlidingExpiration = true;
})
.AddMicrosoftIdentityWebApp(options =>
{
    // 无需绑定静态配置,留空即可
})
.AddOpenIdConnect(options =>
{
    options.Events = new OpenIdConnectEvents
    {
        OnRedirectToIdentityProvider = async context =>
        {
            // 解析当前请求的子域名
            var hostParts = context.HttpContext.Request.Host.Host.Split('.');
            var subdomain = hostParts.Length >= 2 ? hostParts[0] : string.Empty;

            // 获取对应配置
            var configService = context.HttpContext.RequestServices.GetRequiredService<IAdB2cConfigService>();
            var b2cConfig = await configService.GetConfigBySubdomain(subdomain);

            // 动态替换认证参数
            context.ProtocolMessage.IssuerAddress = $"{b2cConfig.Instance}{b2cConfig.Domain}/{b2cConfig.SignUpSignInPolicyId}/v2.0/";
            context.ProtocolMessage.ClientId = b2cConfig.ClientId;
            context.ProtocolMessage.RedirectUri = $"{context.HttpContext.Request.Scheme}://{context.HttpContext.Request.Host}{b2cConfig.CallbackPath}";
            
            // 其他参数按需替换
            context.ProtocolMessage.SetParameter("domain_hint", b2cConfig.Domain);
        }
    };
});

核心要点

  • 服务注册阶段无法获取HttpContext,必须在认证事件中动态处理请求信息
  • 可给配置服务添加缓存逻辑(如分布式缓存),减少SQL查询次数
  • 确保每个子域名的重定向URI已在Azure AD B2C应用中配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:12:33