将 IdentityServer4 与资源所有者密码流和 asp.net Identity 一起使用时,登录失败时它始终返回相同的错误消息。密码是否无效或用户是否已被锁定并不重要。
{
"error": "invalid_grant",
"error_description": "invalid_username_or_password"
}
以下是身份和身份服务器的配置:
services.AddIdentityCore<User>()
.AddEntityFrameworkStores<ApplicationDBContext>()
.AddDefaultTokenProviders()
.AddUserManager<UserManager<User>>()
.AddSignInManager<ApplicationSignInManager>();
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddAspNetIdentity<User>();
由于我使用具有 asp.net 标识的资源所有者密码流,因此没有针对登录用户的自定义用户服务。那么如何根据登录过程中发生的情况显示错误消息呢?
以下是它对我的工作方式:
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
public class CustomResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
private readonly CustomUserRepository _repository;
public CustomResourceOwnerPasswordValidator(CustomUserRepository repository)
{
_repository = repository;
}
// https://docs.identityserver.io/en/latest/topics/resource_owner.html
public async System.Threading.Tasks.Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
var user = await _repository.FindUser(context.UserName, context.Password);
if (user != null)
{
var passwordHasher = new PasswordHasher();
var result = passwordHasher.VerifyHashedPassword(user.User.Password, context.Password);
// https://docs.identityserver.io/en/latest/reference/grant_validation_result.html#refgrantvalidationresult
if (result)
{
context.Result = new GrantValidationResult(subject: user.Id, authenticationMethod: "password");
}
else
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid password");
}
}
else
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid user");
}
}
}
这是在启动时注册的.cs:
var builder = services
.AddIdentityServer()
.AddSigningCredential(certificate)
.AddInMemoryIdentityResources(Resources.Get())
.AddInMemoryClients(Clients.Get(baseUri))
.AddValidationKey(certificate)
.AddProfileService<ProfileService>();
.AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>();
对我来说,要让它工作,我不需要在注册步骤结束时包含.AddAspNetIdentity<User>();
。