Asp.net core 如何使Identity Server同时返回访问令牌和标识令牌?
我需要两者,因为我有很多声明,我想在客户端数据库中存储令牌,只使用没有声明的令牌(我想是identity one),在请求时,我将用大的替换小的(发送的,没有声明),这样请求就没有那么大了,我仍然可以使用声明进行API访问。当前仅返回访问令牌,标识令牌为空。以下是身份配置:Asp.net core 如何使Identity Server同时返回访问令牌和标识令牌?,asp.net-core,identityserver4,Asp.net Core,Identityserver4,我需要两者,因为我有很多声明,我想在客户端数据库中存储令牌,只使用没有声明的令牌(我想是identity one),在请求时,我将用大的替换小的(发送的,没有声明),这样请求就没有那么大了,我仍然可以使用声明进行API访问。当前仅返回访问令牌,标识令牌为空。以下是身份配置: public IdentityConfig(IConfiguration config) { ApiScopes = new List<ApiScope>(); Clien
public IdentityConfig(IConfiguration config)
{
ApiScopes = new List<ApiScope>();
Clients = new List<Client>();
foreach (var apiScope in config.GetSection("IdentityConfig").GetSection("ApiScopes").GetChildren())
{
ApiScopes.Add(new ApiScope(apiScope.Value));
}
foreach (var client in config.GetSection("IdentityConfig").GetSection("Clients").GetChildren())
{
Clients.Add(new Client
{
ClientId = client["Id"],
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,//can be moved to config
ClientSecrets = { new Secret(client["Secret"].Sha256()) },//can be multiple
AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, "apiScope1", IdentityServerConstants.StandardScopes.Profile }//client.GetSection("AllowedScopes").GetChildren().Select(a => a.Value).ToList()
});
}
Resources = new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email()
};
}
我之所以编写自定义密码验证器,是因为我有一个遗留系统,它有自己的auth实现,不确定是否需要,但只是以防万一:
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
try
{
var user = await _userRepository.FindByNameAsync(context.UserName);
if (user != null)
{
if (!string.IsNullOrWhiteSpace(user.LegacyPasswordHash))
{
var hashedPassword = GetLegacyHash(context.Password);
if (hashedPassword == user.LegacyPasswordHash)
{
context.Result = new GrantValidationResult(
subject: user.Id,
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
}
if (await _userRepository.CheckPasswordAsync(user, context.Password))
{
context.Result = new GrantValidationResult(
subject: user.Id,
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password");
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist.");
return;
}
catch (Exception ex)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
}
}
很难在代码中看到它,但看起来您可能会混淆身份验证和授权。你说你使用声明进行API访问,这在我看来像是授权,你能详细说明一下你在访问令牌中提出了什么样的声明吗?是的,我需要它们进行授权。声明类似于“CanUseThisApi”,我在启动时这样定义它们:auth.AddPolicy(“CanUseThisApi”,policy=>policy.Requirecall(“CanUseThisApi”);并添加类似于上述API的内容:[Authorize(Policy=“CanUseThisApi”)]为什么要使用AllowedGrantTypes=GrantTypes.ResourceOwnerPassword?一个想法是,只有在使用代码流时才包含它?老实说,我尝试了不同的东西,而这一个看起来像是做了我想要的——它返回了令牌。我应该用什么?
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
try
{
var user = await _userRepository.FindByNameAsync(context.UserName);
if (user != null)
{
if (!string.IsNullOrWhiteSpace(user.LegacyPasswordHash))
{
var hashedPassword = GetLegacyHash(context.Password);
if (hashedPassword == user.LegacyPasswordHash)
{
context.Result = new GrantValidationResult(
subject: user.Id,
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
}
if (await _userRepository.CheckPasswordAsync(user, context.Password))
{
context.Result = new GrantValidationResult(
subject: user.Id,
authenticationMethod: "custom",
claims: GetUserClaims(user));
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password");
return;
}
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist.");
return;
}
catch (Exception ex)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password");
}
}