如何基于Microsoft Identity Web App平台实现新用户注册?
我们有一个旧版Web应用,使用ASP.NET Identity框架进行身份验证,通过本地aspnet系列数据库表存储用户信息、角色等,注册新用户操作十分简便。
现在上线了新应用,采用OIDC、Microsoft Identity Web App和Microsoft Graph架构。目前了解到添加新用户需要到Azure AD中操作,但这个新应用是给其他公司客户使用的,这些客户都有自己独立的登录组织,且应用注册已设置为接受任意组织。之前旧应用只需要通过邮箱创建账号,用户就能用邮箱和密码完成认证,但我不清楚在新架构下该怎么实现类似的流程。
查阅资料得知需要在Azure应用注册中管理角色和声明,但我没有Azure AD的登录权限,也不想所有内容都通过Azure来管理。我在VS中选择Web应用模板创建新应用,当前认证代码如下:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph")) .AddInMemoryTokenCaches();
请问是否存在如下旧ASP.NET Identity代码的等效实现,还是必须通过Azure应用注册来管理所有内容?
services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<UnitRateContractSystemContext>() .AddDefaultTokenProviders() .AddUserStore<UserStore<ApplicationUser, ApplicationRole, UnitRateContractSystemContext, Guid, ApplicationUserClaim<Guid>, ApplicationUserRole, IdentityUserLogin<Guid>, IdentityUserToken<Guid>, IdentityRoleClaim<Guid>>>() .AddRoleStore<RoleStore<ApplicationRole, UnitRateContractSystemContext, Guid, ApplicationUserRole, IdentityRoleClaim<Guid>>>();
你不需要完全依赖Azure AD管理用户和角色,有两种方案可以实现类似旧ASP.NET Identity的本地管理逻辑:
1. 混合认证模式:同时支持Azure AD OIDC和本地ASP.NET Identity
直接在新应用中同时配置两种认证方案,既保留Azure AD登录能力,又沿用本地数据库管理用户、角色的逻辑:
// 配置本地ASP.NET Identity,和旧代码逻辑一致 builder.Services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<UnitRateContractSystemContext>() .AddDefaultTokenProviders() .AddUserStore<UserStore<ApplicationUser, ApplicationRole, UnitRateContractSystemContext, Guid, ApplicationUserClaim<Guid>, ApplicationUserRole, IdentityUserLogin<Guid>, IdentityUserToken<Guid>, IdentityRoleClaim<Guid>>>() .AddRoleStore<RoleStore<ApplicationRole, UnitRateContractSystemContext, Guid, ApplicationUserRole, IdentityRoleClaim<Guid>>>(); // 配置Azure AD OIDC认证 builder.Services.AddAuthentication() .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph")) .AddInMemoryTokenCaches(); // 可选:设置默认认证方案,根据业务需求调整 builder.Services.Configure<AuthenticationOptions>(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; });
这种模式下,用户既可以选择用本地账号注册登录,也可以通过所属组织的Azure AD登录,完全不需要在Azure后台管理用户和角色。
2. 自定义OIDC用户存储与角色映射
如果只想保留OIDC登录,但不想依赖Azure AD管理角色,可以在本地数据库维护用户(关联Azure AD的objectId)和角色信息,在OIDC回调时动态加载角色到Claims中:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(options => { builder.Configuration.Bind("AzureAd", options); // 验证令牌后触发自定义逻辑 options.Events.OnTokenValidated = async context => { // 获取Azure AD返回的用户唯一标识 var userId = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier); // 从本地数据库查询该用户的角色 var roleService = context.HttpContext.RequestServices.GetRequiredService<IRoleService>(); var roles = await roleService.GetUserRolesAsync(userId); // 将角色添加到当前用户的Claims集合 var claimsIdentity = context.Principal.Identity as ClaimsIdentity; foreach (var role in roles) { claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role)); } }; }) .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph")) .AddInMemoryTokenCaches();
这种方式下,用户通过Azure AD完成身份验证,但角色、额外用户信息完全由本地数据库管理,不需要在Azure应用注册中配置任何角色声明。
关键说明
- 如果你不需要Azure AD的企业级特性(比如跨组织单点登录),完全可以放弃Microsoft Identity Web集成,直接沿用旧版纯ASP.NET Identity的实现;
- 两种方案都不需要你拥有Azure AD的管理权限,所有用户、角色的管理逻辑都在你的应用和本地数据库中完成。
内容的提问来源于stack exchange,提问作者Andrew Casey

