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 logger; public XResourceOwnerPasswordValidator( IXIdentityManager identityProvider, IEventService events, ILogger logger ) { this.identityManager = identityProvider; this.events = events; this.logger = logger; } /// /// Validates the resource owner password credential /// by providing UserName/Email or PhoneNumber /// /// The context. /// 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(); } // 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() : 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); } } }