Пример #1
0
        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
            }));
        }