I've managed to configure JWT authentication for my ASP.NET Core Web API. It works when using Postman.
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.
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.
I'm out of my depth here haha
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?
My middleware Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
// Tell Entity how to connect to the SQL Server
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
});
// Configure Identity
services.Configure<IdentityOptions>(options =>
{
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.SignIn.RequireConfirmedEmail = false; // Set to true for production, test it
options.User.RequireUniqueEmail = false; // Set to true for production
});
services.Configure<PasswordHasherOptions>(options =>
{
// 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<User, IdentityRole>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
}).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
// JWT Authentication Tokens
services.AddAuthentication(auth =>
{
// This will stop Identity using Cookies and make it use JWT tokens by default.
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = "http://mywebsite.com",
ValidIssuer = "http://mywebsite.com",
ValidateLifetime = true,
RequireExpirationTime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("rsvgy555262gthsdfrthga"))
};
options.RequireHttpsMetadata = true; // Use HTTPS to transmit the token.
});
// Admin Login Cookie
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/Admin/Login"; // Url for users to login to the app
options.Cookie.Name = ".AspNetCore.Identity.Application";
options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
options.SlidingExpiration = true;
});
services.AddControllers();
services.AddControllersWithViews();
}
My AdminController
:
public class AdminController : Controller
{
private UserManager<User> userManager; // Manage user accounts in DB
private IPasswordHasher<User> passwordHasher; // Hash user passwords
private SignInManager<User> signInManager; // Login
// Constructor
public AdminController(UserManager<User> usrMgr, IPasswordHasher<User> passwordHash, SignInManager<User> 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<IActionResult> 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("/Admin"); // Send user to localhost/Admin after login
}
}
ModelState.AddModelError(nameof(login.Email), "Login Failed: Invalid Email or password");
}
return View(login);
}
// Admin Logout
public async Task<IActionResult> Logout()
{
await signInManager.SignOutAsync();
return RedirectToAction("Index");
}
// Admin Index Page
[Authorize]
public IActionResult Index()
{
return View(userManager.Users);
}
}
Thanks, any help getting the cookies to work would be appreciated.