using Bit.Core.Models.Table; using Bit.Core.Repositories; using IdentityServer4.Models; using IdentityServer4.Validation; using Microsoft.AspNetCore.Identity; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; using Bit.Core.Services; using Bit.Core.Identity; using Microsoft.Extensions.Logging; namespace Bit.Core.IdentityServer { public class ResourceOwnerPasswordValidator : BaseRequestValidator, IResourceOwnerPasswordValidator { private UserManager _userManager; private readonly IUserService _userService; public ResourceOwnerPasswordValidator( UserManager userManager, IDeviceRepository deviceRepository, IDeviceService deviceService, IUserService userService, IEventService eventService, IOrganizationDuoWebTokenProvider organizationDuoWebTokenProvider, IOrganizationRepository organizationRepository, IOrganizationUserRepository organizationUserRepository, IApplicationCacheService applicationCacheService, IMailService mailService, ILogger logger, CurrentContext currentContext, GlobalSettings globalSettings) : base(userManager, deviceRepository, deviceService, userService, eventService, organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository, applicationCacheService, mailService, logger, currentContext, globalSettings) { _userManager = userManager; _userService = userService; } public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { await ValidateAsync(context, context.Request); } protected async override Task<(User, bool)> ValidateContextAsync(ResourceOwnerPasswordValidationContext context) { if (string.IsNullOrWhiteSpace(context.UserName)) { return (null, false); } var user = await _userManager.FindByEmailAsync(context.UserName.ToLowerInvariant()); if (user == null || !await _userService.CheckPasswordAsync(user, context.Password)) { return (user, false); } return (user, true); } protected override void SetSuccessResult(ResourceOwnerPasswordValidationContext context, User user, List claims, Dictionary customResponse) { context.Result = new GrantValidationResult(user.Id.ToString(), "Application", identityProvider: "bitwarden", claims: claims.Count > 0 ? claims : null, customResponse: customResponse); } protected override void SetTwoFactorResult(ResourceOwnerPasswordValidationContext context, Dictionary customResponse) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Two factor required.", customResponse); } protected override void SetErrorResult(ResourceOwnerPasswordValidationContext context, Dictionary customResponse) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, customResponse: customResponse); } } }