Larry
Larry

Reputation: 573

LDAP auth in ASP.NET MVC authentication error: "Default credentials are not supported when the connection protection is set to None"

I am trying to implement LDAP authentication on the ADAM LDAP server of my company with ASP.NET MVC.

I already tested coordinates and credentials with other LDAP clients and they work fine. The server is not SSL secured and it works on standard 389 port, so I set connectionProtection="None" in web.config membership provider.

When I try login with default login page, I get this error:

Default credentials are not supported when the connection protection is set to None.

Here are parts of web.config

<configuration>
  <connectionStrings>
    <add name="ADConnectionString"    connectionString="LDAP://mycompanyldapserver.com:389"/>
    
  ....

<membership defaultProvider="DefaultMembershipProvider">
  <providers>
    <add name="DefaultMembershipProvider"
         type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
         connectionStringName="ADConnectionString"
         connectionProtection="None"
         attributeMapUsername="sAMAccountName"
         enableSearchMethods="True"/>
  </providers>
</membership>

AccountController

    [AllowAnonymous]
    [HttpPost]
    public JsonResult JsonLogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            // >> Membership.ValidateUser THROWS EXCEPTION AFTER LOGIN TRY >>
            if (Membership.ValidateUser(model.UserName, model.Password)) 
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return Json(new { success = true, redirect = returnUrl });
            }

EDIT

I discovered that the exception "Default credentials are not supported when the connection protection is set to None" is not thrown when I add these parameters to DefaultMembershipProvider:

connectionUsername="username"
connectionPassword="userpwd"

The problem is that username and password must change runtime, based on login form...may you help me to set these parameters runtime, please? I tried to implement this solution, which I suppose could work...I suppose because now I get a "wrong username or password" error instead of above exception specified in the subject. I think I am a step away to solve this problem, anyway I need help from some expert. I do not konw if the following solution can work properly to validate user:

MODIFIED ACCOUNT CONTROLLER: I AM TRYING TO ADD MEMBERSHIP PROVIDER RUNTIME

    [AllowAnonymous]
    [HttpPost]
    public JsonResult JsonLogOn(LogOnModel model, string returnUrl)
    {

        // I'm trying to add membership provider runtime...

        System.Web.Security.ActiveDirectoryMembershipProvider mprov = new System.Web.Security.ActiveDirectoryMembershipProvider();

        NameValueCollection objConfig = new NameValueCollection();
        objConfig.Add("name", "DefaultMembershipProvider");
        objConfig.Add("type", "System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
        objConfig.Add("connectionStringName", "ADConnectionString");
        objConfig.Add("connectionProtection", "None");
        objConfig.Add("connectionUsername", model.UserName);
        objConfig.Add("connectionPassword", model.Password);
        objConfig.Add("attributeMapUsername", "sAMAccountName");
        objConfig.Add("enableSearchMethods", "True");

        try
        {
            // Here I get "wrong username or password error...wrong DN base? I do not know.....
                 mprov.Initialize(objConfig["name"], objConfig);
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return Json(new { success = true, redirect = returnUrl });
        }

        catch (System.Runtime.InteropServices.COMException ex)
        {
            // For now I am catching all COMExceptions...if it works I could change behavior...
            ModelState.AddModelError("", ex.Message);

        }

Upvotes: 1

Views: 3330

Answers (1)

Larry
Larry

Reputation: 573

The main problem was the following error: "Default credentials are not supported when the connection protection is set to None". When DefaultMembershipProvider has connectionProtection="None" it needs connectionUsername and connectionPassword to be set:

web.config

     <membership defaultProvider="DefaultMembershipProvider">
     <providers>
        <add name="DefaultMembershipProvider"
        type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        connectionStringName="ADConnectionString"
        connectionProtection="None"
        connectionUsername="username"
        connectionPassword="userpwd"
        attributeMapUsername="sAMAccountName"
        enableSearchMethods="True"/>
      </providers>
      </membership>

The second problem was that I use LDAP for authentication, so I did not want to use static connectionUsername and connectionPassword. So I decided to define whole MembershipProvider runtime, modifying my account controller JsonLogOn action (LogOn action should be modified in similar way):

ACCOUNT CONTROLLER / LOGON

    // POST: /Account/JsonLogOn

    [AllowAnonymous]
    [HttpPost]
    public JsonResult JsonLogOn(LogOnModel model, string returnUrl)
    {
        System.Web.Security.ActiveDirectoryMembershipProvider mprov = new System.Web.Security.ActiveDirectoryMembershipProvider();
        string baseDN = "OU=myou,OU=myou1,O=myO";
        NameValueCollection objConfig = new NameValueCollection();
        objConfig.Add("name", "DefaultMembershipProvider");
        objConfig.Add("type", "System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
        objConfig.Add("connectionStringName", "ADConnectionString");
        objConfig.Add("connectionProtection", "None");
        objConfig.Add("connectionUsername", "uid=" + model.UserName + "," + baseDN);
        objConfig.Add("connectionPassword", model.Password);
        objConfig.Add("attributeMapUsername", "sAMAccountName");
        objConfig.Add("enableSearchMethods", "True");

        try
        {
            mprov.Initialize(objConfig["name"], objConfig);
           
        }

        catch (System.Runtime.InteropServices.COMException ex)
        {
            switch (ex.ErrorCode)
            {
                // Server give back a value...
                case -2147016661:
                    {
                        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                        return Json(new { success = true, redirect = returnUrl });
                    }
            }
            ModelState.AddModelError("", ex.Message);
        }
        
        // If we got this far, something failed
        return Json(new { errors = GetErrorsFromModelState() });
    }

Upvotes: 2

Related Questions