ArneDEPR
ArneDEPR

Reputation: 5

Application_AuthenticateRequest fires to late

When I create my formsauthenticationticket the Application_AuthenticateRequest (in global.asax) is fired not immediatly. When I check user.isrole it's empty. But later on when I try another action the Application_AuthenticateRequest is fired, and the roles of the user are set.

Login function:

      if (loggedIn)
            {
                ViewBag.loginFailed = 1;
                string roles = "Administrator";
                CreateTicket(pharmacist.ID.ToString(), roles);
                LoginRedirect();
            }

Methods:

    [Authorize(Roles = "Administrator, User")]
    private void CreateTicket(string id, string role)
    {

        var ticket = new FormsAuthenticationTicket(
                version: 1,
                name: id,
                issueDate: DateTime.Now,
                expiration: DateTime.Now.AddHours(1),
                isPersistent: false,
                userData: role);

        var encryptedTicket = FormsAuthentication.Encrypt(ticket);
        var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        HttpContext.Response.Cookies.Add(cookie);
    }

   [Authorize(Roles = "Administrator, User")]
    private ActionResult LoginRedirect() {
        if (User.IsInRole("Administrator"))
        {
            return RedirectToAction("Index", "Pharmacist");
        }
        else if (User.IsInRole("User"))
        {
            return RedirectToAction("Index", "Patient");
        }
        else {
            return RedirectToAction("Logout", "Authentication");
        }
    }

Application_AuthenticateRequest

  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);
                }
            }
        }
    }

Upvotes: 0

Views: 1223

Answers (1)

Win
Win

Reputation: 62260

Application_AuthenticateRequest is only called when you request a new resource.

In your case, you are still in the request which creates FormsAuthenticationTicket. As the result, Principal object hasn't been assigned to the current thread yet.

If you want to retrieve IPrincipal from the current thread, you will need to assign it explicitly.

var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
// You need this two lines.
HttpContext.Current.User = new GenericPrincipal(id, roles); 
Thread.CurrentPrincipal = HttpContext.Current.User;
....

Also make sure you have those two line inside Application_AuthenticateRequest.

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
   ...
   HttpContext.Current.User = new GenericPrincipal(id, roles);
   Thread.CurrentPrincipal = HttpContext.Current.User; <-- Do not forget this.
   ...
}

FYI: You do not need AuthorizeAttribute on private method. You only want it on Controller or Action Methods.

[Authorize(Roles = "Administrator, User")] <-- This is not needed.
private void CreateTicket(string id, string role)
{
   ...
}

Upvotes: 2

Related Questions