0

我试图更改IdentityServer4 AspNetIdentity示例以便能够从本地创建的用户和Google登录。当通过Google OAuth登录时使用IProfileService

我能够加入谷歌认证要做到这一点:

 app.UseIdentity(); 
     app.UseIdentityServer(); 

     var cookieScheme = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value.Cookies.ExternalCookieAuthenticationScheme; 

     // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715 
     app.UseGoogleAuthentication(new GoogleOptions 
     { 
      AuthenticationScheme = "Google", 
      SignInScheme = cookieScheme, 
      ClientId = "client_id", 
      ClientSecret = "client_secret" 
     }); 

正如预期的那样在主页视图显示正确的用户声明:

sub 
c51da331-0348-45dd-352f-08d4526f6266 
name 
[email protected] 
AspNet.Identity.SecurityStamp 
568a167f-a431-4f70-ba66-918f99e95eef 
idp 
Google 
amr 
external 
auth_time 
1486815555 

在使用谷歌账户在首次用户登录我向数据库添加了一些信息,我想我可以通过使用自定义IProfileService实现并将IdentityServer配置为使用我的自定义IProfileService将它们添加到用户声明中:

  var builder = services.AddIdentityServer(); 
     builder.AddTemporarySigningCredential(); 

     builder.AddConfigurationStore(b => b.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationAssembly))); 
     builder.AddOperationalStore(b => b.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationAssembly))); 
     builder.AddAspNetIdentity<MyUser>(); 
     builder.AddProfileService<MyCustomProfileService>(); 

但现在,当我导航到主页时,用户声明保持不变,甚至GetProfileDataAsync方法也不会发生。

我很感激有人能告诉我这是什么感觉。

回答

2

事实证明,除非(如@Set所述)直接调用UserInfo端点,否则IdentityServer将不会使用IProfileService来添加自定义声明,前提是它将配置为使用ASP.NET标识库。设计方法是使用ASP.NET Identity机制通过注册IUserClaimsPrincipalFactory来创建索赔。

在这种情况下,我们可以创建IUserClaimsPrincipalFactory的自定义实现或因为ASP.NET身份将加载存储在数据库中的任何附加要求,添加使用UserManager类的AddClaimsAsync方法,任何额外的要求。

2

根据github上Adding Custom Claims to an ASPNET Core Identity Implementation的讨论,GetProfileDataAsync方法仅在需要将标记放入标记时调用。此外,它有一个链接到Optimizing Identity Tokens for size后解释,这 IdentityServer默认有行为相应地ID连接规范中,提出以下建议(5.4节):

由配置文件要求的索赔,电子邮件,地址,如第5.3.2节所述,当使用response_type值导致发出访问令牌时,UserInfo端点将返回电话范围值。但是,如果没有访问令牌发出(response_type值为id_token的情况),则会在ID令牌中返回结果声明。

换句话说,如果只请求身份标记,则将所有声明放入标记中。但是,如果还要求访问令牌,请从身份令牌中移除声明,并让客户端使用userinfo端点来检索它们。

但是,可以通过在客户端配置(更多this)上设置AlwaysIncludeUserClaimsInIdToken标志来覆盖此默认行为。