?
Solved

AD Connectivity (LDAP)

Posted on 2005-02-25
25
Medium Priority
?
2,860 Views
Last Modified: 2008-03-06
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.Add("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("cn")(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 !


0
Comment
Question by:allanau20
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 9
  • 5
25 Comments
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 13411338
Sorry this is C# code, but it works for show users in either a domain or on the local machine
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.MachineName+",computer";
      userprefix = Environment.MachineName +"\\";
}
try
{
      entry = new DirectoryEntry(type,
      userprefix+textBox1.Text, textBox2.Text);
            
      if( radioButton1.Checked )
      {
            type = "LDAP://"+entry.Properties["defaultNamingContext"][0].ToString();
            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+"\r\n";
}
finally
{
      entry.Close();
}

If you want I can convert it to VB and test it
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 13411549
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.DebuggerStepThrough()> 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 designerPlaceholderDeclaration 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("defaultNamingContext")(0).ToString()
                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.Message)
        Finally
            entry.Close()
        End Try

    End Sub
End Class
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13412928

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.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 9

Assisted Solution

by:Joeisanerd
Joeisanerd earned 100 total points
ID: 13413104
I small thing needs to be changed to the code I posted

change
        Dim type As String = "WinNT://" + Environment.MachineName + ",computer"

        ListBox1.Items.Clear()

to this
        Dim type As String

        If (CheckBox1.Checked) Then
            type = "LDAP://RootDSE"
        Else
            type = "WinNT://" + Environment.MachineName + ",computer"
        End If

        ListBox1.Items.Clear()

0
 
LVL 5

Author Comment

by:allanau20
ID: 13413421
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 !



0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 13415386
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
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13420750
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)
0
 
LVL 5

Author Comment

by:allanau20
ID: 13422724
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 !



0
 
LVL 5

Author Comment

by:allanau20
ID: 13423172
Thanks Joeisanerd, but I need one that works with AD :(
0
 
LVL 5

Author Comment

by:allanau20
ID: 13423248
Joeisanerd, I tried your code, and I get the same error. I think it has to do with the configuration .. not sure. Keep searching..
0
 
LVL 9

Expert Comment

by:Joeisanerd
ID: 13424615
If you are using Intergrated Authentication and Impersonation, then you can just use WindowsIdentity and WindowsPrincipal objects to deal with users.
0
 
LVL 5

Author Comment

by:allanau20
ID: 13424765
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?
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13427024
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.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13428237
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.
0
 
LVL 5

Author Comment

by:allanau20
ID: 13430817
Thanks ihenry. Sys ppl says that there's no SSL enabled. Just to be sure I'll try your suggestions. Will keep you posted !
0
 
LVL 5

Author Comment

by:allanau20
ID: 13435365
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.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13437269

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?
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13438475
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.Sealing
      '--

      de.RefreshCache()
Catch
      Throw
Finally
      de.Close()
      de.Dispose()
End Try
0
 
LVL 5

Author Comment

by:allanau20
ID: 13441840
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:

http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/ASP_DOT_NET/Q_21333064.html

Running the console gives me this error w/ or w/o the AuthenticationTypes line:

'System.Runtime.InteropServices.COMException' occurred in ConsoleApplication1.exe

Additional information: A referral was returned from the server

0
 
LVL 5

Author Comment

by:allanau20
ID: 13441846
Oh, Thanks ihenry for all your help so far.
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13446353
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?
0
 
LVL 20

Expert Comment

by:ihenry
ID: 13449591
And by the way, have you tried using ldp.exe utility?
0
 
LVL 20

Accepted Solution

by:
ihenry earned 1900 total points
ID: 13450572

Ok, some thoughts to the error. It usually due to failed resolving the ADsPath, try to ping to the domain name. Or perhaps you're binding with user name and password that lacks permission to access the domain/container (but I don't see any container is specified in your code).

You also can try to force bind to RootDSE using administrator account, and see if it returns the same DN as in your LDAP path. And another try is to explicitly specify a server name or FQDN in the ADsPath and include Authentication.ServerBind binding option in your code.
0
 
LVL 5

Author Comment

by:allanau20
ID: 13455933
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.DirectoryEntry.Bind(Boolean throwIfFail)
   System.DirectoryServices.DirectoryEntry.Bind()
   System.DirectoryServices.DirectoryEntry.get_NativeObject()
   ADSample.LdapAuthentication.IsAuthenticated(String domain, String username, String pwd) in c:\web\ADSample\LdapAuthentication.vb:21
   ADSample.grabusers.Login_Click(Object sender, EventArgs e) in c:\web\ADSample\grabusers.aspx.vb:50
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +108
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +57
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +18
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
   System.Web.UI.Page.ProcessRequestMain() +1277

Thanks for all your help -- really appreciate it !!!
 
0
 
LVL 5

Author Comment

by:allanau20
ID: 13456060
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:

http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/Q_21248005.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 !!!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article discusses the ASP.NET AJAX ModalPopupExtender control. In this article we will show how to use the ModalPopupExtender control, how to display/show/call the ASP.NET AJAX ModalPopupExtender control from javascript, how to show/display/cal…
I recently went through the process of creating a Calendar Control of events with the basis of using a database to keep track of the dates that are selectable, one requirement was to have the selected date pop-up in a simple lightbox.  At first this…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question