在托管Blazor WebAssembly中为登录/注册配置不同Azure AD B2C用户流
配置独立的Azure AD B2C登录与注册用户流
一、客户端配置调整
1. 更新appsettings.json
将原合一流配置替换为包含两个独立策略的配置:
"AzureAdB2C": { "Instance": "https://***.b2clogin.com/", "Domain": "***.onmicrosoft.com", "ClientId": "****", "ValidateAuthority": false, "SignInPolicyId": "B2C_1_SIGN_IN", "SignUpPolicyId": "B2C_1_SIGN_UP" }
2. 改造登录/注册触发逻辑
在LoginDisplay.razor中拆分登录和注册操作,指定对应策略:
<AuthorizeView> <Authorized> Hello, @context.User.Identity.Name! <button class="nav-link btn btn-link" @onclick="Logout">Log out</button> </Authorized> <NotAuthorized> <button class="nav-link btn btn-link" @onclick="Login">Log in</button> <button class="nav-link btn btn-link" @onclick="SignUp">Sign up</button> </NotAuthorized> </AuthorizeView> @code { [Inject] private NavigationManager NavigationManager { get; set; } [Inject] private IAccessTokenProvider TokenProvider { get; set; } private async Task Login() { var authProps = new AuthenticationProperties { RedirectUri = NavigationManager.Uri, Items = { ["policy"] = "B2C_1_SIGN_IN" } }; await TokenProvider.LoginAsync(authProps); } private async Task SignUp() { var authProps = new AuthenticationProperties { RedirectUri = "/register-complete", Items = { ["policy"] = "B2C_1_SIGN_UP" } }; await TokenProvider.LoginAsync(authProps); } private async Task Logout() { var authProps = new AuthenticationProperties { RedirectUri = NavigationManager.Uri, Items = { ["policy"] = "B2C_1_SIGN_IN" } }; await TokenProvider.LogoutAsync(authProps); } }
二、服务器端配置调整
1. 更新appsettings.json
添加两个独立策略的配置项:
"AzureAdB2C": { "Instance": "https://***.b2clogin.com/", "ClientId": "***", "Domain": "**.onmicrosoft.com", "Scopes": "API.ReadWrite", "SignInPolicyId": "B2C_1_SIGN_IN", "SignUpPolicyId": "B2C_1_SIGN_UP" }
2. 配置多策略认证支持
在Program.cs中调整认证服务,允许两个策略的token通过验证:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAdB2C")) .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); // 配置多策略支持 builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options => { var instance = builder.Configuration["AzureAdB2C:Instance"]; var domain = builder.Configuration["AzureAdB2C:Domain"]; var signInPolicy = builder.Configuration["AzureAdB2C:SignInPolicyId"]; var signUpPolicy = builder.Configuration["AzureAdB2C:SignUpPolicyId"]; // 设置允许的颁发者列表 options.TokenValidationParameters.ValidIssuers = new[] { $"{instance}{domain}/{signInPolicy}/v2.0/", $"{instance}{domain}/{signUpPolicy}/v2.0/" }; });
三、注册后创建本地用户
1. 客户端注册完成回调页
创建RegisterComplete.razor页面,注册成功后调用API创建本地用户:
@page "/register-complete" @inject HttpClient Http @inject NavigationManager NavigationManager <h3>Completing Registration...</h3> @code { protected override async Task OnInitializedAsync() { try { // 获取当前用户身份信息 var userInfo = await Http.GetFromJsonAsync<UserInfo>("/api/userinfo"); // 调用后端API创建本地用户 await Http.PostAsJsonAsync("/api/local-users", new { UserId = userInfo.Sub, Email = userInfo.Email }); // 跳转至主页 NavigationManager.NavigateTo("/"); } catch { NavigationManager.NavigateTo("/error"); } } public class UserInfo { public string Sub { get; set; } public string Email { get; set; } } }
2. 服务器端API实现
添加两个API控制器,分别用于获取用户信息和创建本地用户:
// UserInfoController.cs [ApiController] [Route("api/[controller]")] [Authorize] public class UserInfoController : ControllerBase { [HttpGet] public IActionResult GetUserInfo() { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var email = User.FindFirstValue(ClaimTypes.Email); return Ok(new { Sub = userId, Email = email }); } } // LocalUsersController.cs [ApiController] [Route("api/[controller]")] [Authorize] public class LocalUsersController : ControllerBase { private readonly ApplicationDbContext _dbContext; public LocalUsersController(ApplicationDbContext dbContext) { _dbContext = dbContext; } [HttpPost] public async Task<IActionResult> CreateLocalUser([FromBody] LocalUserRequest request) { // 避免重复创建用户 var existingUser = await _dbContext.LocalUsers.FirstOrDefaultAsync(u => u.UserId == request.UserId); if (existingUser != null) return Ok(); var localUser = new LocalUser { UserId = request.UserId, Email = request.Email, CreatedAt = DateTime.UtcNow }; _dbContext.LocalUsers.Add(localUser); await _dbContext.SaveChangesAsync(); return Ok(); } public class LocalUserRequest { public string UserId { get; set; } public string Email { get; set; } } }
关键注意事项
- 确保Azure AD B2C后台已创建
B2C_1_SIGN_IN和B2C_1_SIGN_UP两个独立用户流,且客户端应用已在两个流中启用。 - 本地用户创建逻辑需保证幂等性,防止重复插入数据。
内容的提问来源于stack exchange,提问作者Haohan Yang
相关产品推荐
相关产品推荐

