Sunday, 18 August 2013

Insert custom object to Forms Authentication cookie to Identify user at each request

Forms authentication is a way that we use to login in our systems in asp.net mvc , it creates cookie on user side and user remains logged in until cookie expires , normally we use :


Where " User.Identity.IsAuthenticated " checks whether is there any user exists who is currently logged in the system and "User.Identity.Name" gives the user name ( usually email ) which we give in login form during login process , but what if we want some thing more that just an email address like , if someone wants to send his/her name,age,address or any other information or property to the server with each request from client side , because if we achieve that then we don't have to worry about what are the roles allowed to current user , what is his name , his id or anything , because in that case we don't have need to make database requests to get user information each time.
To achieve this we have "FormsAuthenticationTicket" object , we can provides your custom data in it , and we then add this object into our forms authentication cookie , and that's how custom information remains stick with each request. i.e.


where UserInfo is custom object containing user information, we add it as string , have to serialize this object to convert to object and vise versa.
We can use above described method while login process like this :

  FormsAuthenticationTicket ticket = UserAuthenticationTicketBuilder.CreateAuthenticationTicket(customer);

  SetTicket(HttpContext.Current, ticket);

Where customer is your object you wants to store in cookie , and setTicket( ) may be defined as :

 private void SetTicket(HttpContext httpContext, FormsAuthenticationTicket ticket)
        {
            var user = new User(ticket);
            if (!ticket.Expired)
            {
                string ticketval = this.Encrypt(ticket);
                string[] userRoles = user.RoleName;
                httpContext.User = new GenericPrincipal(user, userRoles);
                HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ticketval) {        Expires= DateTime.Now.Add(FormsAuthentication.Timeout); };
                cookie.Domain = "";
                httpContext.Response.Cookies.Add(cookie);
                httpContext.Response.AddHeader(FormsAuthentication.FormsCookieName, ticketval);
            }
            else
            {
                httpContext.Response.Headers.Set(FormsAuthentication.FormsCookieName, null);
                HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, null) { Expires = DateTime.Now.AddSeconds(-1) };
                httpContext.Response.Cookies.Add(cookie);
            }

        }


And User class which is accepting ticket must be implementing IIdentity and should get data out of ticket.

And finally implement this in your Global.ascx file :

 public override void Init()
        {
            this.PostAuthenticateRequest += new EventHandler(MvcApplication_PostAuthenticateRequest);
            base.Init();
        }

        void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
        {
            SetCookie();


        }

and in SetCookie() , create user object , add to request header cookie in the form of FormAuthentication cookie , the above Init() method will be called each and every time when request goes to the server and so your user object to.