C# / ASP.NET / AD - "The specified directory service attribute or value does not exist." [duplicate]

When submitting valid credentials to Active Directory via a ASP.NET web form, the following error message is returned: "The specified directory service attribute or value does not exist."

Code for LDAP Authentication:

using System;
using System.Text;
using System.Collections;
using System.DirectoryServices;
namespace FormsAuth
{ public class LdapAuthentication { private string _path; private string _filterAttribute; public LdapAuthentication(string path) { _path = path; } public bool IsAuthenticated(string domain, string username, string pwd) { string domainAndUsername = "CBHC" + @"\" + username; DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd); try { //Bind to the native AdsObject to force authentication. object obj = entry.NativeObject; DirectorySearcher search = new DirectorySearcher(entry); search.Filter = "(SAMAccountName=" + username + ")"; search.PropertiesToLoad.Add("cn"); SearchResult result = search.FindOne(); if (null == result) { return false; } //Update the new path to the user in the directory. _path = result.Path; _filterAttribute = (string)result.Properties["cn"][0]; } catch (Exception ex) { throw new Exception("Error authenticating user. " + ex.Message); } return true; } public string GetGroups() { DirectorySearcher search = new DirectorySearcher(_path); search.Filter = "(cn=" + _filterAttribute + ")"; search.PropertiesToLoad.Add("memberOf"); StringBuilder groupNames = new StringBuilder(); try { SearchResult result = search.FindOne(); int propertyCount = result.Properties["memberOf"].Count; string dn; int equalsIndex, commaIndex; for (int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++) { dn = (string)result.Properties["memberOf"][propertyCounter]; equalsIndex = dn.IndexOf("=", 1); commaIndex = dn.IndexOf(",", 1); if (-1 == equalsIndex) { return null; } groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1)); groupNames.Append("|"); } } catch (Exception ex) { throw new Exception("Error obtaining group names. " + ex.Message); } return groupNames.ToString(); } }
}

Code on login page:

<script runat=server>
void Login_Click(object sender, EventArgs e)
{ string adPath = "LDAP://server/DC=domain,DC=loc"; //Path to your LDAP directory server LdapAuthentication adAuth = new LdapAuthentication(adPath); try { if(true == adAuth.IsAuthenticated("CBHC",txtUsername.Text, txtPassword.Text)) { string groups = adAuth.GetGroups(); //Create the ticket, and add the groups. bool isCookiePersistent = chkPersist.Checked; FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, txtUsername.Text,DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups); //Encrypt the ticket. string encryptedTicket = FormsAuthentication.Encrypt(authTicket); //Create a cookie, and then add the encrypted ticket to the cookie as data. HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); if(true == isCookiePersistent) authCookie.Expires = authTicket.Expiration; //Add the cookie to the outgoing cookies collection. Response.Cookies.Add(authCookie); //You can redirect now. Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, false)); } else { errorLabel.Text = "Authentication did not succeed. Check user name and password."; } } catch(Exception ex) { errorLabel.Text = "Error authenticating. " + ex.Message; }
}
</script>

Authentication settings on Web.config for form on IIS:

<authentication mode="Windows"> <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/" /> </authentication> <authorization> <deny users="?" /> <allow users="*" /> </authorization> <identity impersonate="true" />

Word of note: This does not occur when running the site in Debug; in that situation, it authenticates perfectly and moves on to the Default page. It only occurs when contacting the page live on the IIS server.

3

1 Answer

I've hit an issue like this once. It may be because you can't retrieve LDAP NativeObject property for authentication. If the exception is thrown right after the object obj = entry.NativeObject; call, check if user has permissions on the domain.

Either debug through your code to see if it is indeed the NativeObject binding that is failing. Or Put a try/catch block around the binding in your IsAuthenticated() function like below. You should see the custom error thrown if it's caused by the issue I'm describing.

try
{ //Bind to the native AdsObject to force authentication. Object obj = entry.NativeObject;
}
catch (System.Runtime.InteropServices.COMException e)
{ if (e.ErrorCode == -2147016694) // -2147016694 - The specified directory service attribute or value does not exist. { throw new Exception("Can't retrieve LDAP NativeObject property"); } throw;
}
6

You Might Also Like