title: Asp.Net Core 3.1 Cookie Authentication loop to login page
body: <p>When I successfully signed in to the HTTP context and I'm redirected to the home controller, the Authorize Attribute of the HomeController redirects me to the login path, because I don't know. (Infinite loop)</p>
  <p>The validate async method doesn't sign me out or reject the cookie (I checked it.)</p>
  <p>But where's the problem?
  I have the same authentication process in an ASP.NET Core 2.1 project and there it works perfectly.</p>
  <p>I test it with a custom authorize attribute to check the context. In the context I've a principal and I'm authenticated.</p>
  <p>But why redirect me the standard authorize attribute?</p>
  <p>My configuration is:</p>
  <p>HomeController.cs</p>
  <pre><code>public class HomeController : Controller
  {
      [Authorize]
      public IActionResult Index()
      {
          return this.View(&quot;Index&quot;);
      }
  }
  </code></pre>
  <p>Startup.cs</p>
  <pre><code>public void ConfigureServices(IServiceCollection services)
      {
          services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
              .AddCookie(options =&gt;
              {
                  options.LoginPath = &quot;/auth/login/&quot;;
                  options.ExpireTimeSpan = TimeSpan.FromDays(7);
                  options.Events.OnValidatePrincipal = ValidateAsync;
              });
  
          services.AddControllersWithViews();
  
          services.AddAntiforgery();
  
          services.AddDbContext&lt;ApplicationDbContext&gt;((serviceProvider, options) =&gt;
          {
              options.UseSqlServer(this.Configuration.GetConnectionString(&quot;DefaultConnection&quot;));
              options.EnableSensitiveDataLogging();
          });
      }
  
  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
          if(env.IsDevelopment())
          {
              app.UseDeveloperExceptionPage();
          }
          else
          {
              app.UseExceptionHandler(&quot;/Home/Error&quot;);
              // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
              app.UseHsts();
          }
  
          app.UseHttpsRedirection();
          app.UseStaticFiles();
  
          app.UseRouting();
  
          app.UseAuthorization();
          app.UseAuthentication();
  
          app.UseEndpoints(endpoints =&gt;
          {
              endpoints.MapControllerRoute(
                  name: &quot;default&quot;,
                  pattern: &quot;{controller=Home}/{action=Index}/{id?}&quot;);
          });
      }
  
  public static async Task ValidateAsync(CookieValidatePrincipalContext context)
      {
          context = context ?? throw new ArgumentNullException(nameof(context));
  
          String userId = context.Principal.Claims.FirstOrDefault(claim =&gt; claim.Type == ClaimTypes.NameIdentifier)?.Value;
  
          if(userId == null)
          {
              context.RejectPrincipal();
              await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
              return;
          }
  
          ApplicationDbContext dbContext = context.HttpContext.RequestServices.GetRequiredService&lt;ApplicationDbContext&gt;();
          User user = await dbContext.Users.FindAsync(Guid.Parse(userId));
  
          if(user == null)
          {
              context.RejectPrincipal();
              await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
              return;
          }
  
          if(!user.StaySignedIn &amp;&amp; 
              user.LastLogin != null &amp;&amp; 
              (user.LastLogin.Subtract(TimeSpan.FromDays(1)) &gt; DateTimeOffset.Now))
          {
              context.RejectPrincipal();
              await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
              return;
          }
      }
  </code></pre>
  <p>AuthController.cs</p>
  <pre><code>[Route(&quot;/login&quot;)]
      [Route(&quot;/auth/login&quot;)]
      public async Task&lt;IActionResult&gt; Login([FromForm]LoginModel loginModel)
      {
          Claim nameIdentifier = new Claim(ClaimTypes.NameIdentifier, user.Id.ToString());
  
          ClaimsIdentity userIdentity = new ClaimsIdentity(new List&lt;Claim&gt; { nameIdentifier }, CookieAuthenticationDefaults.AuthenticationScheme);
          ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(userIdentity);
  
          await this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
          return this.RedirectToAction(&quot;Index&quot;, &quot;Home&quot;);
      }
  </code></pre>