Files
xSaherElmIds/Validators/XResourceOwnerPasswordValidator.cs
T
2026-03-22 14:08:25 +03:30

193 lines
6.7 KiB
C#

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);
}
}
}