1

Currently, I am validating the credentials of an Active Directory user with the help of this code:

            string _groups = "";
        bool _isAuthSuccess=true;
        List<string> user_groups = new List<string>();
        try
        {
           using (PrincipalContext _loginContext = new PrincipalContext(ContextType.Domain, "domainname"))
            {
                _message += "calling ValidateCredentials";
                _isAuthSuccess = _loginContext.ValidateCredentials(model.Email, model.Password);
                if(_isAuthSuccess)
                {
                    _message += "calling FindByIdentity";
                    var user = UserPrincipal.FindByIdentity(_loginContext, model.Email);
                    if (user != null)
                    {
                        // get the user's groups
                        _message += "calling GetAuthorizationGroups";
                        var groups = user.GetAuthorizationGroups();
                        foreach (GroupPrincipal group in groups)
                        {
                            // save those groups to session for further processing after login
                            if ((bool)group.IsSecurityGroup)
                            {
                                user_groups.Add(group.Name);
                            }
                        }
                    }
                    _groups = string.Join(",", user_groups);
                }
                else
                {
                    _message += "_isAuthSuccess is false";
                }

            }
        }
        catch (PrincipalServerDownException)
        {
            _message += "Error at logon validatyion as server is down ";
        }  
        catch(Exception ex)
        {
            _message += "Exception : "+ex.Message;
        }

The bool flag is returning the status the user credentials are valid or not. Now i wanted to fetch the list of Active Directory UserGroups the user is a member of. I found that the method GetAuthorizationGroups will return the list of user groups. But I am struggling to relate these 2 methods as there is no way to call _loginCOntext.GetAuthorizationGroups()

So how can efficiently handle these 2 cases together

  1. validate credentials and
  2. get the list of user groups together.
Sebastian
  • 4,625
  • 17
  • 76
  • 145

1 Answers1

2

The GetAuthorizationGroups() method can only be called on a UserPricipal, so you need to get one for the user. That's easy to do with the UserPrincipal.FindByIdentity method (while reusing the _loginContext object you already have):

var user = UserPrincipal.FindByIdentity(_loginContext, user_name);
var groups = user.GetAuthorizationGroups();

Update: To avoid the "Multiple connections" error, try using different instances of PrincipalContext for each operation. At the end of the using, it should disconnect the connection with the server and allow you to start a new one with different credentials without problem.

using (PrincipalContext _loginContext = new PrincipalContext(ContextType.Domain, "domainname"))
{
    _message += "calling ValidateCredentials";
    _isAuthSuccess = _loginContext.ValidateCredentials(model.Email, model.Password);
}

using (PrincipalContext _loginContext = new PrincipalContext(ContextType.Domain, "domainname", "username", "password"))
{
    if(_isAuthSuccess)
    {
        ...
    }
    else
    {
        _message += "_isAuthSuccess is false";
    }

}
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • As per suggestion, the changes are done on the function, But now after the line FindByIdentity(), the below Exception is occurring. The user name or password is incorrect. But validateCredentials call on a line above is working fine So it's not about username or password incorrect, but something different and not been able to figure out why? – Sebastian Aug 11 '19 at 04:55
  • `ValidateCredentials` uses the username and password you specify. But any other operation uses the username and password you pass to the `PrincipalContext` constructor, or whatever credentials the process is running under. Since you didn't specify credentials in the `PrincipalContext` constructor, then it means the credentials the process is running under is not trusted on your domain. So you either need to pass credentials to `PrincipalContext`, or change the credentials that the process is running with. – Gabriel Luci Aug 11 '19 at 13:08
  • Yes thats true, I added the credentials to the PrincipalContext constructor, but the code executes successfully only once. After trying to execute the code second time for a different user i am getting the exception at line GetAuthorizationGroupsException : Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again. – Sebastian Aug 12 '19 at 05:32
  • Can we use the same user credentials in the second PrincipalContext block while fetching the user groups? Since if i use same credentials still this will cause Disconnect all previous connections to the server or shared resource and try again at GetAuthorizationGroups call . But you are right if we use a different user account details everything will work fine. The plan is to use same credentials for validating user and GetAuthorizationGroups Since we are not allowed to save user credentials in database due to security constraints – Sebastian Aug 13 '19 at 06:21
  • Validating the credentials uses the user's credentials, since the only way to validate credentials is to attempt to login as the user. After that `using` block, the connection is closed, and you can reconnect with your app's credentials. – Gabriel Luci Aug 13 '19 at 12:08
  • Sorry the first part is clear , but what exactly meany by apps credentials? Its a web app hosted on IIS . So Apps credentials in this context means, The credentials of remote server ? Then PrincipalContext constructor ContextType is Domain /machine/ApplicationDirectory Or this is credentilas of something different – Sebastian Aug 14 '19 at 04:48
  • The app's credentials would be the credentials of the IIS app pool process, which will likely use the computer's credentials to authenticate with the domain (if the server is joined to the domain). It will be able to read everything on the domain, but probably not change anything. – Gabriel Luci Aug 14 '19 at 12:15