asp.net-corethinktecture-ident-serveridentityserver4

Validating Against credentials Custom Users DB - IResourceOwnerPasswordValidator


I am using Identity Server 4 and implemented the following two interfaces:

IResourceOwnerPasswordValidator: for the purpose of validating user credentials against my custom DB

public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
    private IUserRepository _userRepository;

    public ResourceOwnerPasswordValidator(IUserRepository userRepository)
    {
        this._userRepository = userRepository;
    }

    public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        var isAuthenticated = _userRepository.ValidatePassword(context.UserName, context.Password);

       //code is omitted for simplicity                
    }
}

IProfileService: for getting necessary claims

 public class ProfileService : IdentityServer4.Services.IProfileService
{
    public IUserRepository _userRepository;
    public ProfileService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        //code is ommitted
    }

Then added then necessary Interfaces and dependencies to the services in Startup class. I have also modified the Account Controller by injecting the login service which has the following implementation:

   public class LoginService
{
    private readonly IUserRepository _userRepository;
    public LoginService( IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }
    public bool ValidateCredentials(string username, string password)
    {
        return _userRepository.ValidatePassword(username, password);
    }

The AccountController "Login" Action validate for the credentials by calling:

 if (_loginService.ValidateCredentials(model.Username, model.Password))
        {
           var user = _loginService.FindByUsername(model.Username);
           await HttpContext.Authentication.SignInAsync(user.Subject, user.Username);
             //other code is omitted  


               

When debugging the project the Login Action of AccountContoller is called, then my login service. After validating the user credentials, the consent page is displayed, which trigger the ProfileService GetProfileDataAsync Method.

However, the ResourceOwnerPasswordValidator was never called. Am I Implementing the LoginService in the correct manner or should I replace the IUserRepository injected by IResourceOwnerPasswordValidation then call the "ValidateAsync" method in Login Service ValidateCredentails?

And if that was the case, what is the advantage of passing that to LoginService, since I am already validating users in this way?


Solution

  • According to docs:

    If you want to use the OAuth 2.0 resource owner password credential grant (aka password), you need to implement and register the IResourceOwnerPasswordValidator interface:

    Since you don't use password grant, expected behaviour is to not call ResourceOwnerPasswordValidator. For your case you don't need ResourceOwnerPasswordValidator implementation.