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

如何在含Razor Pages与Web API的ASP.NET Core应用中实现AD B2C认证

ASP.NET Core混合Razor Pages+Web API的AD B2C安全实现方案

核心思路

要解决这个问题,关键是分离Web应用(Razor Pages)和Web API的认证管道:Razor Pages依赖Cookie认证实现用户登录,Web API依赖JWT Bearer认证验证请求令牌,不能只用单一的WebAppAuthentication配置。


一、AD B2C应用注册配置

  1. 在AD B2C中注册单个应用(也可分开注册,单应用更简便)
  2. 进入应用的「暴露API」页面,添加自定义范围(如api://{你的应用Client ID}/access_as_user),设置范围名称和描述
  3. 进入「API权限」页面,添加刚才定义的自定义范围,并完成管理员同意(确保应用能获取该范围的令牌)

二、ASP.NET Core服务配置

1. 同时配置两种认证方案

在Program.cs中同时添加Cookie认证(供Razor Pages)和Bearer认证(供Web API),并指定不同的方案名称:

builder.Services.AddAuthentication()
    // Razor Pages用的Cookie认证方案,命名为"CookieAuth"
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAdB2C"), "CookieAuth")
    // Web API用的Bearer认证方案,命名为"BearerAuth"
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAdB2C"), "BearerAuth");

// 设置默认认证/挑战方案为Cookie(适配Razor Pages的登录流程)
builder.Services.Configure<AuthenticationOptions>(options =>
{
    options.DefaultAuthenticateScheme = "CookieAuth";
    options.DefaultChallengeScheme = "CookieAuth";
});

2. 定义API专属授权策略

创建仅接受Bearer令牌且包含指定范围声明的授权策略:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ApiAccessPolicy", policy =>
    {
        policy.AuthenticationSchemes.Add("BearerAuth");
        policy.RequireAuthenticatedUser();
        // 验证令牌包含之前定义的API范围声明
        policy.RequireClaim("scp", "access_as_user");
    });
});

三、Razor Pages调用API的正确姿势

在Razor Pages的后台代码中,通过ITokenAcquisition获取针对API范围的AccessToken,并且确保请求仅携带Bearer令牌(不要混入Cookie):

private readonly IHttpClientFactory _httpClientFactory;
private readonly ITokenAcquisition _tokenAcquisition;

public IndexModel(IHttpClientFactory httpClientFactory, ITokenAcquisition tokenAcquisition)
{
    _httpClientFactory = httpClientFactory;
    _tokenAcquisition = tokenAcquisition;
}

public async Task OnGetAsync()
{
    var apiScope = "api://{你的应用Client ID}/access_as_user";
    // 获取针对API范围的AccessToken
    var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { apiScope });
    
    var client = _httpClientFactory.CreateClient();
    // 手动添加Bearer令牌到请求头
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
    // 调用自身API
    var response = await client.GetAsync($"{Request.Scheme}://{Request.Host}/api/values");
    response.EnsureSuccessStatusCode();
    var apiContent = await response.Content.ReadAsStringAsync();
    
    // 处理API返回内容
}

四、Web API端点授权

在API控制器(或API型Razor Pages)上应用之前定义的授权策略,确保只有携带有效Bearer令牌的请求能访问:

[ApiController]
[Route("api/[controller]")]
[Authorize(Policy = "ApiAccessPolicy")]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok(new string[] { "value1", "value2" });
    }
}

常见问题排查

  • 解析获取的AccessToken(用jwt.ms),确认包含scp声明且值为定义的API范围
  • 检查API端点的授权策略是否指定了BearerAuth方案,避免默认使用Cookie认证导致跳转到登录页返回HTML
  • 确认AD B2C应用注册中已完成API范围的管理员同意,否则无法获取有效令牌

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:13:11