Allan
asked on
AD Connectivity (LDAP)
Hi Experts !
I need help with AD connectivity. I followed the instruction from this link:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/active_directory_authentication_from_asp__net.asp
The only difference in my code is that I converted it to VB.NET and use code-behind when possible.
I'm able to compile and run the web app, but when I tried to 'login' (using correct credential) it returns with this error:
A referral was returned from the server
If I use the wrong credential it returns:
Logon failure: unknown user name or bad password
And it occurred on this line (when it tries to bind):
Dim obj As Object = entry.NativeObject
I have double and tripled checked with the link above in case I have missed something.
My guess is that I don’t have the proper LDAP syntax?
If my domain name is golucky, here’s what I have for LDAP:
Dim adPath As String = "LDAP://DC=golucky,DC=com"
Domain Controller is on a Win 2003, and web app is on a different dev workstation (XP Pro).
Public Function IsAuthenticated(domain As String, username As String, pwd As String) As Boolean
Dim domainAndUsername as String = domain + "\" + username
Dim entry As New DirectoryEntry(_path, domainAndUsername, pwd)
Try
'Bind to the native AdsObject to force authentication.
Dim obj As Object = entry.NativeObject '<-- Error Here
Dim search As New DirectorySearcher(entry)
search.Filter = "(SAMAccountName=" + username + ")"
search.PropertiesToLoad.Ad d("cn")
Dim result As SearchResult = search.FindOne()
If result Is Nothing Then
Return False
End If
'Update the new path to the user in the directory.
_path = result.Path
_filterAttribute = CType(result.Properties("c n")(0), String)
Catch ex As Exception
Throw New Exception("Error authenticating user. " + ex.Message)
End Try
Return True
End Function 'IsAuthenticated
Any help or guidance you can provide is really appreciated !
I need help with AD connectivity. I followed the instruction from this link:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/active_directory_authentication_from_asp__net.asp
The only difference in my code is that I converted it to VB.NET and use code-behind when possible.
I'm able to compile and run the web app, but when I tried to 'login' (using correct credential) it returns with this error:
A referral was returned from the server
If I use the wrong credential it returns:
Logon failure: unknown user name or bad password
And it occurred on this line (when it tries to bind):
Dim obj As Object = entry.NativeObject
I have double and tripled checked with the link above in case I have missed something.
My guess is that I don’t have the proper LDAP syntax?
If my domain name is golucky, here’s what I have for LDAP:
Dim adPath As String = "LDAP://DC=golucky,DC=com"
Domain Controller is on a Win 2003, and web app is on a different dev workstation (XP Pro).
Public Function IsAuthenticated(domain As String, username As String, pwd As String) As Boolean
Dim domainAndUsername as String = domain + "\" + username
Dim entry As New DirectoryEntry(_path, domainAndUsername, pwd)
Try
'Bind to the native AdsObject to force authentication.
Dim obj As Object = entry.NativeObject '<-- Error Here
Dim search As New DirectorySearcher(entry)
search.Filter = "(SAMAccountName=" + username + ")"
search.PropertiesToLoad.Ad
Dim result As SearchResult = search.FindOne()
If result Is Nothing Then
Return False
End If
'Update the new path to the user in the directory.
_path = result.Path
_filterAttribute = CType(result.Properties("c
Catch ex As Exception
Throw New Exception("Error authenticating user. " + ex.Message)
End Try
Return True
End Function 'IsAuthenticated
Any help or guidance you can provide is really appreciated !
Here is a Web Version, I haven't tested the AD part, but the local machine part works
Imports System.DirectoryServices
Public Class WebForm1
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.Debugg erStepThro ugh()> Private Sub InitializeComponent()
End Sub
Protected WithEvents Button2 As System.Web.UI.WebControls. Button
Protected WithEvents TextBox1 As System.Web.UI.WebControls. TextBox
Protected WithEvents TextBox2 As System.Web.UI.WebControls. TextBox
Protected WithEvents ListBox1 As System.Web.UI.WebControls. ListBox
Protected WithEvents CheckBox1 As System.Web.UI.WebControls. CheckBox
'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclara tion As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim entry As DirectoryEntry
Dim userprefix As String = ""
Dim type As String = "WinNT://" + Environment.MachineName + ",computer"
ListBox1.Items.Clear()
Try
entry = New DirectoryEntry(type, userprefix & TextBox1.Text, TextBox2.Text)
If CheckBox1.Checked Then
type = "LDAP://" & entry.Properties("defaultN amingConte xt")(0).To String()
entry = New DirectoryEntry(type, userprefix & TextBox1.Text, TextBox2.Text)
End If
For Each en As DirectoryEntry In entry.Children
ListBox1.Items.Add(en.Name .ToString( ))
Next en
Catch ex As Exception
ListBox1.Items.Add(ex.Mess age)
Finally
entry.Close()
End Try
End Sub
End Class
Imports System.DirectoryServices
Public Class WebForm1
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.Debugg
End Sub
Protected WithEvents Button2 As System.Web.UI.WebControls.
Protected WithEvents TextBox1 As System.Web.UI.WebControls.
Protected WithEvents TextBox2 As System.Web.UI.WebControls.
Protected WithEvents ListBox1 As System.Web.UI.WebControls.
Protected WithEvents CheckBox1 As System.Web.UI.WebControls.
'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclara
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim entry As DirectoryEntry
Dim userprefix As String = ""
Dim type As String = "WinNT://" + Environment.MachineName + ",computer"
ListBox1.Items.Clear()
Try
entry = New DirectoryEntry(type, userprefix & TextBox1.Text, TextBox2.Text)
If CheckBox1.Checked Then
type = "LDAP://" & entry.Properties("defaultN
entry = New DirectoryEntry(type, userprefix & TextBox1.Text, TextBox2.Text)
End If
For Each en As DirectoryEntry In entry.Children
ListBox1.Items.Add(en.Name
Next en
Catch ex As Exception
ListBox1.Items.Add(ex.Mess
Finally
entry.Close()
End Try
End Sub
End Class
Your code looks fine to me, did you follow exactly what the article said about the IIS settings required ? If "Integrated Windows Authentication" set to enabled it's very likely a double hop issue.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks joeisanerd, I'll try it when on Monday.
ihenry, I had a feeling you would reply since I think you're really good with AD. I read your 'double loop' before on exchange when you're were helping someone else. Too bad I didn't same the link, but I'll search for it.
Thanks for your replies, and I'll try it on Monday. Have a good weekend !
ihenry, I had a feeling you would reply since I think you're really good with AD. I read your 'double loop' before on exchange when you're were helping someone else. Too bad I didn't same the link, but I'll search for it.
Thanks for your replies, and I'll try it on Monday. Have a good weekend !
Just an FYI, the code I posted was converted from C# and I know it work for windows apps, but there may need to be something done for it work with Web Apps and since I am not at work I can't fully test it without being in a domain environment
After looked a little deeper to sample code provided in the link, I started thinking a couple things. First, your problem doesn't seem to be a double hop issue. Secondly, I don't really the code.
Authentication to AD tends to fail for a myriads of reasons, I can't be sure what's exactly the problem just from the error message. But the following checks might be able to help you.
1. Are you sure you are not passing a null password to the function? because when a null password is used, AD proceeds with current context credentials of running process which is anonymous user account.
2. Are you sure the user account which is being authenticated has no password problem. You'll get the same error message when the user account's password expired or "User must change password" is checked.
3. Since what the code does is just a simple binding which means the password is sent in a clear text, if your AD server has SSL enabled or uses Kerberos protocol enabled then code simply won't work. Try different combination of AuthenticationTypes.Secure , Sealing, Signing and Delegation might solve your problem.
Finally, as far as authentication process goes your code should do some checking before the actual authentication takes place. Such as password expiration, "user must change password" flag and some other factors and so that you can handle it correctly and display proper error message to your user.
PS: I'll explain why I don't like the sample code after you solve this problem :o)
Authentication to AD tends to fail for a myriads of reasons, I can't be sure what's exactly the problem just from the error message. But the following checks might be able to help you.
1. Are you sure you are not passing a null password to the function? because when a null password is used, AD proceeds with current context credentials of running process which is anonymous user account.
2. Are you sure the user account which is being authenticated has no password problem. You'll get the same error message when the user account's password expired or "User must change password" is checked.
3. Since what the code does is just a simple binding which means the password is sent in a clear text, if your AD server has SSL enabled or uses Kerberos protocol enabled then code simply won't work. Try different combination of AuthenticationTypes.Secure
Finally, as far as authentication process goes your code should do some checking before the actual authentication takes place. Such as password expiration, "user must change password" flag and some other factors and so that you can handle it correctly and display proper error message to your user.
PS: I'll explain why I don't like the sample code after you solve this problem :o)
ASKER
Hi ihenry,
Thank you for all your help so far.
On the IIS for the web app under 'Directory Security' -> 'Anonymous access and authentication control'
I have 'Anonymous access' checked with a domain account that's part of the 'domain admin' group.
'Allow IIS to control password' is not checked.
I also have 'Integrated Windows' checked. If it's not checked, then I can't view the page, and get this error:
You are not authorized to view this page
HTTP 401.1 - Unauthorized: Logon Failed
If it's a double hop - do you have any suggestions? In the meantime, I'll look into the article:
"Troubleshooting Authentication Problems on ASP Pages"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/active_directory_authentication_from_asp__net.asp
As for your pointers:
1. I've debug into the function and the password is not null.
2. There's no problem with the account being use for aunthentication. It's a normal account to logon into the
network.
3. I'm checking with the sys guys if SSL or anything else is enabled.
Basically, I just want to pull all users on the domain and store into them into a db table. From there, when someone
visits the site I can use Context.User.Identity.Name and then match up with what I have in db and go from there.
Again, thanks for all your help !
Thank you for all your help so far.
On the IIS for the web app under 'Directory Security' -> 'Anonymous access and authentication control'
I have 'Anonymous access' checked with a domain account that's part of the 'domain admin' group.
'Allow IIS to control password' is not checked.
I also have 'Integrated Windows' checked. If it's not checked, then I can't view the page, and get this error:
You are not authorized to view this page
HTTP 401.1 - Unauthorized: Logon Failed
If it's a double hop - do you have any suggestions? In the meantime, I'll look into the article:
"Troubleshooting Authentication Problems on ASP Pages"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/active_directory_authentication_from_asp__net.asp
As for your pointers:
1. I've debug into the function and the password is not null.
2. There's no problem with the account being use for aunthentication. It's a normal account to logon into the
network.
3. I'm checking with the sys guys if SSL or anything else is enabled.
Basically, I just want to pull all users on the domain and store into them into a db table. From there, when someone
visits the site I can use Context.User.Identity.Name
Again, thanks for all your help !
ASKER
Thanks Joeisanerd, but I need one that works with AD :(
ASKER
Joeisanerd, I tried your code, and I get the same error. I think it has to do with the configuration .. not sure. Keep searching..
If you are using Intergrated Authentication and Impersonation, then you can just use WindowsIdentity and WindowsPrincipal objects to deal with users.
ASKER
What I need is to grab all the users from our network. I checked MSDN. I don't think WindowsIdentity and WindowsPrincipal will do that right?
Hi allanau20
In the code you explicitly use a user account to bind to AD therefore double hop should be a problem. I'm still thinking that the problem isn't a double hop issue. That's pretty much described in the following KB.
http://support.microsoft.com/default.aspx?scid=kb;en-us;329986
I think the problem has got to do with delegation, SSL or Kerberos encryption so that binding with AuthenticationTypes Delegation, Sealing, Secure or SSL might be necessary.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdirectoryservicesauthenticationtypesclasstopic.asp
Or better yet, before you continue coding use ldp.exe utility, which comes with Windows support tools, to bind to your AD using the same user account and try different set combination set of AuthenticationTypes and also port number. For example, to test whether your AD has SSL enable, bind to your DC via port 636.
In the code you explicitly use a user account to bind to AD therefore double hop should be a problem. I'm still thinking that the problem isn't a double hop issue. That's pretty much described in the following KB.
http://support.microsoft.com/default.aspx?scid=kb;en-us;329986
I think the problem has got to do with delegation, SSL or Kerberos encryption so that binding with AuthenticationTypes Delegation, Sealing, Secure or SSL might be necessary.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdirectoryservicesauthenticationtypesclasstopic.asp
Or better yet, before you continue coding use ldp.exe utility, which comes with Windows support tools, to bind to your AD using the same user account and try different set combination set of AuthenticationTypes and also port number. For example, to test whether your AD has SSL enable, bind to your DC via port 636.
Haha..my previous comment sounds funny! sorry about that, I was rushing typing into the texbox. What I wanted to say was double hop issue shouldn't be a problem.
ASKER
Thanks ihenry. Sys ppl says that there's no SSL enabled. Just to be sure I'll try your suggestions. Will keep you posted !
ASKER
Hi ihenry,
I have tried all the different AuthenticationTypes and still not working. I'll look into the ldp.exe utility, but I have a question. Using LDAP, do I need to install 'it' on the domain controller or IIS to get LDAP working? Thanks again.
I have tried all the different AuthenticationTypes and still not working. I'll look into the ldp.exe utility, but I have a question. Using LDAP, do I need to install 'it' on the domain controller or IIS to get LDAP working? Thanks again.
I'm not very sure can understand your question. When you say "do you need to install 'it' on the domain controller or IIS to get LDAP working". do you mean ldp.exe utility?
Ok, a small testing to whether you can bind to your AD server in the first place. Create a simple console program and paste the following code into the main function and run it, what do you get?
Dim de As DirectoryEntry
Try
de = new DirectoryEntry()
de.Path = yourAdsPath
de.Username = theUserName
de.Password = thePassword
'--first run without this line then second run try with this
'de.AuthenticationType = AuthenticationTypes.Secure Or AuthenticationTypes.Sealin g
'--
de.RefreshCache()
Catch
Throw
Finally
de.Close()
de.Dispose()
End Try
Dim de As DirectoryEntry
Try
de = new DirectoryEntry()
de.Path = yourAdsPath
de.Username = theUserName
de.Password = thePassword
'--first run without this line then second run try with this
'de.AuthenticationType = AuthenticationTypes.Secure
'--
de.RefreshCache()
Catch
Throw
Finally
de.Close()
de.Dispose()
End Try
ASKER
Sorry about the confusion. What I meant was that the LDAP provider that DirectoryServices uses, do I need to install it somehow on the IIS or DC? I read here that you need to 'integrate LDAP' to AD. Just a thought:
https://www.experts-exchange.com/questions/21333064/Authenticating-WebApp-with-LDAP.html
Running the console gives me this error w/ or w/o the AuthenticationTypes line:
'System.Runtime.InteropSer vices.COME xception' occurred in ConsoleApplication1.exe
Additional information: A referral was returned from the server
https://www.experts-exchange.com/questions/21333064/Authenticating-WebApp-with-LDAP.html
Running the console gives me this error w/ or w/o the AuthenticationTypes line:
'System.Runtime.InteropSer
Additional information: A referral was returned from the server
ASKER
Oh, Thanks ihenry for all your help so far.
LDAP or WinNT provider is supported by AD on Win2K (or higher) and if your web server is also running on Win2K or higher, I don't think you need to install anything. As long you're able to login to your web server using your domain account, everything should be set correctly.
About the error, did you use the same ADsPath? after login with domain account run again the code without using user name and password.
And can you post the exception stack trace here?
About the error, did you use the same ADsPath? after login with domain account run again the code without using user name and password.
And can you post the exception stack trace here?
And by the way, have you tried using ldp.exe utility?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for your replies ihenry - you're right that I don't need to install anything else if I have Win2k or higher.
I'm still waiting from Sys admin for the ldp.exe -- arrrgghhh.
Yes, I did use the same ADsPath and I tried w/o the passwords.
I'll look into your suggestion of RootDSE and FQDN.
In the meantime, here's my stack trace:
[COMException (0x8007202b): A referral was returned from the server]
System.DirectoryServices.D irectoryEn try.Bind(B oolean throwIfFail)
System.DirectoryServices.D irectoryEn try.Bind()
System.DirectoryServices.D irectoryEn try.get_Na tiveObject ()
ADSample.LdapAuthenticatio n.IsAuthen ticated(St ring domain, String username, String pwd) in c:\web\ADSample\LdapAuthen tication.v b:21
ADSample.grabusers.Login_C lick(Objec t sender, EventArgs e) in c:\web\ADSample\grabusers. aspx.vb:50
System.Web.UI.WebControls. Button.OnC lick(Event Args e) +108
System.Web.UI.WebControls. Button.Sys tem.Web.UI .IPostBack EventHandl er.RaisePo stBackEven t(String eventArgument) +57
System.Web.UI.Page.RaisePo stBackEven t(IPostBac kEventHand ler sourceControl, String eventArgument) +18
System.Web.UI.Page.RaisePo stBackEven t(NameValu eCollectio n postData) +33
System.Web.UI.Page.Process RequestMai n() +1277
Thanks for all your help -- really appreciate it !!!
I'm still waiting from Sys admin for the ldp.exe -- arrrgghhh.
Yes, I did use the same ADsPath and I tried w/o the passwords.
I'll look into your suggestion of RootDSE and FQDN.
In the meantime, here's my stack trace:
[COMException (0x8007202b): A referral was returned from the server]
System.DirectoryServices.D
System.DirectoryServices.D
System.DirectoryServices.D
ADSample.LdapAuthenticatio
ADSample.grabusers.Login_C
System.Web.UI.WebControls.
System.Web.UI.WebControls.
System.Web.UI.Page.RaisePo
System.Web.UI.Page.RaisePo
System.Web.UI.Page.Process
Thanks for all your help -- really appreciate it !!!
ASKER
HA AH HA HA HA HA HA HAH HA !
I figured it out. You're right the problem was in the adPath. What I did was ping dc for an ip and used that instead:
"LDAP://xxx.x.x.10"
I got the idea by reading one of your post:
https://www.experts-exchange.com/questions/21248005/Active-Directory-Search-Filter-Issue.html
Now, I just got figure out how to pull all users from the domain.
I can stop pulling my hair, and all thanks to you !!!
I figured it out. You're right the problem was in the adPath. What I did was ping dc for an ip and used that instead:
"LDAP://xxx.x.x.10"
I got the idea by reading one of your post:
https://www.experts-exchange.com/questions/21248005/Active-Directory-Search-Filter-Issue.html
Now, I just got figure out how to pull all users from the domain.
I can stop pulling my hair, and all thanks to you !!!
textBox1 is the username and textBox2 is the password. The radioButton1.Checked indicates to connect to the domain that the computer is part of.
Happens in this code is that if the user name and password are correct for the domain or the local machine depending on which is chosen, then a listbox will be filled with all of the account names for the local machine or the domain. If authentication fails the error message will be displayed in the listBox indicate an error.
DirectoryEntry entry = null;
string type;
string userprefix = "";
if( radioButton1.Checked )
type = "LDAP://RootDSE";
else
{
type = "WinNT://"+Environment.Mac
userprefix = Environment.MachineName +"\\";
}
try
{
entry = new DirectoryEntry(type,
userprefix+textBox1.Text, textBox2.Text);
if( radioButton1.Checked )
{
type = "LDAP://"+entry.Properties
entry = new DirectoryEntry(type,
userprefix+textBox1.Text, textBox2.Text);
}
foreach( DirectoryEntry en in entry.Children)
{
textBox3.Text += en.Name.ToString()+"\r\n";
}
textBox3.Text += "Valid\r\n";
}
catch(Exception ex)
{
textBox3.Text+=ex.Message+
}
finally
{
entry.Close();
}
If you want I can convert it to VB and test it