• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3032
  • Last Modified:

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.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
allanau20
Asked:
allanau20
  • 11
  • 9
  • 5
2 Solutions
 
JoeisanerdCommented:
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
 
JoeisanerdCommented:
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
 
ihenryCommented:

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
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
JoeisanerdCommented:
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
 
allanau20Author Commented:
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
 
JoeisanerdCommented:
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
 
ihenryCommented:
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
 
allanau20Author Commented:
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
 
allanau20Author Commented:
Thanks Joeisanerd, but I need one that works with AD :(
0
 
allanau20Author Commented:
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
 
JoeisanerdCommented:
If you are using Intergrated Authentication and Impersonation, then you can just use WindowsIdentity and WindowsPrincipal objects to deal with users.
0
 
allanau20Author Commented:
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
 
ihenryCommented:
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
 
ihenryCommented:
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
 
allanau20Author Commented:
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
 
allanau20Author Commented:
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
 
ihenryCommented:

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
 
ihenryCommented:
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
 
allanau20Author Commented:
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
 
allanau20Author Commented:
Oh, Thanks ihenry for all your help so far.
0
 
ihenryCommented:
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
 
ihenryCommented:
And by the way, have you tried using ldp.exe utility?
0
 
ihenryCommented:

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
 
allanau20Author Commented:
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
 
allanau20Author Commented:
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

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

  • 11
  • 9
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now