Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forms Authentication understanding context.user.identity

Since documentation on this process is very vague and confusing (or old), I wanted to verify that I was doing it correctly and not missing any steps.

I am trying to create a secure login system, that expires on browser-close.

-- in my web.config I have the following --

<authentication mode="Forms">
      <forms loginUrl="~/Login.aspx" defaultUrl="Index.aspx" name=".ASPXFORMSAUTH" timeout="100" />
    </authentication>
    <authorization>
      <allow users="?" />
    </authorization>
    <machineKey decryption="AES" validation="SHA1" validationKey.......... />

So I have a login form with username/password textbox and this button:

<asp:Button ID="LoginButton" runat="Server" OnClick="Login_Authenticate" Text="Sign in" />

Inside Login_Authenticate I do the following:

protected void Login_Authenticate(object sender, EventArgs e){
string userName = UserName.Text;
string password = Password.Text;

bool Authenticated = false;

// Here's code that makes sure that Username and Password is CORRECT
if(AuthClass.Authenticate(userName, password)){
 Authenticated = true;
}
// error checking does happen here.

if (Authenticated)
{
  FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(30), rememberUserName, String.Empty, FormsAuthentication.FormsCookiePath);
  string encryptedCookie = FormsAuthentication.Encrypt(ticket);
  HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookie);
  cookie.Expires = DateTime.Now.AddMinutes(30);
  Response.Cookies.Add(cookie);
  //FormsAuthentication.RedirectFromLoginPage(userName, false);

  Response.Redirect("MainPage.aspx");
}
}

--- in the MasterPage.master.cs I have the following check in Page_Init() ---

if (Context.User.Identity.IsAuthenticated)
    {
      int userid = (int)Session["userid"];
      if (userid == null)
      {
        userid = GetUserID(Context.User.Identity.Name);
        if (userid != null)
        {
          Session["userid"] = userid;
        }
      }
    }

EDIT: --- GLOBAL.ASAX ; some code that I am not quite sure is correct or know what it does

protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        // look if any security information exists for this request
        if (HttpContext.Current.User != null)
        {
            // see if this user is authenticated, any authenticated cookie (ticket) exists for this user
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                // see if the authentication is done using FormsAuthentication
                if (HttpContext.Current.User.Identity is FormsIdentity)
                {
                    // Get the roles stored for this request from the ticket
                    // get the identity of the user
                    FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;
                    //Get the form authentication ticket of the user
                    FormsAuthenticationTicket ticket = identity.Ticket;
                    //Get the roles stored as UserData into ticket
                    string[] roles = { };
                    //Create general prrincipal and assign it to current request

                    HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(identity, roles);
                }
            }
        }
    }

--- from then on, on every page, I use the Session userid to gather the user information and content and make sure the user has proper authentication and group-role permissions.

Is this all correct? Or do I have to Decrypt anything somewhere?

Is this enough to make a secure user login? Or should I not bother with forms authentication and find my own way to make my own cookies and manage it myself?

like image 847
Dexter Avatar asked Jan 10 '12 21:01

Dexter


People also ask

Can you explain forms authentication in detail?

Forms authentication enables user and password validation for Web applications that do not require Windows authentication. With forms authentication, user information is stored in an external data source, such as a Membership database, or in the configuration file for an application.

How do you set context user identity?

You can achieve this by manually settings HttpContext. User: var identity = new ClaimsIdentity("Custom"); HttpContext. User = new ClaimsPrincipal(identity);

What is the difference between logic controls and forms authentication?

What is the difference between login controls and Forms authentication? Forms authentication can be easily implemented using login controls without writing any code. Login control performs functions like prompting for user credentials, validating them and issuing authentication just as the FormsAuthentication class.

How many types of authentication are there in ASP.NET MVC?

There are three types of authentication available in ASP.NET MVC. For form authentication the user needs to provide his credentials through a form. Windows Authentication is used in conjunction with IIS authentication.


2 Answers

The way your code is written logins will persist across browser sessions. It might help to understand the basics of what is going on.

For cookie based authentication methods, there are really three actions:

1) Login - validates user's credentials and creates and stores a cookie on their browser.

2) Logout - simply removes the cookie from the browser (by expiring the cookie or deleting it)

3) Per Request Validation (the part that is is your Application_AuthenticateRequest) - check to see if a cookie exists, and if so, get the user's Identity and Roles and set HttpContext.Current.User.

Typically, the FormsAuthentication module hides most of this from you. It looks like your code is trying to use some of the elements of FormAuthentication (like the FormsAuthenticationTicket and FormsIdentity. This is fine as long as you get what you want.

Your Login_Authenticate method looks fine EXCEPT you are setting an expiration on the cookie. This will make the cookie persist even if you close and reopen the browser. Since this is not the behavior you want, I would not set a cookie expiration. Setting this is like checking the "remember me" checkbox.

The code in Application_AuthenticateRequest gets run every time a page is served from your application. It's primary job is to set HttpContext.Current.User. Typically, if no user is logged in, User is either null or an Anonymous user. If a user is logged in, this should represent your user.

If you are doing these three things, then anywhere in your code you can reference HttpContext.Current.User to decide what level of information you want to display. For instance, if you want to restrict a page to administrators only, you could call HttpContext.Current.Users.IsInRole("Administrators"), and redirect them away from the page if the call returns false.

Hope this helps.

like image 61
Joe Enzminger Avatar answered Sep 23 '22 01:09

Joe Enzminger


I am a bit late on the subject, but for those trying to implement forms authentication while keeping things simple (like I was trying to), here is the relevant most current documentation I have found from Microsoft: https://docs.microsoft.com/en-us/previous-versions/aspnet/xdt4thhy(v=vs.100)

In short, do not mess up with setting cookies, checking them, instantiating tickets or principal, ... Leave-it to FormsAuthentication class.

On log on, when your code has check credentials and if they are valid, just call:

FormsAuthentication.RedirectFromLoginPage(yourUserId, false);

It does set the authentication cookie for you, which, combined with the redirect, is enough. The "false" is for not persisting the authorization: it will be lost on browser close (or authorization timeout).

On already authenticated request, there is nothing to check by code for ensuring your authentication is valid. Use Context.User.Identity.Name to know who is connected (would be the string yourUserId above).

On explicit logout, call

FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();

And have forms authentication configured in web.config.

<system.web>
  <authentication mode="Forms">
    <forms loginUrl="yourLoginPage" defaultUrl="yourDefaultPageAfterLogin">
    </forms>
  </authentication>
  <authorization>
    <deny users="?" />
  </authorization>
</system.web>

Note that for MVC applications the authorization part should be removed from configuration and handled with AuthorizeAttribute registered as a global filter attribute, with usage of AllowAnonymousAttribute on controllers or actions needing it. (MVC 4; prior to this one, it was required to create its own attributes for handling that.)

like image 41
Frédéric Avatar answered Sep 20 '22 01:09

Frédéric