外部登录需要名称标识符声明才能成功。如何删除令牌中的重复密钥 [英] nameidentifier claim is required for external login to succeed. How to remove duplicate keys in token

查看:89
本文介绍了外部登录需要名称标识符声明才能成功。如何删除令牌中的重复密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于成功地使用IdentityServer4设置了一个项目,允许用户使用单个帐户登录到多个应用程序。然而,我觉得事情并不完全是这样的。

这是我的OAuthOptions

public class CentralOptions : OAuthOptions
{
    public CentralOptions()
    {
        ClaimsIssuer = "https://localhost:44359";
        CallbackPath = new Microsoft.AspNetCore.Http.PathString("/signin-central");
        AuthorizationEndpoint = "https://localhost:44359/connect/authorize";
        TokenEndpoint = "https://localhost:44359/connect/token";
        UserInformationEndpoint = "https://localhost:44359/connect/userinfo";

        Scope.Add("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
        Scope.Add("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");
        Scope.Add("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
        Scope.Add("openid");
        Scope.Add("profile");
        Scope.Add("email");
        Scope.Add("phone");
        Scope.Add("role");
        Scope.Add("weatherforecasts.read");
        Scope.Add("weatherforecasts.write");

        UsePkce = true;
        ClaimActions.MapJsonKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "sub");
        ClaimActions.MapJsonKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "name");
        ClaimActions.MapJsonKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "email");

        //ClaimActions.MapJsonKey("sub", "sub");
        //ClaimActions.MapJsonKey("name", "name");
        //ClaimActions.MapJsonKey("email", "email");
    }
}
如您所见,现在我必须复制RequestedClaims,一次用于实际的声明类型,一次用于某个短名称。我调整数据库的内容已经有一段时间了,但我想不出我必须更改什么才能只拥有一次声明(我认为http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress不应该出现在持有者令牌中,而email应该出现在其中。但如果我更改数据库和应用程序中的声明,登录将失败,因为它依赖the ClaimTypes.NameIdentifier claim to be present in the bearer token

我登录后,IS会给我一个访问令牌,例如:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjVCOTBDN0JBNkExMjI2RjEyMEU0QzJGOEQzMjIwMzAxIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE2MzcxNzkxNDAsImV4cCI6MTYzNzI2NTU0MCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNTkiLCJhdWQiOiJ3ZWF0aGVyZm9yZWNhc3RzIiwiY2xpZW50X2lkIjoiU3NvQXBwbGljYXRpb25DbGllbnQiLCJjZW50cmFsLXRoZWNsaWVudCI6IlRoZSBTU08gY2xpZW50Iiwic3ViIjoiOTU5YzliZmEtZWQzMC00NjM4LTk5ODYtNjNjZjE1ODllZmY4IiwiYXV0aF90aW1lIjoxNjM3MTc5MTM3LCJpZHAiOiJsb2NhbCIsImVtYWlsIjoicGlldGVyamFuQGV4YW1wbGUuY29tIiwibmFtZSI6IlBpZXRlcmphbiIsImlkIjoiOTU5YzliZmEtZWQzMC00NjM4LTk5ODYtNjNjZjE1ODllZmY4IiwicGhvbmUiOiIrMzIxMjMvNDUuNjcuODkiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiUGlldGVyamFuIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZW1haWxhZGRyZXNzIjoicGlldGVyamFuQGV4YW1wbGUuY29tIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbW9iaWxlcGhvbmUiOiIrMzIxMjMvNDUuNjcuODkiLCJqdGkiOiI3RjA0QTA5MDM3MUNEMjQ2MENCQzg3OUY3MDEwOTU1MyIsInNpZCI6IjA0NDYzRDlBRDNENDRCNUExQTNCQTRFOTczRUE5OTI4IiwiaWF0IjoxNjM3MTc5MTQwLCJzY29wZSI6WyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiLCJvcGVuaWQiLCJwcm9maWxlIiwiZW1haWwiLCJwaG9uZSIsInJvbGUiLCJ3ZWF0aGVyZm9yZWNhc3RzLnJlYWQiLCJ3ZWF0aGVyZm9yZWNhc3RzLndyaXRlIl0sImFtciI6WyJwd2QiXX0.KBKLezXnUs6s-bU9hme7Ab7ADZN8DEewqfUncDwR0c2_LFqAnyCw3IZ85VJC4t-NN6xJYu8ROk-cX9PDKIQzEAOWGkOrQuqeaspKfIpl_rCq4qbP7x7uflToqPO245iU6xlzxVnGuaG1o_sSILNQA_YZJV8nsmXJkdB2QonuCZwvrBh5URFXV5cZpivlWznJls9eqfRM9MjlRpWe-NCI6I7FExfCaRgPZ4b1XwyrmmQWNlaKJOmIM3qag1pQshdXBSzg3w65htj89zOKKWSNl6Go6Q_0pZzbv0FLcMUMR_GTzuw56_CFobavD40T65wQQlXxf0cfkzbrdyAx7k8tyg

解码后如下所示

{
  "alg": "RS256",
  "kid": "5B90C7BA6A1226F120E4C2F8D3220301",
  "typ": "at+jwt"
}
{
  "nbf": 1637179140,
  "exp": 1637265540,
  "iss": "https://localhost:44359",
  "aud": "weatherforecasts",
  "client_id": "SsoApplicationClient",
  "central-theclient": "The SSO client",
  "sub": "959c9bfa-ed30-4638-9986-63cf1589eff8",
  "auth_time": 1637179137,
  "idp": "local",
  "email": "pieterjan@example.com",
  "name": "Pieterjan",
  "id": "959c9bfa-ed30-4638-9986-63cf1589eff8",
  "phone": "+32123/45.67.89",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "Pieterjan",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "pieterjan@example.com",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone": "+32123/45.67.89",
  "jti": "7F04A090371CD2460CBC879F70109553",
  "sid": "04463D9AD3D44B5A1A3BA4E973EA9928",
  "iat": 1637179140,
  "scope": [
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
    "openid",
    "profile",
    "email",
    "phone",
    "role",
    "weatherforecasts.read",
    "weatherforecasts.write"
  ],
  "amr": [
    "pwd"
  ]
}

使用此令牌可以向

发送请求
https://localhost:44359/connect/userinfo

这将给出以下响应

{
    "email": "pieterjan@example.com",
    "name": "Pieterjan",
    "id": "959c9bfa-ed30-4638-9986-63cf1589eff8",
    "phone": "+32123/45.67.89",
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "Pieterjan",
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "pieterjan@example.com",
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone": "+32123/45.67.89",
    "sub": "959c9bfa-ed30-4638-9986-63cf1589eff8"
}
在我看来,您应该在响应中只包含短名称限定符(emailnamesubphone),对吗?但是,如果我重新安排,来自/connect/userinfo的响应将不包含http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name声明,并且登录将在following line失败,following line在来自此UserInfo终结点的响应中查找确切的声明,因此将失败。

我猜我必须调整当前显示为以下内容的OAuthOptions.ClaimActions

ClaimActions.MapJsonKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "sub");
ClaimActions.MapJsonKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "name");
ClaimActions.MapJsonKey("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "email");

我已经在尝试使用它们了,但最轻微的修改都会导致所有声明不再从IdentityServer返回。

dbo.Clients

dbo.ClientGrantType

=client.allowedGrantTypes

dbo.ClientSecret

=client.ClientSecrets

dbo.ClientScope

=client.AllowedScopes

在这里您可以看到,我现在的作用域可能不应该在数据库中,因为它们实际上是声明类型,但如果我删除它们,NameIdentifier声明类型将不会出现在标识中。

dbo.ClientRedirectUri

=client.RedirectUris

dbo.ClientClaim

=client.Claims

dbo.IdentityResources

dbo.IdentityResourceClaim

=identityResource.UserClaims

其中的标记为:

List of associated user claims that should be included when this resource is requested.

很明显,我必须引入双行才能使外部登录开始工作。

dbo.AspNetUser

dbo.AspNetUserClaims

=user.Claims

如何正确设置我的代码和数据库,以便不再需要那些重复的声明才能使我的应用程序工作/我的外部登录成功?

另外,声明应该在数据库级别保存,还是generated during login

提前谢谢。

Git repository

推荐答案

我将只在标识服务器中使用较短的声明名称,并在客户端中执行必要的声明转换或映射。

我会考虑使用MapUniqueJsonKey:

在客户端或API中进行转换
options.ClaimActions.MapUniqueJsonKey("website", "website");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
options.ClaimActions.MapUniqueJsonKey("birthdate", "birthdate");

我认为在身份验证之后(但在授权之前)了解Claims主体用户对象包含的内容很重要。

有关更高级的转换需求,请务必查看使用IClaimsConvertion接口。

更多信息:

这篇关于外部登录需要名称标识符声明才能成功。如何删除令牌中的重复密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆