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);
}
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() });
}