繁体   English   中英

IdentityServer4 - 缺少来自 Google 的声明

[英]IdentityServer4 - missing claims from Google

TLDR; 在使用 IdentityServer4 的上下文中

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

我已经完成了 IdentityServer 快速入门,并且有一个工作的 MVC 客户端与 IdentityServer 实例通信(如果使用了错误的术语,请致歉)。 我正在使用外部身份验证(Google)并且没有任何稍微复杂的东西,例如本地登录/数据库等。我没有使用 ASP.NET 身份。 这一切都很好。

我可以在我的 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>

在此处输入图像描述

问题:

  1. 我无法从 Google 检索额外的声明(正确的术语?)。 特别是“高清”甚至“电子邮件”——请注意,它们没有出现在上面屏幕截图的声明中。 如何从 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;
});

身份服务器

客户端定义

// 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"
    }
}

身份资源定义

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"}
    } 
};

答案出奇地不明显:只要您具有以下配置(在 Identity Server Startup.cs 中),IdentityServer4 提供的示例代码就可以工作:

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

为什么? 因为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

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

我可以告诉你如何让电子邮件被退回。

有两种方法可以做到这一点,但它们都要求您将电子邮件范围添加到初始请求中。 只是发送 openId 是行不通的。

打开电子邮件

用户信息请求

现在,当您取回访问令牌时,您可以执行

https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token={access token}

回复

{
  "family_name": "Lawton", 
  "name": "Linda Lawton", 
  "picture": "https://lh5.googleusercontent.com/-a1CWlFnA5xE/AAAAAAAAAAI/AAAAAAAAl1I/UcwPajZOuN4/photo.jpg", 
  "gender": "female", 
  "email": "xxxx@gmail.com", 
  "link": "https://plus.google.com/+LindaLawton", 
  "given_name": "Linda", 
  "id": "117200475532672775346", 
  "verified_email": true
}

令牌信息请求:

使用 id 令牌

 https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={token id}

回复

{
 "azp": "07408718192.apps.googleusercontent.com",
 "aud": "07408718192.apps.googleusercontent.com",
 "sub": "00475532672775346",
 "email": "XX@gmail.com",
 "email_verified": "true",
 "at_hash": "8ON2HwraMXbPpP0Nwle8Kw",
 "iss": "https://accounts.google.com",
 "iat": "1509967160",
 "exp": "1509970760",
 "alg": "RS256",
 "kid": "d4ed62ee21d157e8a237b7db3cbd8f7aafab2e"
}

至于如何填充您的控制器,我对此无能为力。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM