自定义Azure AD B2C策略无法向注册/登录API发送OAuth2 Bearer令牌的问题求助
我来帮你梳理下这个问题,从你的配置来看,确实有几个容易忽略的细节可能导致Bearer令牌没被正确发送到API:
1. 移除干扰Bearer头生成的冗余配置
你在REST-GetProfile的<InputClaims>里添加了<InputClaim ClaimTypeReferenceId="bearerToken"/>,这会把令牌放到请求Body中,但你已经通过<Item Key="AuthenticationType">Bearer</Item>和<Item Key="UseClaimAsBearerToken">bearerToken</Item>配置了要将令牌放到Authorization请求头里。这两个配置会产生冲突,B2C可能优先处理Body的发送,从而忽略了头的设置。
解决方法:直接删掉REST-GetProfile里的这个bearerToken InputClaim,只保留业务相关的字段(比如objectId、email等)。
2. 修正令牌获取的Scope配置
你当前REST-AcquireAccessToken里的scope是https://graph.microsoft.com/.default,这是用于获取Microsoft Graph的令牌的,但你要调用的是自定义API,所以这里的scope必须替换为你的API对应的正确范围。
如果你的API注册在Azure AD B2C中,正确的scope格式应该是:api://{你的API的Client ID}/.default(client credentials流需要用.default来获取默认权限)。用Graph的scope拿到的令牌受众(aud)是Graph,你的API不会认可,甚至B2C在发送时可能因为令牌受众不匹配跳过头的设置。
3. 确认bearerToken声明类型已定义
确保你的策略的<ClaimsSchema>部分已经定义了bearerToken这个声明类型,否则B2C无法存储从令牌端点返回的access_token:
<ClaimType Id="bearerToken"> <DisplayName>Bearer Token</DisplayName> <DataType>string</DataType> <UserHelpText>OAuth 2.0 bearer token for API authentication</UserHelpText> </ClaimType>
4. 验证令牌获取步骤是否成功
开启Azure AD B2C的Application Insights日志,查看REST-AcquireAccessToken这个TechnicalProfile是否成功返回了bearerToken。如果令牌获取失败(比如Client ID/Secret错误、scope无效),那后续调用API时自然没有令牌可以发送。
你可以在B2C门户的策略设置里启用日志,触发一次登录/注册流程后,查看日志中是否有REST-AcquireAccessToken的成功记录,以及bearerToken是否被正确返回。
API端的授权配置(ASP.NET Core为例)
对于你的C# API,需要配置JWT验证来接受B2C颁发的Bearer令牌,步骤如下:
- 在
Program.cs中添加JWT验证服务:
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); // 添加JWT验证 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // 替换为你的B2C租户和策略名称 options.Authority = "https://your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com/your-b2c-policy-name/v2.0/"; // 替换为你的API的Client ID(或API的标识符) options.Audience = "api://your-api-client-id"; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true }; }); // 添加授权 builder.Services.AddAuthorization(); // 其他服务配置... var app = builder.Build(); // 启用认证和授权中间件(注意顺序:先认证后授权) app.UseAuthentication(); app.UseAuthorization(); // 其他中间件和路由配置... app.Run();
- 在需要保护的API控制器或方法上添加
[Authorize]特性,确保只有携带有效B2C令牌的请求才能访问:
[ApiController] [Route("api/[controller]")] [Authorize] public class SignInController : ControllerBase { [HttpGet] public IActionResult Get() { // 这里可以通过User.Claims获取令牌中的声明 return Ok("Authenticated successfully"); } }
完成以上调整后,重新发布你的B2C策略和API,再测试一次,应该就能在API的Request.Headers中看到Authorization: Bearer {token}的请求头了。
内容的提问来源于stack exchange,提问作者K Deman

