Reputation: 12147
I'm usin ROPC flow with IdentityServer4 with ASP.NET Core Identity where I need to send username and password to /connect/token endpoint to get access_token.
How to configure IdentityServer4 to accept either Username or Email, and password in /connect/token requests?
PS: asp.net core: 2.0.2 IdentityServer4: 2.0.2
Upvotes: 4
Views: 1188
Reputation: 2052
You need to override the ValidateAsync by creating the Custom PasswordValidator class which implement IResourceOwnerPasswordValidator interface like below.
public class OwnerPasswordValidatorService : IResourceOwnerPasswordValidator
{
public UserManager<ApplicationUser> _userManager { get; }
public OwnerPasswordValidatorService(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
var user = await _userManager.FindByNameAsync(context.UserName);
if (user == null)
{
user = await _userManager.FindByEmailAsync(context.UserName);
if (user == null)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Username or password is incorrect");
return;
}
}
var passwordValid = await _userManager.CheckPasswordAsync(user, context.Password);
if (!passwordValid)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Username or password is incorrect");
return;
}
context.Result = new GrantValidationResult(subject: context.UserName, authenticationMethod: "custom");
}
}
Then configure your dependency for your custom class like below.
services.AddIdentityServer()
.AddDeveloperSigningCredential()
...
.AddAspNetIdentity<ApplicationUser>()
.AddResourceOwnerValidator<OwnerPasswordValidatorService>() //here
.AddProfileService<ProfileService>();
If any one still cannot make it work let me know. I will be happy to help.
Upvotes: 0
Reputation: 12147
Found this solution:
1) Copy file IdentityServer4.AspNetIdentity/src/IdentityServer4.AspNetIdentity/ResourceOwnerPasswordValidator.cs to your project from https://github.com/IdentityServer/IdentityServer4.AspNetIdentity/blob/dev/src/IdentityServer4.AspNetIdentity/ResourceOwnerPasswordValidator.cs
2) Fix ValidateAsync method to find user with email
var user = await _userManager.FindByNameAsync(context.UserName);
if (user == null) {
user = await _userManager.FindByEmailAsync(context.UserName);
}
3) Add Validator to IS4:
.AddAspNetIdentity<AppUser>()
.AddResourceOwnerValidator<Services.ResourceOwnerPasswordValidator<AppUser>>();
4) Profit!
Upvotes: 5