Blog

Authenticate Users with ActiveDirectory

06.02.2016
Aljoša Kocen

A recent project required some sort of authenticating software users. I could have used username/password combination, stored in an encrypted form inside some SQL database. The project however was to be used internally, inside Company's office or over VPN connection. So I went with Active directory Authentication.

When a user logs to PC, connected to Domain Environment, he/she passes his/her UserName and Password. These are compared against the entries written in Active Directory on Domain Controller server. If credentials provided are correct, the user logs on to the client PC. So one might think that if user was already authenticated through log-in process, no further means of security is to be provided. Users, connected to company network though VPN remained a challenge though. One can easily imagine a scenario, where a employee PC at home is left unattended... Besides that, even work PC's are sometimes left with their desktops sessions open.

Enter System.DirectoryServices.AcountManagement object

Search over the Internet quickly provided me with a solution.

    Public Shared Function ValidateActiveDirectoryLogin(ByVal Domain As String,
                                                        ByVal Username As String,
                                                        ByVal Password As String) As Boolean
        Dim Success As Boolean = False


        Dim Context As New PrincipalContext(ContextType.Domain, Domain)

        Try
            Success = Context.ValidateCredentials(Username, Password)
        Catch
            'Always implement some sort of Exception handling in production code
            Throw New NotImplementedException()
        End Try
        Return Success
    End Function

 Very simple and elegant solution. The function accepts Domain name, against whict to validate, Username and corresponding password. If username and password is accepted by AD, the function returns True, otherwise it will return false. There are some things to consider.

  1. If user account is locked on AD, or its password expired, method will always return False, which is correct. It doesn't tell you however WHY exactly the method returned false.
  2. If "Guest" account is enabled on domain, method will return true, if username passed to method is that of nonexisting user. But having GUest accounts enabled on the domain system is BIG NO NO anyway.

How to use the code

Username and password are typed in some sort of login window. Domain name is  somewhat different beast. In the calling routine, Domain name can easily be obtained by calling 

DomainName = Environment.UserDomainName

For the clients, connected through VPN Connection, this would result in their PC name, or their Domain name, if they are on a different domain. Domain name therefore must be explicitly typed in.

Solution I use is fairly straightforward:

    Private Sub Authenticate()

        Dim UserName As String = UserNameTextBox.Text
        Dim DomainName As String = ""
        Dim Password As String = PasswordTextBox.Password

        'Check if Username contains possible domain name
        If UserName.Contains("\") Then
            'UserName in the form "DomainName\UserName
            DomainName = UserName.Split("\")(0)
            UserName = UserName.Split("\")(1)
        Else
            'Get system Domain, if present
            DomainName = Environment.UserDomainName

        End If
        Dim res As Boolean = ValidateActiveDirectoryLogin(DomainName,
                                                                   UserName,
                                                                   Password)
        If res = True Then
            'Success
            'Load main window, or perform other action as required by your project
        Else
            'Failure, 
            NotificationTextBox.Content = "Wrong username and/or password"
        End If

        'Log Succesfull Login
    End Sub

Code is pretty well documented. UserName and password are obtained from UI input. The code then checks, if Domain name can be resolved from UserName in the form "DomainName\UserName", and parses out Domain name. If Domain name cannot be resolved it is assumed, that the Client PC is joined to the domain, and gets the domain name. All three values are passed to validation code. If validation fails, a message is to be displayed, notifying user of a failure.

Best regards and happy coding.