使用资源所有者密码在身份服务器中获取声明
Getting claims in identity server using resource owner password
我正在使用身份服务器 4 进行身份验证,授权类型为 'ResourceOwnerPassword'。我能够对用户进行身份验证,但无法获得与用户相关的声明。那么我怎样才能得到这些呢?
下面是我的代码
客户端
Startup.cs
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ApiName = "api1"
});
控制器
public async Task<IActionResult> Authentication(LoginViewModel model)
{
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(model.Email, model.Password, "api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
}
// Here I am not getting the claims, it is coming Forbidden
var extraClaims = new UserInfoClient(disco.UserInfoEndpoint);
var identityClaims = await extraClaims.GetAsync(tokenResponse.AccessToken);
if (!tokenResponse.IsError)
{
Console.WriteLine(identityClaims.Json);
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");
}
服务器
Startup.cs
services.AddIdentityServer()
.AddTemporarySigningCredential()
.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients(Configuration))
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<IdentityProfileService>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
Config.cs
public static IEnumerable<Client> GetClients(IConfigurationRoot Configuration)
{
// client credentials client
return new List<Client>
{
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AlwaysSendClientClaims = true,
AlwaysIncludeUserClaimsInIdToken = true,
AccessTokenType = AccessTokenType.Jwt
}
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}
但是当我在 jwt.io 中检查我的访问令牌时,我可以看到声明但是为什么我无法进入控制器?
感谢任何帮助!
尝试在调用 UserInfoEndpoint 时随请求发送令牌。试试这个:
var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint, token);
var response = await userInfoClient.GetAsync();
var claims = response.Claims;
您可以按照您的示例调用 UserInfoEndpoint
,但如果您将 ApiResource
定义为要求它们,您也可以获得额外的声明。
例如,而不是像这样定义您的 ApiResource
:
new ApiResource("api1", "My API")
您可以使用扩展格式并定义 UserClaims
在获取此范围的访问令牌时您希望拥有的内容。
例如:
new ApiResource
{
Name = "api1",
ApiSecrets = { new Secret(*some secret*) },
UserClaims = {
JwtClaimTypes.Email,
JwtClaimTypes.PhoneNumber,
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName,
JwtClaimTypes.PreferredUserName
},
Description = "My API",
DisplayName = "MyApi1",
Enabled = true,
Scopes = { new Scope("api1") }
}
然后在您自己的 IProfileService
实现中,您会发现对 GetProfileDataAsync
的调用有一个列表,其中列出了在上下文 (ProfileDataRequestContext.RequestedClaimTypes
) 中请求的声明。鉴于所要求的内容列表,您可以将任何您喜欢的声明添加到 context.IssuedClaims
中,您可以从该方法中添加 return。这些将成为访问令牌的一部分。
如果您只需要通过专门调用 UserInfo 端点来声明某些声明,您将需要创建一个 IdentityResource
定义并将该范围包含在您的原始令牌请求中。
例如:
new IdentityResource
{
Name = "MyIdentityScope",
UserClaims = {
JwtClaimTypes.EmailVerified,
JwtClaimTypes.PhoneNumberVerified
}
}
但是您的第一个问题是遵循此处的其他答案,因此您不会得到 'forbidden' 作为对 UserInfo 端点的响应!
我正在使用身份服务器 4 进行身份验证,授权类型为 'ResourceOwnerPassword'。我能够对用户进行身份验证,但无法获得与用户相关的声明。那么我怎样才能得到这些呢?
下面是我的代码
客户端
Startup.cs
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ApiName = "api1"
});
控制器
public async Task<IActionResult> Authentication(LoginViewModel model)
{
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(model.Email, model.Password, "api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
}
// Here I am not getting the claims, it is coming Forbidden
var extraClaims = new UserInfoClient(disco.UserInfoEndpoint);
var identityClaims = await extraClaims.GetAsync(tokenResponse.AccessToken);
if (!tokenResponse.IsError)
{
Console.WriteLine(identityClaims.Json);
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");
}
服务器 Startup.cs
services.AddIdentityServer()
.AddTemporarySigningCredential()
.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients(Configuration))
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<IdentityProfileService>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
Config.cs
public static IEnumerable<Client> GetClients(IConfigurationRoot Configuration)
{
// client credentials client
return new List<Client>
{
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AlwaysSendClientClaims = true,
AlwaysIncludeUserClaimsInIdToken = true,
AccessTokenType = AccessTokenType.Jwt
}
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}
但是当我在 jwt.io 中检查我的访问令牌时,我可以看到声明但是为什么我无法进入控制器?
感谢任何帮助!
尝试在调用 UserInfoEndpoint 时随请求发送令牌。试试这个:
var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint, token);
var response = await userInfoClient.GetAsync();
var claims = response.Claims;
您可以按照您的示例调用 UserInfoEndpoint
,但如果您将 ApiResource
定义为要求它们,您也可以获得额外的声明。
例如,而不是像这样定义您的 ApiResource
:
new ApiResource("api1", "My API")
您可以使用扩展格式并定义 UserClaims
在获取此范围的访问令牌时您希望拥有的内容。
例如:
new ApiResource
{
Name = "api1",
ApiSecrets = { new Secret(*some secret*) },
UserClaims = {
JwtClaimTypes.Email,
JwtClaimTypes.PhoneNumber,
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName,
JwtClaimTypes.PreferredUserName
},
Description = "My API",
DisplayName = "MyApi1",
Enabled = true,
Scopes = { new Scope("api1") }
}
然后在您自己的 IProfileService
实现中,您会发现对 GetProfileDataAsync
的调用有一个列表,其中列出了在上下文 (ProfileDataRequestContext.RequestedClaimTypes
) 中请求的声明。鉴于所要求的内容列表,您可以将任何您喜欢的声明添加到 context.IssuedClaims
中,您可以从该方法中添加 return。这些将成为访问令牌的一部分。
如果您只需要通过专门调用 UserInfo 端点来声明某些声明,您将需要创建一个 IdentityResource
定义并将该范围包含在您的原始令牌请求中。
例如:
new IdentityResource
{
Name = "MyIdentityScope",
UserClaims = {
JwtClaimTypes.EmailVerified,
JwtClaimTypes.PhoneNumberVerified
}
}
但是您的第一个问题是遵循此处的其他答案,因此您不会得到 'forbidden' 作为对 UserInfo 端点的响应!