title: ASP.NET Core - Using both Cookies and JWT for WebAPI
body: <p>I've managed to configure JWT authentication for my ASP.NET Core Web API. It works when using Postman.</p>
  <p>I have also built an MVC admin section, that I want to log into. The guide I'm following to create the Admin section uses cookies and not JWT authentication for the log in page.</p>
  <p>It doesn't work, I get 401 authentication error after the login. It redirects me to the correct page and you can see the Identity cookie in the browser but I'm not authenticated.</p>
  <p><a href="https://i.stack.imgur.com/O0cUT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/O0cUT.png" alt="Login Page" /></a></p>
  <p><a href="https://i.stack.imgur.com/jEkfP.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/jEkfP.png" alt="Admin Page" /></a></p>
  <p>I'm out of my depth here haha</p>
  <p>Can I also use cookies as well as JWT authentication? JWT for any mobile phone app that wants to access the WebAPI but Cookies and sessions for logging in through the WebAPI's admin page?</p>
  <p>My middleware <code>Startup.cs</code>:</p>
  <pre><code>public void ConfigureServices(IServiceCollection services)
  {
          // Tell Entity how to connect to the SQL Server
          services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt; 
          {
              options.UseSqlServer(Configuration.GetConnectionString(&quot;DefaultConnection&quot;));
          });
  
          // Configure Identity
          services.Configure&lt;IdentityOptions&gt;(options =&gt;
          {
              options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
              options.Lockout.MaxFailedAccessAttempts = 5;
              options.Lockout.AllowedForNewUsers = true;
              options.User.AllowedUserNameCharacters = &quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+&quot;;
              options.SignIn.RequireConfirmedEmail = false;                   // Set to true for production, test it
              options.User.RequireUniqueEmail = false;                        // Set to true for production
          });
  
          services.Configure&lt;PasswordHasherOptions&gt;(options =&gt;
          {
              // First byte of the hashed password is 0x00 = V2 and 0x01 = V3
              options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV3;        // Default IdentityV2 is used, it uses SHA1 for hashing, 1000 iterations.
              options.IterationCount = 12000;                                                // With IdentityV3 we can use SHA256 and 12000 iterations.
          });
  
          // We need to add the IdentityUser to Entity and create a token for authentication.
          services.AddIdentity&lt;User, IdentityRole&gt;(options =&gt;
          {
              options.Password.RequireDigit = true;
              options.Password.RequireLowercase = true;
              options.Password.RequireUppercase = true;
              options.Password.RequiredLength = 6;
  
          }).AddEntityFrameworkStores&lt;ApplicationDbContext&gt;().AddDefaultTokenProviders();
  
  
          // JWT Authentication Tokens
          services.AddAuthentication(auth =&gt;
         {
             // This will stop Identity using Cookies and make it use JWT tokens by default.
             auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
             auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
         }).AddJwtBearer(options =&gt;
         {
             options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
             {
                 ValidateIssuer = true,
                 ValidateAudience = true,
                 ValidAudience = &quot;http://mywebsite.com&quot;,
                 ValidIssuer = &quot;http://mywebsite.com&quot;,
                 ValidateLifetime = true,
                 RequireExpirationTime = true,
                 ValidateIssuerSigningKey = true,
                 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(&quot;rsvgy555262gthsdfrthga&quot;))
             };
             options.RequireHttpsMetadata = true;                    // Use HTTPS to transmit the token.
         });
  
          // Admin Login Cookie
          services.ConfigureApplicationCookie(options =&gt;
          {
              options.LoginPath = &quot;/Admin/Login&quot;;                             // Url for users to login to the app
              options.Cookie.Name = &quot;.AspNetCore.Identity.Application&quot;;
              options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
              options.SlidingExpiration = true;
          });
  
          services.AddControllers();
          services.AddControllersWithViews();
  
  }
  </code></pre>
  <p>My <code>AdminController</code>:</p>
  <pre><code>public class AdminController : Controller
  {
      private UserManager&lt;User&gt; userManager;                  // Manage user accounts in DB
      private IPasswordHasher&lt;User&gt; passwordHasher;           // Hash user passwords
      private SignInManager&lt;User&gt; signInManager;              // Login
  
      // Constructor
      public AdminController(UserManager&lt;User&gt; usrMgr, IPasswordHasher&lt;User&gt; passwordHash, SignInManager&lt;User&gt; signinMgr)
      {
          userManager = usrMgr;
          passwordHasher = passwordHash;
          signInManager = signinMgr;
      }
  
      // Admin Login Page
      [AllowAnonymous]
      public IActionResult Login(string returnUrl)
      {
          Login login = new Login();
          return View(login);
      }
  
      // Admin Login Module
      [HttpPost]
      [AllowAnonymous]
      [ValidateAntiForgeryToken]
      public async Task&lt;IActionResult&gt; Login(Login login)
      {
          if (ModelState.IsValid)
          {
              User loginUser = await userManager.FindByEmailAsync(login.Email);
  
              if (loginUser != null)
              {
                  // Sign out any user already signed in
                  await signInManager.SignOutAsync();
  
                  // Sign in the new user
                  Microsoft.AspNetCore.Identity.SignInResult result = await signInManager.PasswordSignInAsync(loginUser, login.Password, false, false);
                  if (result.Succeeded)
                  {
                      return Redirect(&quot;/Admin&quot;); // Send user to localhost/Admin after login
                  }
              }
  
              ModelState.AddModelError(nameof(login.Email), &quot;Login Failed: Invalid Email or password&quot;);
          }
  
          return View(login);
      }
  
      // Admin Logout
      public async Task&lt;IActionResult&gt; Logout()
      {
          await signInManager.SignOutAsync();
          return RedirectToAction(&quot;Index&quot;);
      }
  
      // Admin Index Page
      [Authorize]
      public IActionResult Index()
      {
          return View(userManager.Users);
      }
  }
  </code></pre>
  <p>Thanks, any help getting the cookies to work would be appreciated.</p>