问题描述
我终于成功地使用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"
}
在我看来,您应该在响应中只包含短名称限定符(email
、name
、sub
、phone
),对吗?但是,如果我重新安排,来自/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返回。
- This is the place where IdentityServer is being configured
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接口。
更多信息:
- Mapping, customizing, and transforming claims in ASP.NET Core
这篇关于外部登录需要名称标识符声明才能成功。如何删除令牌中的重复密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!