Razor Pages应用Azure AD B2C注册时遇AADB2C90088错误求助
问题分析与修复方案
错误核心原因
你遇到的AADB2C90088错误,本质是应用在处理注册流程的回调时,使用了登录策略(B2C_1A_SIGNIN)去验证由注册策略(B2C_1A_SIGNUP)颁发的授权码,导致策略不匹配。ID Token的acr声明为B2C_1A_SIGNUP,说明授权码确实来自注册策略,但应用端用了错误的策略去处理令牌兑换请求,因此触发错误。
具体修复步骤
1. 完善AccountController的SignUp方法
确保你有专门的SignUp动作,并正确设置注册策略ID(而非登录策略):
public IActionResult SignUp( [FromRoute] string scheme, [FromQuery] string redirectUri) { scheme ??= OpenIdConnectDefaults.AuthenticationScheme; string redirect; if (!string.IsNullOrEmpty(redirectUri) && Url.IsLocalUrl(redirectUri)) { redirect = redirectUri; } else { redirect = Url.Content("~/")!; } var properties = new AuthenticationProperties { RedirectUri = redirect }; // 这里必须设置注册策略ID,而非登录策略 properties.Items[Constants.Policy] = _configuration.GetValue<string>("AzureAdB2C:SignUpPolicyId"); return Challenge(properties, scheme); }
2. 动态配置OpenIdConnect策略元数据
在配置OpenIdConnect中间件时,需要根据AuthenticationProperties中携带的策略值,动态切换元数据地址,确保回调时用对应的策略验证授权码:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddOpenIdConnect(options => { options.ClientId = _configuration["AzureAdB2C:ClientId"]; // 默认用登录策略作为初始Authority options.Authority = $"{_configuration["AzureAdB2C:Instance"]}{_configuration["AzureAdB2C:TenantId"]}/{_configuration["AzureAdB2C:SignInPolicyId"]}/v2.0/"; options.CallbackPath = _configuration["AzureAdB2C:CallbackPath"]; options.SignedOutCallbackPath = _configuration["AzureAdB2C:SignedOutCallbackPath"]; options.ClientSecret = _configuration["AzureAdB2C:ClientSecret"]; // 授权码流需配置此项 options.Events = new OpenIdConnectEvents { // 跳转至B2C身份提供商时,动态切换策略地址 OnRedirectToIdentityProvider = context => { if (context.Properties.Items.TryGetValue(Constants.Policy, out string policy)) { context.ProtocolMessage.IssuerAddress = $"{_configuration["AzureAdB2C:Instance"]}{_configuration["AzureAdB2C:TenantId"]}/{policy}/v2.0/"; } return Task.CompletedTask; }, // 兑换授权码时,同步切换策略的Authority OnAuthorizationCodeReceived = context => { if (context.Properties.Items.TryGetValue(Constants.Policy, out string policy)) { context.Options.Authority = $"{_configuration["AzureAdB2C:Instance"]}{_configuration["AzureAdB2C:TenantId"]}/{policy}/v2.0/"; } return Task.CompletedTask; } }; });
3. 优化AppSettings配置
移除多余的SignUpSignInPolicyId配置(因为你用的是独立的注册/登录策略),并可选添加注册策略的登出回调路径:
"AzureAdB2C": { "CallbackPath": "/signin-oidc", "Instance": "https://xxx.b2clogin.com/", "ClientId": "xxx", "TenantId": "xxx", "Domain": "xxx.onmicrosoft.com", "SignedOutCallbackPath": "/signout/B2C_1A_SIGNIN", "SignedOutCallbackPathSignUp": "/signout/B2C_1A_SIGNUP", // 可选,对应注册策略的登出回调 "SignInPolicyId": "B2C_1A_SIGNIN", "SignUpPolicyId": "B2C_1A_SIGNUP", "SignInUrl": "/CustomIdentity/Account/SignIn?redirectUri={0}", "SignOutUrl": "/CustomIdentity/Account/SignOut?redirectUri={0}", "SignUpUrl": "/CustomIdentity/Account/SignUp?redirectUri={0}" }
4. 调试验证策略匹配(可选)
在OnAuthorizationCodeReceived事件中添加调试日志,确认当前使用的策略与ID Token的acr声明一致:
OnAuthorizationCodeReceived = context => { var idToken = context.ProtocolMessage.IdToken; var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(idToken); var acrClaim = jwtToken.Claims.FirstOrDefault(c => c.Type == "acr")?.Value; var currentPolicy = context.Properties.Items.TryGetValue(Constants.Policy, out string policy) ? policy : "Unknown"; // 输出日志用于调试 Console.WriteLine($"ACR Claim: {acrClaim}, Current Policy: {currentPolicy}"); if (context.Properties.Items.TryGetValue(Constants.Policy, out string policyValue)) { context.Options.Authority = $"{_configuration["AzureAdB2C:Instance"]}{_configuration["AzureAdB2C:TenantId"]}/{policyValue}/v2.0/"; } return Task.CompletedTask; }
内容的提问来源于stack exchange,提问作者Jeevan
相关产品推荐
相关产品推荐

