ABP Framework 5.3.5添加外部OAuth认证及用户关联问题
ABP Framework 5.3.5 外部OAuth认证集成与内部用户关联问题解决
背景
应用基于ABP Framework 5.3.5开发,采用传统用户名/密码登录方式,内部通过AbpUsers表做身份验证,需要新增外部OAuth认证功能,并将外部登录用户关联到内部用户。
初始尝试与问题
最初编写的OAuth配置代码如下:
context.Services.AddAuthentication() .AddOAuth("...", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.ClientId = configuration["...:ClientId"]; options.ClientSecret = configuration["...:ClientSecret"]; options.AuthorizationEndpoint = configuration["...:AuthorizationEndpoint"]; options.CallbackPath = new PathString(configuration["...:CallbackPath"]); options.TokenEndpoint = configuration["...:TokenEndpoint"]; options.Scope.Add("..."); options.Events = new OAuthEvents() { OnCreatingTicket = async context => { var email = context.TokenResponse.Response.RootElement.GetProperty("userinfo").GetProperty("email").ToString(); context.Identity.AddClaim(new Claim(ClaimTypesEnum.UserEmail.GetDescription(), email)); Console.WriteLine(email); // TODO Link external user to internal, authorize user as internal user } }; });
这段代码能完成基础OAuth流程:引导用户到外部OAuth服务登录、携带授权码重定向回Identity Server并获取令牌,但用户最终会回到Identity Server登录界面,无法完成内部用户关联与授权。同时在OnCreatingTicket事件中尝试获取UserManager和SignInManager时遇到阻碍。
中间尝试的报错情况
- 尝试直接获取内部用户并登录时,出现错误:
The navigation 'IdentityUser.Claims' cannot be loaded because the entity is not being tracked. Navigations can only be loaded for tracked entities.
- 2024-06-11更新代码后出现警告:
External login info is not available.,排查发现SignInManager中await this.Context.AuthenticateAsync(IdentityConstants.ExternalScheme)返回null。
最终解决代码
2024-06-12更新后的代码解决了所有问题:
context.Services.AddAuthentication() .AddOAuth("...", options => { options.SignInScheme = IdentityConstants.ExternalScheme; options.ClientId = configuration["...:ClientId"]; options.ClientSecret = configuration["...:ClientSecret"]; options.AuthorizationEndpoint = configuration["...:AuthorizationEndpoint"]; options.CallbackPath = new PathString(configuration["...:CallbackPath"]); options.TokenEndpoint = configuration["...:TokenEndpoint"]; options.Scope.Add("...:auth ...:userinfo"); options.Events = new OAuthEvents() { OnCreatingTicket = async context => { var userInfo = context.TokenResponse.Response.RootElement.GetProperty("userinfo"); var email = userInfo.GetProperty("email").ToString(); var sub = userInfo.GetProperty("sub").ToString(); context.Principal.Identities.First().AddClaim(new Claim(ClaimTypes.NameIdentifier, sub)); context.Principal.Identities.First().AddClaim(new Claim(ClaimTypes.Email, email)); } }; });
关键修改点
- 调整SignInScheme:将
IdentityServerConstants.ExternalCookieAuthenticationScheme替换为IdentityConstants.ExternalScheme,确保外部认证信息能被ABP的Identity模块正确识别。 - 完善Scope配置:添加了包含用户信息和权限的Scope(
...:auth ...:userinfo),确保能获取到完整的用户身份数据。 - 添加标准声明:在
OnCreatingTicket中,为Principal.Identity添加标准的ClaimTypes.NameIdentifier(对应外部用户的sub)和ClaimTypes.Email声明,替代之前的自定义Claim类型,让ABP能正确关联内部用户。
内容的提问来源于stack exchange,提问作者user25472340
相关产品推荐
相关产品推荐

