Initial ...
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using IdentityServer4.Events;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Services;
|
||||
using IdentityServer4.Validation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using xCommons.Extensions;
|
||||
using xExceptions.Constants;
|
||||
using xIdentityModels.Navigations;
|
||||
using xIds.Interfaces;
|
||||
using static IdentityModel.OidcConstants;
|
||||
|
||||
namespace xIds.Validators
|
||||
{
|
||||
public class XResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
|
||||
{
|
||||
private readonly IXIdentityManager identityManager;
|
||||
private readonly IEventService events;
|
||||
private readonly ILogger<XResourceOwnerPasswordValidator> logger;
|
||||
|
||||
public XResourceOwnerPasswordValidator(
|
||||
IXIdentityManager identityProvider,
|
||||
IEventService events,
|
||||
ILogger<XResourceOwnerPasswordValidator> logger
|
||||
)
|
||||
{
|
||||
this.identityManager = identityProvider;
|
||||
this.events = events;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the resource owner password credential
|
||||
/// by providing UserName/Email or PhoneNumber
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
|
||||
{
|
||||
//
|
||||
var clientId = context.Request?.Client?.ClientId;
|
||||
var xUser = await identityManager.GetUserAsync(context.UserName, true);
|
||||
|
||||
//
|
||||
// Check Force Data ...
|
||||
var isForced = true;
|
||||
var isForcedStr = context.Request?.Raw["force"];
|
||||
if (!isForcedStr.IsNullOrEmpty())
|
||||
{
|
||||
isForced = isForcedStr.FromJSON<bool>();
|
||||
}
|
||||
|
||||
//
|
||||
XDevice device = null;
|
||||
var language = context.Request?.Raw["language"];
|
||||
var deviceStr = context.Request?.Raw["device"];
|
||||
if (deviceStr.IsNullOrEmpty() && isForced)
|
||||
{
|
||||
//
|
||||
logger.LogError($"Device not Found ...");
|
||||
|
||||
//
|
||||
await events
|
||||
.RaiseAsync(
|
||||
new UserLoginFailureEvent(
|
||||
xUser.UserName,
|
||||
XException.InvalidDevice.ToXError().Message,
|
||||
false,
|
||||
clientId
|
||||
));
|
||||
return;
|
||||
}
|
||||
device = isForced ? deviceStr.FromJSON<XDevice>() : null;
|
||||
|
||||
//
|
||||
XException exception;
|
||||
if (!xUser.IsNull())
|
||||
{
|
||||
//
|
||||
var result = await identityManager
|
||||
.CheckPasswordSignInAsync(
|
||||
xUser,
|
||||
context.Password,
|
||||
device,
|
||||
language,
|
||||
true,
|
||||
isForced
|
||||
);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
//
|
||||
logger.LogInformation("Credentials validated for username: {username}", xUser.UserName);
|
||||
|
||||
//
|
||||
// Update User Last Login ...
|
||||
xUser.LastLogin = DateTime.UtcNow;
|
||||
await identityManager.UpdateUserAsync(xUser);
|
||||
|
||||
//
|
||||
await events.RaiseAsync(
|
||||
new UserLoginSuccessEvent(
|
||||
xUser.UserName, xUser.Id, xUser.UserName, false, clientId
|
||||
));
|
||||
|
||||
//
|
||||
context.Result = new GrantValidationResult(xUser.Id, AuthenticationMethods.Password);
|
||||
return;
|
||||
}
|
||||
else if (result.IsLockedOut)
|
||||
{
|
||||
//
|
||||
logger.LogInformation("Authentication failed for username: {username}, reason: locked out", xUser.UserName);
|
||||
|
||||
//
|
||||
exception = XException.AccountLockedOut;
|
||||
await events
|
||||
.RaiseAsync(
|
||||
new UserLoginFailureEvent(
|
||||
xUser.UserName,
|
||||
exception.ToXError().Message,
|
||||
false,
|
||||
clientId
|
||||
));
|
||||
}
|
||||
else if (result.IsNotAllowed)
|
||||
{
|
||||
//
|
||||
logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", xUser.UserName);
|
||||
|
||||
//
|
||||
exception = XException.NotAllowed;
|
||||
await events
|
||||
.RaiseAsync(
|
||||
new UserLoginFailureEvent(
|
||||
xUser.UserName,
|
||||
exception.ToXError().Message,
|
||||
false,
|
||||
clientId
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", xUser.UserName);
|
||||
|
||||
//
|
||||
exception = XException.LoginFailed;
|
||||
await events
|
||||
.RaiseAsync(
|
||||
new UserLoginFailureEvent(
|
||||
xUser.UserName,
|
||||
exception.ToXError().Message,
|
||||
false,
|
||||
clientId
|
||||
));
|
||||
|
||||
//
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
logger.LogInformation("No user found matching username: {username}", xUser.UserName);
|
||||
|
||||
//
|
||||
exception = XException.InvalidUserName;
|
||||
await events
|
||||
.RaiseAsync(
|
||||
new UserLoginFailureEvent(
|
||||
xUser.UserName,
|
||||
exception.ToXError().Message,
|
||||
false,
|
||||
clientId
|
||||
));
|
||||
}
|
||||
|
||||
//
|
||||
Exception ecs = exception.ToException();
|
||||
if (exception == XException.AccountLockedOut && xUser.LockoutEnd.HasValue)
|
||||
{
|
||||
//
|
||||
var passedTime = xUser.LockoutEnd.Value.UtcDateTime;
|
||||
ecs = XException.AccountLockedOut
|
||||
.AddContentToException(passedTime.ToString());
|
||||
}
|
||||
|
||||
//
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, ecs.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user