private async Task <(IAuthenticationProvider?authenticationProvider, string username, bool success)> AuthenticateLocalUser( string username, string password, User?user, string remoteEndPoint) { bool success = false; IAuthenticationProvider?authenticationProvider = null; foreach (var provider in GetAuthenticationProviders(user)) { var providerAuthResult = await AuthenticateWithProvider(provider, username, password, user).ConfigureAwait(false); var updatedUsername = providerAuthResult.username; success = providerAuthResult.success; if (success) { authenticationProvider = provider; username = updatedUsername; break; } } if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user?.EnableLocalPassword == true && !string.IsNullOrEmpty(user.EasyPassword)) { // Check easy password var passwordHash = PasswordHash.Parse(user.EasyPassword); var hash = _cryptoProvider.ComputeHash( passwordHash.Id, Encoding.UTF8.GetBytes(password), passwordHash.Salt.ToArray()); success = passwordHash.Hash.SequenceEqual(hash); } return(authenticationProvider, username, success); }
// This is the version that we need to use for local users. Because reasons. public Task <ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser) { bool success = false; if (resolvedUser == null) { throw new ArgumentNullException(nameof(resolvedUser)); } // As long as jellyfin supports passwordless users, we need this little block here to accommodate if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password)) { return(Task.FromResult(new ProviderAuthenticationResult { Username = username })); } ConvertPasswordFormat(resolvedUser); byte[] passwordbytes = Encoding.UTF8.GetBytes(password); PasswordHash readyHash = new PasswordHash(resolvedUser.Password); if (_cryptographyProvider.GetSupportedHashMethods().Contains(readyHash.Id) || _cryptographyProvider.DefaultHashMethod == readyHash.Id) { byte[] calculatedHash = _cryptographyProvider.ComputeHash(readyHash.Id, passwordbytes, readyHash.Salt); if (calculatedHash.SequenceEqual(readyHash.Hash)) { success = true; } } else { throw new AuthenticationException($"Requested crypto method not available in provider: {readyHash.Id}"); } if (!success) { throw new AuthenticationException("Invalid username or password"); } return(Task.FromResult(new ProviderAuthenticationResult { Username = username })); }
// This is the verson that we need to use for local users. Because reasons. public Task <ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser) { bool success = false; if (resolvedUser == null) { throw new Exception("Invalid username or password"); } // As long as jellyfin supports passwordless users, we need this little block here to accomodate if (IsPasswordEmpty(resolvedUser, password)) { return(Task.FromResult(new ProviderAuthenticationResult { Username = username })); } ConvertPasswordFormat(resolvedUser); byte[] passwordbytes = Encoding.UTF8.GetBytes(password); PasswordHash readyHash = new PasswordHash(resolvedUser.Password); byte[] calculatedHash; string calculatedHashString; if (_cryptographyProvider.GetSupportedHashMethods().Contains(readyHash.Id)) { if (string.IsNullOrEmpty(readyHash.Salt)) { calculatedHash = _cryptographyProvider.ComputeHash(readyHash.Id, passwordbytes); calculatedHashString = BitConverter.ToString(calculatedHash).Replace("-", string.Empty); } else { calculatedHash = _cryptographyProvider.ComputeHash(readyHash.Id, passwordbytes, readyHash.SaltBytes); calculatedHashString = BitConverter.ToString(calculatedHash).Replace("-", string.Empty); } if (calculatedHashString == readyHash.Hash) { success = true; // throw new Exception("Invalid username or password"); } } else { throw new Exception(string.Format($"Requested crypto method not available in provider: {readyHash.Id}")); } // var success = string.Equals(GetPasswordHash(resolvedUser), GetHashedString(resolvedUser, password), StringComparison.OrdinalIgnoreCase); if (!success) { throw new Exception("Invalid username or password"); } return(Task.FromResult(new ProviderAuthenticationResult { Username = username })); }