I think you are close. If we are trying to authenticate a uid and password, let's try something like this:
'We will intentionally let the Exception bubble
Public Function Authenticate(username as String, password as String) as Boolean
Dim adsPath As String = "LDAP://dbm.i2a2.purdue.edu/dc=purdue,dc=edu"
Dim userdn As String = String.Empty
Dim userPath As String = String.Empty
'Binds Anonymously
Dim root As DirectoryEntry = New DirectoryEntry( _
adsPath, _
Nothing, _
Nothing, _
AuthenticationTypes.None _
)
Try
Dim ds As DirectorySearcher = New DirectorySearcher( _
root, _
String.Format("(uid={0})", username), _
New String() {"distinguishedName", "dn"} _
)
'It's ok to use FindOne in v2.0 of Fx
Dim sr As SearchResult = ds.FindOne()
If sr Is Nothing Then Throw New ArgumentException("User not found, check username")
'We want the distinguishedName and a binding point for next time
userdn = sr.Properties("dn")(0).ToString()
userPath = sr.Path
'Or we parse the path for the DN if we can't get it directly
'userdn = sr.Path.Split(new char[]{'\\'})[3]
Finally
root.Dispose()
End Try
'Create our secure entry for passing credentials
Dim SSLEntry As DirectoryEntry = New DirectoryEntry( _
userPath, _
userdn, _
password, _
AuthenticationTypes.SecureSocketsLayer _
)
Try
'Forces a bind
Dim object o = SSLEntry.NativeObject
return True
Catch ex As COMException
'Re-throw if not a logon failure
If ex.ErrorCode <> -2147023570 Then Throw
return False
Finally
SSLEntry.Dispose()
End Try
End Function
You should just have to pass a username and password and it will return a boolean if they are authenticated or not. Now, you should wrap this entire method to catch errors since it is designed to let it bubble up. The part you should hook into and inspect
surrounds getting the user's DN. Notice I have commented out one way of doing it. It is best to just ask the directory for the DN directly, but sometimes I don't know which attribute it is held on and it turns out to be easier to just parse the .Path. Just
make sure it is in the 'UID=Foo,...DC=domain' format.
By default, SecureSocketsLayer is going to try and connect to 636, so we don't have to worry about it. Notice I did not bind directly to an object, but the root partition instead. This allows me to find anyone, not just one account.
If you still get the "server not operational error", try putting AuthenticationTypes.None instead of .SecureSocketsLayer to test if it is an issue there.
dunnry
Star
9098 Points
1806 Posts
Re: Unknown Error - talking to LDAP not AD
Oct 24, 2005 09:44 PM|LINK
'We will intentionally let the Exception bubble
Public Function Authenticate(username as String, password as String) as Boolean
Dim adsPath As String = "LDAP://dbm.i2a2.purdue.edu/dc=purdue,dc=edu"
Dim userdn As String = String.Empty
Dim userPath As String = String.Empty
'Binds Anonymously
Dim root As DirectoryEntry = New DirectoryEntry( _
adsPath, _
Nothing, _
Nothing, _
AuthenticationTypes.None _
)
Try
Dim ds As DirectorySearcher = New DirectorySearcher( _
root, _
String.Format("(uid={0})", username), _
New String() {"distinguishedName", "dn"} _
)
'It's ok to use FindOne in v2.0 of Fx
Dim sr As SearchResult = ds.FindOne()
If sr Is Nothing Then Throw New ArgumentException("User not found, check username")
'We want the distinguishedName and a binding point for next time
userdn = sr.Properties("dn")(0).ToString()
userPath = sr.Path
'Or we parse the path for the DN if we can't get it directly
'userdn = sr.Path.Split(new char[]{'\\'})[3]
Finally
root.Dispose()
End Try
'Create our secure entry for passing credentials
Dim SSLEntry As DirectoryEntry = New DirectoryEntry( _
userPath, _
userdn, _
password, _
AuthenticationTypes.SecureSocketsLayer _
)
Try
'Forces a bind
Dim object o = SSLEntry.NativeObject
return True
Catch ex As COMException
'Re-throw if not a logon failure
If ex.ErrorCode <> -2147023570 Then Throw
return False
Finally
SSLEntry.Dispose()
End Try
End Function
You should just have to pass a username and password and it will return a boolean if they are authenticated or not. Now, you should wrap this entire method to catch errors since it is designed to let it bubble up. The part you should hook into and inspect surrounds getting the user's DN. Notice I have commented out one way of doing it. It is best to just ask the directory for the DN directly, but sometimes I don't know which attribute it is held on and it turns out to be easier to just parse the .Path. Just make sure it is in the 'UID=Foo,...DC=domain' format.
By default, SecureSocketsLayer is going to try and connect to 636, so we don't have to worry about it. Notice I did not bind directly to an object, but the root partition instead. This allows me to find anyone, not just one account.
If you still get the "server not operational error", try putting AuthenticationTypes.None instead of .SecureSocketsLayer to test if it is an issue there.
Weblog
The Book
LDAP Programming Help