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

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

Related

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.

Authenticate against AD LDS

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.

Authorization denied message with FormsAuthentication

So, I've implemented my IPrincipal.IsInRole(...) and I'm using FormsAuthentication like so:
<authentication mode="Forms">
<forms loginUrl="Login.aspx" name="someName" timeout="600"/>
</authentication>
Then I have a page that requires you to be authenticated and that you have "roleA". This is configured like so:
<location path="SomePage.aspx">
<system.web>
<authorization>
<allow roles="roleA" />
<deny users="*"/>
</authorization>
</system.web>
</location>
Now, I login to my web application, but with a user that does NOT have roleA. When I visit SomePage.aspx I get redirected to Login.aspx, the url specified in loginUrl of the forms element. So, my question is shouldn't I be able be specify an authorization denied message or url? If the user is authenticated, but not authorized why would I want to redirect to the login page. It's confusing as hell to the user. Please tell me I am missing something simple.
Thanks for reading!
Yeah, this is a little annoying. Maybe someone has a simpler idea, but the solution (hack?) that we came up with was to look for the originally-requested URL that ASP.NET appends to the query string when the user is redirected to the login page.
We created a new web.config section that stores a set of keys/values that match a fragment of the redirect URL to an authorization message:
<configSections>
<section name="authorizationFailureMessages" type="System.Configuration.NameValueSectionHandler, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
...etc...
</configSections>
<authorizationFailureMessages>
<add key="MemberResources" value="MembershipRequired" />
<add key="Staff" value="StaffOnly" />
<add key="Departments/Administration/BoardOfDirectors" value="BoardOfDirectorsOnly" />
...etc...
</authorizationFailureMessages>
In the Page_Load() event of the Login.aspx page, we call a method that uses this URL to determine which (un)authorization event occurred then redirect them to a message page that displays the appropriate text:
private void DisplayAppropriateAuthorizationMessage ()
{
if ( !Page.User.Identity.IsAuthenticated )
return;
string redirectUrl = FormsAuthentication.GetRedirectUrl( Page.User.Identity.Name, false );
if ( string.IsNullOrEmpty( redirectUrl ) )
return;
NameValueCollection authorizationFailureMessages = ConfigurationManager.GetSection( "authorizationFailureMessages" ) as NameValueCollection;
if ( authorizationFailureMessages == null )
return;
foreach ( string key in authorizationFailureMessages.AllKeys )
{
if ( redirectUrl.Contains( key ) )
{
Response.Redirect( String.Format( "Message.aspx?{0}={1}", Constants.QueryStringKeys.ERRORMESSAGENAME, authorizationFailureMessages[ key ] ), true );
}
}
}
Roles.IsUserInRole - If you're just using it for this page, throw this in the code behind. If you have a lot of pages, you could consider putting this in a base class and reading either from the web.config or the database per page. I believe this will give you the most control.
I basically agree to #MattPeterson 's solution. But I suggest two improvements.
In my view, you just tell that "according to the roles that you are, you are not allowed to visit that page", that is enough. You do not need to tell which extra roles are needed, which will expose the details of authorization management of your website.
You can get access control list from web.config (in each folder), and no need to write <add key="MemberResources" value="MembershipRequired" /> again.
I believe you should have something similar to
<authorization>
<deny users="?" />
</authorization
in your web.config.

Single Sign On & Sign Out Problem in ASP.NET

Site Details which uses the single sign on,
1. http:\\webgate.abcltd.com
2. http:\\sales.abcltd.com
3. http:\\emp.abcltd.com
webgate application does the authentication and authorization. others(sales,emp) uses the webgate application. when any one access the any page from sales/emp site, they will be redirected to webgate's login page(here i have used form authentication. the configurations are below)
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
protection="All"
name="WebGateSecurity"
path="/"
domain="abcltd.com"
defaultUrl="ApplicationList.aspx"
enableCrossAppRedirects="true"/>
</authentication>
<authorization>
<deny users="?" />
</authorization>
<machineKey validationKey="2C0904BC344116CC6FFD3DD7087C942878C41B7F861555651E69C7B72F9A7DF6BC3B63BFF0F1438DFB863EE3EAC62CBFFECA7482D3758888E7CDACDBBAE136D5" decryptionKey="A60EC9E480CB3BBC48D1D2B7FFF9E945FBA46196AD3029187022ADE8F7B99B25" validation="SHA1" decryption="AES" />
User credentials is validated against the data store and the authentication ticket/cookies are being created as below
var authTicket=FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(30), false, userActions, FormsAuthentication.FormsCookiePath);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
If the given credentials are correct, i am tring to redirect to requested url as below
if (Request.Params["ReturnURL"] == null || Request.Params["ReturnURL"].EndsWith("/Logout.aspx") || Request.Params["ReturnURL"].EndsWith("/Error.aspx"))
Response.Redirect(FormsAuthentication.DefaultUrl);
else
{
//Response.Redirect(FormsAuthentication.GetRedirectUrl(username, false));
FormsAuthentication.RedirectFromLoginPage(username, false);
}
I have used the LoginStatus Control(placed in master page) which is let the user to perform the sign in/sign out from webgate app. When user sign out, the following code will be executed in order to remove the cookie.
protected void LoginStatus1_LoggingOut(object sender, LoginCancelEventArgs e)
{
FormsAuthentication.SignOut();
HttpCookie httpCookie = Request.Cookies[System.Web.Security.FormsAuthentication.FormsCookieName];
if (httpCookie != null)
{
httpCookie.Domain = "abcltd.com";
httpCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(httpCookie);
}
}
Configuration in other applications(sales and emp) are follows
<authentication mode="Forms">
<forms loginUrl="http://webgate.abcltd.com/Login.aspx" name="WebGateSecurity" protection="All" path="/" domain="abcltd.com" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<machineKey validationKey="2C0904BC344116CC6FFD3DD7087C942878C41B7F861555651E69C7B72F9A7DF6BC3B63BFF0F1438DFB863EE3EAC62CBFFECA7482D3758888E7CDACDBBAE136D5" decryptionKey="A60EC9E480CB3BBC48D1D2B7FFF9E945FBA46196AD3029187022ADE8F7B99B25" validation="SHA1" decryption="AES" />
My problem is: sign out is not working. In details if i say: after sign out, i able to access the any pages from webgate,sales and emp application.
Please help me.
That's because you are using a different domain name in web.config:
domain="vrxstudios.com"
and
domain="abcltd.com"
so no single sign on possible. In your sign out method you cannot remove a cookie that belongs on abcltd.com from vrxstudios.com:
if (httpCookie != null)
{
httpCookie.Domain = "abcltd.com"; // this is not possible from vrxstudios.com
httpCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(httpCookie);
}
What you could do is redirect to a sign out page on abcltd.com which will do the job.

Using forms authentication class for authentication

I am developing an user authentication site.
I have a login page, "Login.aspx" in which i have provided a login control.
In the web.config,
<authentication mode="Forms">
<forms name=".AuthenticationCookie" loginUrl="Login.aspx" protection="All" timeout="60" path="/">
<credentials passwordFormat="Clear">
<user name="Jack" password="Jerry"/>
</credentials>
</forms>
</authentication>
<authorization>
<deny users="*"/>
</authorization>
In the login.aspx.cs page,
I have provided,
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
if (FormsAuthentication.Authenticate(Login1.UserName,Login1.Password))
{
FormsAuthentication.SetAuthCookie(Login1.UserName,true);
Label1.Text = "Login Successful";
Login1.InstructionText = "";
FormsAuthentication.RedirectFromLoginPage(Login1.UserName, true);
Response.Redirect("Success.aspx")
}
else
{
Label1.Text = "You are not an authentic user";
}
}
}
but however, while execution instead of going to success.aspx
with the url http://localhost/Login.aspx?ReturnUrl=%2fSuccess.aspx
Why is this so?
If you want to set the forms auth cookie yourself and redirect correctly based on the ReturnUrl query string parameter, you should look at the FormsAuthentication.RedirectFromLoginPage method. In your example, it would be:
FormsAuthentication.RedirectFromLoginPage(Login1.UserName, true);
That method sets the appropriate Forms auth cookie / ticket and then redirects based on the presence or absence of the ReturnUrl parameter. (If absent, it goes to the configured default page.)
Hope this helps,
Donnie

Resources