Home
Manage Your Code
Snippet: Validate a User's Active Directory Credentials (Windows XP or greater) (C#)
Title: Validate a User's Active Directory Credentials (Windows XP or greater) Language: C#
Description: Validate a user name and password combination against Active Directory or older Windows domain types. Returns a 3-level return code of SUCCESS, or ERROR_BAD_USERNAME_OR_PASSWORD, or UNKNOWN_ERROR. Views: 307
Author: Kevin Shuma Date Added: 11/27/2007
Copy Code  
1                /// <summary>

2		/// Return codes for the validate user credentials function

3		/// </summary>

4		public enum ValidateUserCredentialsReturnCodes
5		{
6			/// <summary>

7			/// user name and password provided were authenticated successfully

8			/// </summary>

9			SUCCESS = 0,
10			/// <summary>

11			/// Bad user name or password was provided

12			/// </summary>

13			ERROR_BAD_USERNAME_OR_PASSWORD = 1,
14			/// <summary>

15			/// An unknown error occurred

16			/// </summary>

17			UNKNOWN_ERROR = 99
18		}
19
20                /// <summary>

21		/// Validate a user's credentials against active directory.

22		/// </summary>

23		/// <param name="DomainName">string.  The user's domain name.  Example "AMERICAS"</param>

24		/// <param name="UserName">string.  User name. Example "kevin_shuma"</param>

25		/// <param name="Password">string.  The user's password.</param>

26		/// <returns>bool.  True = authentication success, False = authentication failure.</returns>

27		public static ValidateUserCredentialsReturnCodes
28			ValidateUserCredentials(string DomainName, string UserName, string Password)
29		{
30			try
31			{
32                // create a server-side stream that can be authenticated against

33                // create a full duplex stream using the loopback adapter

34                TcpListener TcpListener = new TcpListener(IPAddress.Loopback, 0);
35                TcpListener.Start();
36                WindowsIdentity Id = null;
37                bool AnswerReceived = false;
38                TcpListener.BeginAcceptTcpClient(delegate(IAsyncResult AsyncResult)
39                {
40                    using (NegotiateStream ServerSide = new NegotiateStream(
41                        TcpListener.EndAcceptTcpClient(AsyncResult).GetStream()))
42                    {
43                        try
44                        {
45                            ServerSide.AuthenticateAsServer(
46                                CredentialCache.DefaultNetworkCredentials,
47                                ProtectionLevel.None,
48                                TokenImpersonationLevel.Impersonation);
49                            Id = (WindowsIdentity)ServerSide.RemoteIdentity;
50                        }
51                        catch
52                        {
53                            Id = null;
54                        }
55                        AnswerReceived = true;
56                    }
57                }, null);
58
59                // try to create a connection to the server-side stream

60                //  and use the supplied credentials for authentication

61                using (NegotiateStream ClientSide =
62                    new NegotiateStream(new TcpClient(IPAddress.Loopback.ToString(),
63                    ((IPEndPoint)TcpListener.LocalEndpoint).Port).GetStream()))
64                {
65                    ClientSide.AuthenticateAsClient(
66                        new NetworkCredential(UserName, Password, DomainName),
67                        string.Empty,
68                        ProtectionLevel.None,
69                        TokenImpersonationLevel.Impersonation);
70                }
71
72                // if the code executes before the connection on the server-side 

73                //  replies, a false NULL is returned.  wait until an answer

74                //  is received (up to the timeout value) before continuing

75                const int WAIT_INTERVAL = 50;   // MS to wait between polling

76                const int MAX_WAIT_TIME = 2000; // max MS to wait

77                for (int i = 0; i < MAX_WAIT_TIME / WAIT_INTERVAL; i++)
78                {
79                    if (AnswerReceived)
80                        break;
81                    Thread.Sleep(WAIT_INTERVAL);
82                }
83
84                if (Id != null) // not null = logon okay

85                    return ValidateUserCredentialsReturnCodes.SUCCESS;
86                else // null = logon failed

87                    return ValidateUserCredentialsReturnCodes.ERROR_BAD_USERNAME_OR_PASSWORD;
88			}
89			catch (Exception ex)
90			{
91				Logging.LogException(MethodBase.GetCurrentMethod(), ref ex);
92				return ValidateUserCredentialsReturnCodes.UNKNOWN_ERROR;
93			}
94		}
Notes
Uses SSPI available in V2 of the .NET Framework. This is preferred to AD binding methods since AD is not a true authentication service.