Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FormsAuthentication Roles without Membership

I'm trying to use FormsAuthentication and it's working fine at the moment with user name and password. I need to add User Role to the Forms authentication Ticket and i'm not using ASP.NET Membership.

if (rep.CheckUser(model.UserName, model.Password,out UserRole))//Check User
  {

  FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

 // Roles.AddUserToRole(model.UserName, UserRole);//This Requires Membership

  return Redirect(FormsAuthentication.DefaultUrl);

 }
like image 558
chamara Avatar asked Jun 05 '13 06:06

chamara


1 Answers

FormsAuthenticationTicket constructor (the one with the most parameters) has userData parameter which takes a string. It is here that you can add your roles, separated by some character like pipe (|) or hash. How you plan to use is up to you. What you would normally do is to register AuthenticateRequest event. So, you could create a ticket this was:

private void CreateTicket()
{
    var ticket = new FormsAuthenticationTicket(
            version: 1,
            name: UserName,
            issueDate: DateTime.Now,
            expiration: DateTime.Now.AddSeconds(httpContext.Session.Timeout),
            isPersistent: false,
            userData: String.Join("|", arrayOfRoles));

    var encryptedTicket = FormsAuthentication.Encrypt(ticket);
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

    httpContext.Response.Cookies.Add(cookie);
}

After that in global.asax you would do something like this:

public override void Init()
{
    base.AuthenticateRequest += OnAuthenticateRequest;
}

private void OnAuthenticateRequest(object sender, EventArgs eventArgs)
{
    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        var decodedTicket = FormsAuthentication.Decrypt(cookie.Value);
        var roles = decodedTicket.UserData.Split(new[] {"|"}, StringSplitOptions.RemoveEmptyEntries);

        var principal = new GenericPrincipal(HttpContext.Current.User.Identity, roles);
        HttpContext.Current.User = principal;
    }
}

Now you have roles in IPrincipal object (HttpContext.Current.User) and when you query with HttpContext.Current.User.IsUserInRole("RoleName") you will get true or false. That way you should be able to avoid using Roles provider.

UPDATE: A better event to call in order to handle recreating User principal is Application_AuthenticateRequest instead of BeginRequest. I have updated the code to reflect this.

like image 73
Husein Roncevic Avatar answered Oct 14 '22 14:10

Husein Roncevic