Authenticate against AD LDS - asp.net

I've just installed AD LDS on my developer PC and everything works find, I've even created the user "abc" via ADSI Edit.
My goal is to test my ASP.NET Mvc 3 web application with my test AD LDS instance.
How can I get the app to authenticate the user against the instance? Do I have to write a custom membership provider? (overriding some stuff in the default AD membership provider?)
Thank you for any help!

You don't have to do any authentication since it is handled by iis.
All you have to do is change authentication mode to windows.
<system.web>
<authentication mode="Windows" />
</system.web>
Remember to either install iis after you installed AD, or register it manually.

Because you are using AD LDS I don't think authentication mode "Windows" will be so helpful. I believe you need to create a Login View(here /Account/Logon) and use authentication mode "Forms".
Enter the followwing in web.config
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Account/Logon" timeout="30" slidingExpiration="false" protection="All"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
Authenticating the user can be accomplished by using System.DirectoryServices.AccountManagement. The controller code should look something like this:
public ActionResult Logon(LogonModel model)
{
if (model.Username != null && model.Password != null)
{
string container = "CN=...,DC=....,DC=...."; //Your container in LDS
string ldapserver = "server:port"; //LDS server
PrincipalContext context = new PrincipalContext(
ContextType.ApplicationDirectory,
ldapserver,
container,
ContextOptions.SimpleBind);
bool authenticate = context.ValidateCredentials(string.Format("CN={0},{1}", model.Username, container), model.Password, ContextOptions.SimpleBind);
if (authenticate)
{
FormsAuthentication.RedirectFromLoginPage(model.Username, false);
}
else
{
System.Threading.Thread.Sleep(5000);
this.ModelState.AddModelError("Password", "Wrong username or password");
}
}
return View("Logon", new LogonModel { Username = model.Username });
}
Note that this ONLY solves authentication and not authorization.
You can also use membership providers, but if you are looking for an easy solution I think this should do the trick.

Related

SSO FormsAuthentication - 2 Applications - 1 x WebForms and 1 x MVC

I have read many posts and while I have gleaned all the information I need I cannot get this to work. So I am hopeful someone can point me in the right direction. Or if you have a working dummy project(s) even better. All the examples I have see do not specifically deal with my requirement 2.
I have an existing WebForms (W1) application that uses FormsAuthentication. As part of migrating this to MVC we want to create an MVC (M1) application "alongside" it and implement new functionality there. (It is currently out of scope to port the entire W1 application to MVC.) Existing FormsAuthentication is to be maintained and used for both sites.
Both applications will run on the same IIS but under different subdomains as:
w1.mydomain.com
m1.mydomain.com
Expectations
Users will log in to W1 and once authenticated access M1 urls as well as W1 urls
M1 application needs to "know" which user is logged in
Logging out either via W1 or M1 will log the user out for the other application
Implemented Solution
Login:
Share the authentication cookie at domain level viz mydomain.com
On successful login in W1 redirect to M1 to set the user auth cookie
Redirect back from M1 to W1
Logout:
W1/M1 Call FormsAuthentication.SignOut(); and then redirect to the the other side to do the same
Configurations
W1
web.config
<machineKey decryption="AES" validation="HMACSHA256" decryptionKey="AutoGenerate" validationKey="AutoGenerate" />
<authentication mode="Forms">
<forms loginUrl="~/account/login" timeout="120" defaultUrl="~/" domain=".mydomain.com" />
</authentication>
<compilation targetFramework="4.6.1"></compilation>
<!-- requestValidationMode needs to remain -->
<httpRuntime targetFramework="4.6.1" requestValidationMode="2.0"
maxRequestLength="20480" executionTimeout="300" />
login control on /account/login
<asp:Login ID="idLogin" runat="server" ViewStateMode="Disabled" DestinationPageUrl="~/sso/BounceLogin.aspx" >
Code behind for BounceLogin.aspx:
public partial class BounceLogin : Page
{
protected void Page_Load(object aSender, EventArgs aArgs)
{
Response.Redirect("https://m1.mydomain.com/sso/login");
}
}
M1
web.config
<machineKey decryption="AES" validation="HMACSHA256" decryptionKey="AutoGenerate" validationKey="AutoGenerate" />
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
<authentication mode="Forms">
<forms loginUrl="https://w1.mydomain.com/account/login" timeout="120" domain=".mydomain.com" />
</authentication>
SSO Controller:
public class SsoController : Controller
{
[Authorize]
// GET: Secure
public ActionResult Index()
{
return View();
}
public ActionResult Status()
{
return View(new ViewModel
{
TheUser = User
});
}
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return Redirect("https://w1.mydomain.com/");
}
public ActionResult Login()
{
FormsAuthentication.SetAuthCookie("test#mydomain.com", false);
return Redirect("https://w1.mydomain.com/sso/BounceLoginReturn");
}
}
Interactions
So here is what happens when I log in with my test user: test#mydomain.com. (I have omitted the username passing to M1 to keep the code simpler).
A. w1.mydomain.com/account/login - Perform Successful Login and redirect to m1.mydomain.com/sso/login
B. m1.mydomain.com/sso/login - Sets cookie for user test#mydomain.com and redirects to w1.mydomain.com/BounceLoginReturn
Problem
When I return to w1.mydomain.com/BounceLoginReturn W1 still thinks I am not logged in and redirects me to w1.mydomain.com/account/login. (If I open M1 in another browser tab it tells me I am logged in as user#test.com)
I have checked and both w1.mydomain.com and m1.mydomain.com have the same cookie value set for the domain .mydomain.com.
So what am I doing wrong here to make W1 think I am not logged in bearing in mind I originally logged in via the asp:Login control it contains?
If anyone else has this issue it turns out the solution was simple. My code above was functionally correct. I did however need to use hard coded keys:
<machineKey decryption="AES" validation="HMACSHA256" decryptionKey="{Hard Coded Key Here}" validationKey="{Hard Coded Key Here}" />
There are heaps of sites out there to generate these, but the easiest way is using IIS itself:
and then use "Generate Keys" on the right hand side.

Current user with ASP.NET Forms authentication app

I am trying to retrieve the current user in my web application that uses ASP.NET Forms authentication.
However, System.Security.Principal.WindowsIdentity.GetCurrent().Name returns domain\windowsUser, NOT the username that was used in the FormsAuthentication.RedirectFromLoginPage method.
I am using Forms authentication in my config file:
<authentication mode="Forms">
<forms loginUrl="Views/Login.aspx" name=".ASPXFORMSAUTH" timeout="1" cookieless="UseUri">
</forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
I am also trying to follow Microsoft's walk through and retrieve the Authentication ticket using the following snippet:
if (Request.IsAuthenticated)
{
var ident = User.Identity as FormsIdentity;
if (ident != null)
{
FormsAuthenticationTicket ticket = ident.Ticket;
var name = ticket.Name;
}
}
However, ident is always null because it's WindowsIdentity not FormsIdentity. What's wrong here?
Thank you!
Use User.Identity.Name to get the user name.
Windows authentication does not use the FormsAuthenticationTicket.

Communication Active Directory users with asp.net

I installed VM player in my machine and installed windows 2008 standard core inside. Also via command prompt added users and groups for a particular user as below,
creating user
dsadd user "cn=username,cn=users,dc=myname,dc=ca" -pwd password -disabled no
creating group
dsadd group "cn=groupname,cn=users,dc=myname,dc=ca"
Also added user to the existing group as below,
dsmod group "cn=groupname,cn=users,dc=myname,dc=ca" -addmbr "cn=username,cn=users,dc=myname,dc=ca"
Now i connect this users via my asp.net application in my local machine as below,
Web.config settings
<authentication mode="Forms">
<forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/"/>
</authentication>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
script for authentication
void Login_Click(object sender, EventArgs e)
{
string adPath = "LDAP://domainaddress:389/DC=somename,DC=m"; //Path to your LDAP directory server
LdapAuthentication adAuth = new LdapAuthentication(adPath);
try
{
if(true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text))
{
FormsAuthentication.SetAuthCookie(txtUsername.Text.Trim(), false);
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);
---------
-------
}
where i am getting exception in string groups = adAuth.GetGroups(); as below
"Error authenticating. Error getting groups. The username is incorrect or bad password. "
Please let me know if i am doing some mistakes or please let me know how i find groups of assciated user.
Regards
Sangeetha

Informing ASP.NET website about the currently logged-in user

I'm new to ASP.NET and have been trying to solve this for awhile now.
I've came across this blog, and everything looks to be good, except one thing: the below code always evaluates to false in HttpContext.Current.User.Identity is FormsIdentity in this code snippit:
protected void Application_AuthenticateRequest(Object sender,
EventArgs e)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity is FormsIdentity)
{
FormsIdentity id =
(FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
// Get the stored user-data, in this case, our roles
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
}
When I used breakpoints, it turned that my PC name is the current user, which I think is not a FormsIdentity.
Web.config:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
</configuration>
What am I missing here? and how to tell HttpContext of the current user after a sucessful login?
If you want users to have a FormsIdentity, then you need to turn on FormsAuthentication in your web.config file. In your element, you need to populate the authentication and authorization nodes. (For example, see the section of the blog post you mentioned titled "Securing Directories with Role-based Forms Authentication") Right now these elements are not present in your web.config file, and so Forms Authentication is not happening. A configuration like this is typical:
<system.web>
<authentication mode="Forms">
<forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx" protection="All" path="/" timeout="30" />
</authentication>
<authorization>
<deny users ="?" />
<allow users = "*" />
</authorization>
</system.web>
The node instructs ASP.Net to use forms authentication, while the node denies access to the site for any user who is not authentication.
More information can be found here and here

When does ASP.NET authentication occur?

I have an application where I display every Active Directory group that the current user belongs to. When I have my config setup like this:
<authentication mode="Windows"/>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
It works fine. When it's like this:
<authentication mode="Windows"/>
<authorization>
<!--<deny users="?"/>-->
<allow users="*"/>
</authorization>
No groups are found. Why does this make a difference? Does asp.net only authenticate if we are specifically denying access to unauthenticated users?
If it helps this is how i'm getting the groups:
protected string GetUserGroups()
{
StringBuilder userGroups = new StringBuilder();
ArrayList groupMembers = new ArrayList();
DirectoryEntry root = new DirectoryEntry("LDAP://myldap/DC=nc,DC=local");
DirectorySearcher ds = new DirectorySearcher(root);
ds.Filter = String.Format("(&(samaccountname={0})(objectClass=person))", User.Identity.Name.Substring(User.Identity.Name.LastIndexOf(#"\") + 1));
ds.PropertiesToLoad.Add("memberof");
try
{
foreach (SearchResult sr in ds.FindAll())
{
foreach (string str in sr.Properties["memberof"])
{
string str2 = str.Substring(str.IndexOf("=") + 1, str.IndexOf(",") - str.IndexOf("=") - 1);
groupMembers.Add(str2);
}
}
}
catch
{
//ignore if any properties found in AD
}
return String.Join("|", (string[])groupMembers.ToArray(typeof(string)));
}
I may be wrong, but I believe this is how it works:
The first time a browser hits a site it does so as anonymous.
If the server says that anonymous isn't allowed, the browser then sends the users windows credentials.
If those credentials don't pass muster, then the browser pops up the login box or (depending on the application) sends them over to a login page.
So, because your site allows anonymous, all of the users are coming in that way.

Resources