title: Application_AuthenticateRequest keeps calling infinite redirects
body: <p>This is a continuation of my <a href="https://stackoverflow.com/q/10846307/481656">previous question here</a>.</p>
  
  <p>I have tried to use the built in ASP Login mechanism but it didn't work for me. The primary reason being, I'm asked to keep it bare and simple.</p>
  
  <p>Now, here is where I stand:</p>
  
  <p><strong>Web.config</strong></p>
  
  <pre><code>&lt;system.web&gt;
      &lt;sessionState timeout="10" /&gt;
  
      &lt;authentication mode="Forms"&gt;
          &lt;forms timeout="30" loginUrl="~/SecuredArea/LogInOut/log-in.aspx" /&gt;
      &lt;/authentication&gt;
  
      &lt;authorization&gt;
          &lt;allow users="?" /&gt;
      &lt;/authorization&gt;
  
  &lt;/system.web&gt;
  
  &lt;location path="SecuredArea/AdminArea"&gt;
      &lt;system.web&gt;
          &lt;authorization&gt;
              &lt;allow roles="administrators" /&gt;
              &lt;deny users="*" /&gt;
          &lt;/authorization&gt;
      &lt;/system.web&gt;
  &lt;/location&gt;
  
  &lt;location path="SecuredArea/EmployeeArea"&gt;
      &lt;system.web&gt;
          &lt;authorization&gt;
              &lt;allow roles="employees" /&gt;
              &lt;deny users="*" /&gt;
          &lt;/authorization&gt;
      &lt;/system.web&gt;
  &lt;/location&gt;
  </code></pre>
  
  <p><strong>Global.asax</strong></p>
  
  <pre><code>protected void Application_AuthenticateRequest(Object sender, EventArgs e)
  {
      if (HttpContext.Current.User != null)
      {
          if (HttpContext.Current.User.Identity.IsAuthenticated)
          {
              IIdentity userId = HttpContext.Current.User.Identity;
  
              //if role info is already NOT loaded into cache, put the role info in cache
              //if (HttpContext.Current.Cache[userId.Name] == null)
              //{
              //  string[] roles;
  
              //  if (userId.Name == "admin")
              //  {
              //    roles = new string[1] { "administrators" };
              //  }
              //  else if (userId.Name == "member1")
              //  {
              //    roles = new string[1] { "employees" };
              //  }
              //  else
              //  {
              //    roles = new string[1] { "public" };
              //  }
  
                //1 hour sliding expiring time. Adding the roles in cache. 
                //This will be used in Application_AuthenticateRequest event located in Global.ascx.cs 
                //file to attach user Principal object.
              //  HttpContext.Current.Cache.Add(userId.Name, roles, null, DateTime.MaxValue, TimeSpan.FromHours(1), CacheItemPriority.BelowNormal, null);
              //}
  
              //now assign the user role in the current security context
              HttpContext.Current.User = new GenericPrincipal(userId, (string[])HttpContext.Current.Cache[userId.Name]);
          }
      }
  }
  </code></pre>
  
  <p>I have commented the confusing code here because I don't want to access DB and loop through all possible employees here. For the admin account, it's easy, but for employee account, it's not possible.</p>
  
  <p><strong>log-in.aspx.cs</strong></p>
  
  <pre><code>protected void ButtonLogOn_Click(object sender, EventArgs e)
  {
      if (String.IsNullOrEmpty(txtUserName.Value.Trim()) || String.IsNullOrEmpty(txtPassword.Value.Trim()))
      {
          labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
      }
      else
      {
          try
          {
              LoginPage loginBack = new LoginPage();
              int result = loginBack.VerifyCredentials(txtUserName.Value.Trim(), txtPassword.Value.Trim());
  
              switch (result)
              {
                  case -9:
                  //System needs provisioning
                  labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("SMB Password Reset System need provisioning. Login as Administrator.");
                  break;
  
                  case 0:
                  //Enroll-able User
                  // Success, create non-persistent authentication cookie.
                  FormsAuthentication.SetAuthCookie(txtUserName.Value.Trim(), false);
  
                  FormsAuthenticationTicket ticketEmployee =
                      new FormsAuthenticationTicket(
                          1,                                                      // version
                          txtUserName.Value.Trim(),           // get username  from the form
                          DateTime.Now,                                   // issue time is now
                          DateTime.Now.AddMinutes(10),    // expires in 10 minutes
                          false,                                              // cookie is not persistent
                          "employees");
  
                  HttpCookie cookieEmployee = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticketEmployee));
                  Response.Cookies.Add(cookieEmployee);
  
                  SiteLogin.PerformAuthentication(txtUserName.Value.Trim(), false);
                  break;
  
                  case 1:
                  //User not in required directory group
                  labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You cannot login because you are not authorized.");
                  break;
  
                  default:
                  //Bad name and/or password                              
                  labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
                  break;
              }
          }
          catch (MessageSecurityException expMse)
          {
              //Bad name and/or password
              Debug.WriteLine("Error: " + expMse.Message);
              labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
          }
          catch (Exception exp)
          {
              labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("Some general error has occured. Message reads: " + exp.Message);
          }
      }
  }
  
  protected void ButtonAdminLogOn_Click(object sender, EventArgs e)
  {
      if (String.IsNullOrEmpty(txtUserName.Value) || String.IsNullOrEmpty(txtPassword.Value))
          labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("&lt;strong&gt;Login Please!&lt;/strong&gt;&lt;hr/&gt;You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
      else
      {
          //if the log-in is successful
          if (txtUserName.Value == "admin" &amp;&amp; txtPassword.Value == "AlphaBeta")
          {
              // Success, create non-persistent authentication cookie.
              FormsAuthentication.SetAuthCookie(txtUserName.Value.Trim(), false);
  
              FormsAuthenticationTicket ticketAdmin =
                  new FormsAuthenticationTicket(
                      1,                                                      // version
                      txtUserName.Value.Trim(),           // get username  from the form
                      DateTime.Now,                                   // issue time is now
                      DateTime.Now.AddMinutes(10),    // expires in 10 minutes
                      false,                                              // cookie is not persistent
                      "administrators");
  
              HttpCookie cookieAdmin = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticketAdmin));
              Response.Cookies.Add(cookieAdmin);
  
              SiteLogin.PerformAdminAuthentication(txtUserName.Value.Trim(), false);
          }
          else
          {
              labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("&lt;strong&gt;Login Failed!&lt;/strong&gt;&lt;hr/&gt;The username and/or password you entered do not belong to any Administrator account on our system.&lt;br/&gt;You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
          }
      }
  }
  </code></pre>
  
  <p>Lastly, utility class: <strong>SiteLogin.cs</strong></p>
  
  <pre><code>public sealed class SiteLogin
  {       
      public static void PerformAuthentication(string userName, bool remember)
      {
          FormsAuthentication.RedirectFromLoginPage(userName, remember);
  
          if (HttpContext.Current.Request.QueryString["ReturnUrl"] == null)
          {
              RedirectToDefaultPage();
          }
          else
          {
              HttpContext.Current.Response.Redirect(HttpContext.Current.Request.QueryString["ReturnUrl"]);
          }
      }
  
      public static void PerformAdminAuthentication(string userName, bool remember)
      {
          FormsAuthentication.RedirectFromLoginPage(userName, remember);
  
          if (HttpContext.Current.Request.QueryString["ReturnUrl"] == null)
          {
              RedirectToAdminDefaultPage();
          }
          else
          {
              HttpContext.Current.Response.Redirect(HttpContext.Current.Request.QueryString["ReturnUrl"]);
          }
      }
  
      /// &lt;summary&gt;
      /// Redirects the current user based on role
      /// &lt;/summary&gt;
      public static void RedirectToDefaultPage()
      {
          HttpContext.Current.Response.Redirect("~/SecuredArea/EmployeeArea/EmployeeDefaultPage.aspx");
      }
  
      /// &lt;summary&gt;
      /// Redirects the current user based on role
      /// &lt;/summary&gt;
      public static void RedirectToAdminDefaultPage()
      {
          HttpContext.Current.Response.Redirect("~/SecuredArea/AdminArea/AdminDefaultPage.aspx");
      }
  
      public static void LogOff()
      {
          // Put user code to initialize the page here
          FormsAuthentication.SignOut();
  
          //// Invalidate roles token
          //Response.Cookies[Globals.UserRoles].Value = "";
          //Response.Cookies[Globals.UserRoles].Path = "/";
          //Response.Cookies[Globals.UserRoles].Expires = new System.DateTime(1999, 10, 12);
  
          //Set the current user as null
          HttpContext.Current.User = null;
      }
  }
  </code></pre>
  
  <p>Now, I'm getting a seriously inconsistent behavior whenever I try to login. Biggest issue is that once I try to access any of the protected pages for Admin or Employee, i get redirected to the Login page. I provide the details and attempt to login and in both (the simple admin login and the complex employee login) cases, I get an error in browser. IE wasn't making much sense but Firefox complain made some sense:</p>
  
  <blockquote>
    <p><strong>The page isn't redirecting properly</strong>
    <em>Pale Moon has detected that the server is redirecting the request for this address in a way that will never complete.</em> 
    This problem can sometimes be caused by disabling or refusing to accept cookies.</p>
  </blockquote>
  
  <p>I'm having a bad time debugging this but it seems that one inside <code>Global.asax</code>'s <code>Application_AuthenticateRequest()</code> method, the method is just called over and over.</p>
  
  <p>Funny thing is that if I go to the unprotected pages, I can see myself as logged in and get the "Welcome Admin!, Logout" in my header. This is dynamicly done through Master page</p>
  
  <pre><code>&lt;div class="info-area"&gt;
      &lt;asp:LoginView ID="HeadLoginView" runat="server" EnableViewState="false"&gt;
          &lt;LoggedInTemplate&gt;
              Welcome &lt;span class="bold"&gt;
                  &lt;asp:LoginName ID="HeadLoginName" runat="server" /&gt;
              &lt;/span&gt;! |
          &lt;/LoggedInTemplate&gt;
      &lt;/asp:LoginView&gt;
      &lt;asp:LoginStatus ID="HeadLoginStatus" runat="server" LogoutAction="Redirect" LogoutText="Logout" LogoutPageUrl="~/SecuredArea/LogInOut/log-out.aspx" /&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Can anyone identify the issue? I really need to close this thing today. Thanks.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>I have used fiddler and I see that once I press login, an infinite loop is created. I can show the behavior through images:</p>
  
  <p><strong>Thrown to login page upon accessing a secured area</strong></p>
  
  <p><img src="https://i.stack.imgur.com/erVRa.png" alt="Thrown to login page upon accessing a secured area"></p>
  
  <p><strong>Entered the credentials and pressed the login button</strong></p>
  
  <p><img src="https://i.stack.imgur.com/QUkY6.png" alt="Entered the credentials and pressed the login button"></p>
  
  <p><strong>Credentials accepted and redirected back to secure page and redirected again to login and so forth</strong></p>
  
  <p><img src="https://i.stack.imgur.com/q29XX.png" alt="Credentials accepted and redirected back to secure page and redirected again to login and so forth"></p>
  
  <p>I choose the Cookies Tab of fiddler because there was a clear change detected there.</p>