/// <summary>
        /// Verify User Name, Password, User Status and Policy against Active Directory
        /// </summary>
        public async Task <bool> VerifyCredential(string userName, string password, string ldapUri, PendingRequest request, ClientConfiguration clientConfig)
        {
            if (string.IsNullOrEmpty(userName))
            {
                throw new ArgumentNullException(nameof(userName));
            }
            if (string.IsNullOrEmpty(password))
            {
                _logger.Error("Empty password provided for user '{user:l}'", userName);
                return(false);
            }
            if (string.IsNullOrEmpty(ldapUri))
            {
                throw new ArgumentNullException(nameof(ldapUri));
            }

            var user   = LdapIdentity.ParseUser(userName);
            var bindDn = FormatBindDn(ldapUri, user, clientConfig);

            _logger.Debug($"Verifying user '{{user:l}}' credential and status at {ldapUri}", bindDn);

            try
            {
                using (var connection = new LdapConnection())
                {
                    //trust self-signed certificates on ldap server
                    connection.TrustAllCertificates();

                    if (Uri.IsWellFormedUriString(ldapUri, UriKind.Absolute))
                    {
                        var uri = new Uri(ldapUri);
                        connection.Connect(uri.GetLeftPart(UriPartial.Authority));
                    }
                    else
                    {
                        connection.Connect(ldapUri, 389);
                    }
                    //do not follow chase referrals
                    connection.SetOption(LdapOption.LDAP_OPT_REFERRALS, IntPtr.Zero);

                    await connection.BindAsync(LdapAuthType.Simple, new LdapCredential
                    {
                        UserName = bindDn,
                        Password = password
                    });

                    var domain = await WhereAmI(ldapUri, connection, clientConfig);

                    _logger.Information($"User '{{user:l}}' credential and status verified successfully in {domain.Name}", user.Name);

                    var profile = await LoadProfile(connection, domain, user, clientConfig);

                    if (profile == null)
                    {
                        return(false);
                    }

                    var checkGroupMembership = !string.IsNullOrEmpty(clientConfig.ActiveDirectoryGroup);
                    //user must be member of security group
                    if (checkGroupMembership)
                    {
                        var isMemberOf = await IsMemberOf(connection, domain, user, profile, clientConfig.ActiveDirectoryGroup);

                        if (!isMemberOf)
                        {
                            _logger.Warning($"User '{{user:l}}' is not member of '{clientConfig.ActiveDirectoryGroup}' group in {profile.BaseDn.Name}", user.Name);
                            return(false);
                        }

                        _logger.Debug($"User '{{user:l}}' is member of '{clientConfig.ActiveDirectoryGroup}' group in {profile.BaseDn.Name}", user.Name);
                    }

                    var onlyMembersOfGroupMustProcess2faAuthentication = !string.IsNullOrEmpty(clientConfig.ActiveDirectory2FaGroup);
                    //only users from group must process 2fa
                    if (onlyMembersOfGroupMustProcess2faAuthentication)
                    {
                        var isMemberOf = await IsMemberOf(connection, domain, user, profile, clientConfig.ActiveDirectory2FaGroup);

                        if (isMemberOf)
                        {
                            _logger.Debug($"User '{{user:l}}' is member of '{clientConfig.ActiveDirectory2FaGroup}' in {profile.BaseDn.Name}", user.Name);
                        }
                        else
                        {
                            _logger.Information($"User '{{user:l}}' is not member of '{clientConfig.ActiveDirectory2FaGroup}' in {profile.BaseDn.Name}", user.Name);
                            request.Bypass2Fa = true;
                        }
                    }

                    if (clientConfig.UseActiveDirectoryUserPhone)
                    {
                        request.UserPhone = profile.Phone;
                    }
                    if (clientConfig.UseActiveDirectoryMobileUserPhone)
                    {
                        request.UserPhone = profile.Mobile;
                    }
                    request.DisplayName  = profile.DisplayName;
                    request.EmailAddress = profile.Email;
                    request.LdapAttrs    = profile.LdapAttrs;

                    if (profile.MemberOf != null)
                    {
                        request.UserGroups = profile.MemberOf.Select(dn => LdapIdentity.DnToCn(dn)).ToList();
                    }
                }

                return(true); //OK
            }
            catch (LdapException lex)
            {
                if (lex.Message != null)
                {
                    var dataReason = ExtractErrorReason(lex.Message);
                    if (dataReason != null)
                    {
                        _logger.Warning($"Verification user '{{user:l}}' at {ldapUri} failed: {dataReason}", user.Name);
                        return(false);
                    }
                }

                _logger.Error(lex, $"Verification user '{{user:l}}' at {ldapUri} failed", user.Name);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"Verification user '{{user:l}}' at {ldapUri} failed", user.Name);
            }

            return(false);
        }
Exemple #2
0
        /// <summary>
        /// Verify User Name, Password, User Status and Policy against Active Directory
        /// </summary>
        public bool VerifyCredential(string userName, string password, PendingRequest request)
        {
            if (string.IsNullOrEmpty(userName))
            {
                throw new ArgumentNullException(nameof(userName));
            }
            if (string.IsNullOrEmpty(password))
            {
                _logger.Error($"Empty password provided for user '{userName}'");
                return(false);
            }

            var user   = LdapIdentity.ParseUser(userName);
            var bindDn = FormatBindDn(user);

            _logger.Debug($"Verifying user '{bindDn}' credential and status at {_configuration.ActiveDirectoryDomain}");

            try
            {
                using (var connection = new LdapConnection())
                {
                    //trust self-signed certificates on ldap server
                    connection.TrustAllCertificates();

                    if (Uri.IsWellFormedUriString(_configuration.ActiveDirectoryDomain, UriKind.Absolute))
                    {
                        var uri = new Uri(_configuration.ActiveDirectoryDomain);
                        connection.Connect(uri.GetLeftPart(UriPartial.Authority));
                    }
                    else
                    {
                        connection.Connect(_configuration.ActiveDirectoryDomain, 389);
                    }
                    //do not follow chase referrals
                    connection.SetOption(LdapOption.LDAP_OPT_REFERRALS, IntPtr.Zero);

                    connection.Bind(LdapAuthType.Simple, new LdapCredential
                    {
                        UserName = bindDn,
                        Password = password
                    });

                    var domain = WhereAmI(connection);

                    _logger.Information($"User '{user.Name}' credential and status verified successfully in {domain.Name}");

                    var isProfileLoaded = LoadProfile(connection, domain, user, out var profile);
                    if (!isProfileLoaded)
                    {
                        return(false);
                    }

                    var checkGroupMembership = !string.IsNullOrEmpty(_configuration.ActiveDirectoryGroup);
                    //user must be member of security group
                    if (checkGroupMembership)
                    {
                        var isMemberOf = IsMemberOf(connection, domain, user, profile, _configuration.ActiveDirectoryGroup);

                        if (!isMemberOf)
                        {
                            _logger.Warning($"User '{user.Name}' is not member of '{_configuration.ActiveDirectoryGroup}' group in {profile.BaseDn.Name}");
                            return(false);
                        }

                        _logger.Debug($"User '{user.Name}' is member of '{_configuration.ActiveDirectoryGroup}' group in {profile.BaseDn.Name}");
                    }

                    var onlyMembersOfGroupMustProcess2faAuthentication = !string.IsNullOrEmpty(_configuration.ActiveDirectory2FaGroup);
                    //only users from group must process 2fa
                    if (onlyMembersOfGroupMustProcess2faAuthentication)
                    {
                        var isMemberOf = IsMemberOf(connection, domain, user, profile, _configuration.ActiveDirectory2FaGroup);

                        if (isMemberOf)
                        {
                            _logger.Debug($"User '{user.Name}' is member of '{_configuration.ActiveDirectory2FaGroup}' in {profile.BaseDn.Name}");
                        }
                        else
                        {
                            _logger.Information($"User '{user.Name}' is not member of '{_configuration.ActiveDirectory2FaGroup}' in {profile.BaseDn.Name}");
                            request.Bypass2Fa = true;
                        }
                    }

                    //check groups membership for radius reply conditional attributes
                    foreach (var attribute in _configuration.RadiusReplyAttributes)
                    {
                        foreach (var value in attribute.Value.Where(val => val.UserGroupCondition != null))
                        {
                            if (IsMemberOf(connection, domain, user, profile, value.UserGroupCondition))
                            {
                                _logger.Information($"User '{user.Name}' is member of '{value.UserGroupCondition}' in {profile.BaseDn.Name}. Adding attribute '{attribute.Key}:{value.Value}' to reply");
                                request.UserGroups.Add(value.UserGroupCondition);
                            }
                            else
                            {
                                _logger.Debug($"User '{user.Name}' is not member of '{value.UserGroupCondition}' in {profile.BaseDn.Name}");
                            }
                        }
                    }

                    if (_configuration.UseActiveDirectoryUserPhone)
                    {
                        request.UserPhone = profile.Phone;
                    }
                    if (_configuration.UseActiveDirectoryMobileUserPhone)
                    {
                        request.UserPhone = profile.Mobile;
                    }
                    request.DisplayName  = profile.DisplayName;
                    request.EmailAddress = profile.Email;
                }

                return(true); //OK
            }
            catch (LdapException lex)
            {
                if (lex.Message != null)
                {
                    var dataReason = ExtractErrorReason(lex.Message);
                    if (dataReason != null)
                    {
                        _logger.Warning($"Verification user '{user.Name}' at {_configuration.ActiveDirectoryDomain} failed: {dataReason}");
                        return(false);
                    }
                }

                _logger.Error(lex, $"Verification user '{user.Name}' at {_configuration.ActiveDirectoryDomain} failed");
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"Verification user '{user.Name}' at {_configuration.ActiveDirectoryDomain} failed");
            }

            return(false);
        }