IdentityServer4-缺少Google的声明

han*_*rld 2 c# google-oauth asp.net-core identityserver4

TLDR;在使用IdentityServer4的上下文中

  1. 您如何从Google获得电子邮件地址和高清声明?
  2. 如何获取要填充的User.Identity.Name?

我已经完成了IdentityServer 快速入门,并且有一个正在工作的MVC客户端与IdentityServer实例进行对话(如果使用错误的术语,则表示歉意)。我正在使用外部身份验证(Google),并且没有任何复杂的问题,例如本地登录名/数据库等。我没有在使用ASP.NET Identity。这一切都很好。

我可以在我的MVC应用中成功进行身份验证,并且以下代码在以下屏幕截图中产生了声明:

@foreach (var claim in User.Claims)
{
    <dt>@claim.Type</dt>
    <dd>@claim.Value</dd>
}
<dt>Identity.Name</dt>
<dd>&nbsp;@User.Identity.Name</dd>

<dt>IsAuthenticated</dt>
<dd>@User.Identity.IsAuthenticated</dd>
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

问题:

  1. 我无法从Google检索其他索赔(正确的字词?)。特别是“ hd”或“ email”-请注意,它们没有出现在上述屏幕截图的声明中。如何获得Google的电子邮件地址和高清声明?我想念什么或做错什么?
  2. 请注意,User.Identity.Name的输出为空。为什么会这样,如何填充呢?这似乎是未设置的User.Identity的唯一属性。

我的设置如下-您可以看到上面的输出:

客户(MVC)

在Startup.cs中,ConfigureServices

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
    options.SignInScheme = "Cookies";
    options.Authority = Configuration["App:Urls:IdentityServer"];
    options.RequireHttpsMetadata = false;
    options.Resource = "openid profile email";
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("email");
    options.Scope.Add("domain");
    options.ClientId = "ctda-web";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
});
Run Code Online (Sandbox Code Playgroud)

身份服务器

客户定义

// OpenID Connect implicit flow client (MVC)
new Client
{
    ClientId = "ctda-web",
    ClientName = "Company To Do Web App",
    AllowedGrantTypes = GrantTypes.Implicit,
    EnableLocalLogin = false,

    // where to redirect to after login
    RedirectUris = { "http://localhost:53996/signin-oidc" },

    // where to redirect to after logout
    PostLogoutRedirectUris = { "http://localhost:53996/signout-callback-oidc" },

    AllowedScopes = new List<string>
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email,
        "domain"
    }
}
Run Code Online (Sandbox Code Playgroud)

IdentityResource定义

return new List<IdentityResource>
{
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResources.Email(),
    new IdentityResource
    {
        Name = "domain",
        DisplayName = "Google Organisation",
        Description = "The hosted G Suite domain of the user, if part of one",
        UserClaims = new List<string> { "hd"}
    } 
};
Run Code Online (Sandbox Code Playgroud)

han*_*rld 5

答案令人惊讶地不清楚:只要您具有以下配置(在Identity Server Startup.cs中),IdentityServer4提供的示例代码就可以工作:

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryClients(Config.GetClients()
    .AddTestUsers(Config.GetUsers()); //<--- this line here
Run Code Online (Sandbox Code Playgroud)

为什么?因为AddTestUsers正在做很多事情,所以您需要在自己的世界中做。本演练暗中假定您移至EF或ASP.NET Identity等,并且不清楚如果您不打算使用这些数据存储时该做什么。简而言之,您需要:

  1. 创建一个代表用户的对象(这是一个入门者
  2. 创建一个持久性/查询类(这是一个入门
  3. 创建一个IProfileService实例,将其联系在一起,输入您对User和UserStore的定义(这里是一个入门工具
  4. 添加适当的绑定等

我的IdentityServer Startup.cs最终看起来像这样(我想在内存中故意做,但显然不使用示例中提供的测试用户):

services.AddSingleton(new InMemoryUserStore()); //<-- new

services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryClients(Config.GetClients())
    .AddProfileService<UserProfileService>(); //<-- new
Run Code Online (Sandbox Code Playgroud)

事实证明Google确实将电子邮件作为索赔的一部分。问题的代码示例中的范围有效。