Cookie Authentication
Moka.Auth provides cookie-based authentication for web applications, enabling secure session management and user persistence across requests.
Basic Setup
Enable cookie authentication in your Program.cs:
builder.Services.AddMokaAuth(options =>{ options.Authentication = new AuthenticationOptions { EnableCookie = true };
options.Cookie = new CookieOptions { LoginPath = "/auth/login", LogoutPath = "/auth/logout", AccessDeniedPath = "/auth/access-denied", SlidingExpiration = true, ExpireTimeSpan = TimeSpan.FromHours(2) };});Or via appsettings.json:
{ "MokaAuth": { "Authentication": { "EnableCookie": true }, "Cookie": { "LoginPath": "/auth/login", "LogoutPath": "/auth/logout", "AccessDeniedPath": "/auth/access-denied", "SlidingExpiration": true, "ExpireTimeSpan": "02:00:00" } }}Cookie Options
Security Settings
Configure cookie security options:
builder.Services.AddMokaAuth(options =>{ options.Cookie = new CookieOptions { // Cookie name and domain Name = ".Moka.Auth", Domain = null, // null for same domain as application
// Security settings HttpOnly = true, SecurePolicy = CookieSecurePolicy.Always, SameSite = SameSiteMode.Lax,
// Session settings SlidingExpiration = true, ExpireTimeSpan = TimeSpan.FromHours(2), SessionExpireTimeSpan = TimeSpan.FromMinutes(20),
// Paths LoginPath = "/auth/login", LogoutPath = "/auth/logout", AccessDeniedPath = "/auth/access-denied", ReturnUrlParameter = "returnUrl" };});Session Management
Configure session behavior and expiration:
builder.Services.AddMokaAuth(options =>{ options.Cookie = new CookieOptions { // Session configuration SlidingExpiration = true, ExpireTimeSpan = TimeSpan.FromHours(2), SessionExpireTimeSpan = TimeSpan.FromMinutes(20),
// Remember me settings AllowPersistentCookies = true, PersistentExpireTimeSpan = TimeSpan.FromDays(30),
// Ticket refresh RefreshIntervalTimeSpan = TimeSpan.FromMinutes(30), RefreshOnIssuerKeyChange = true,
// Session store settings UseDistributedCache = true, DistributedCacheExpirationMode = CacheExpirationMode.Sliding };});Cookie Events
Handle cookie authentication events:
builder.Services.AddMokaAuth(options =>{ options.Cookie = new CookieOptions { Events = new CookieEvents { OnSigningIn = async context => { // Add custom claims var identity = context.Principal.Identity as ClaimsIdentity; identity?.AddClaim(new Claim("LastLoginTime", DateTime.UtcNow.ToString())); },
OnSignedIn = async context => { // Post-login actions var userId = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier); await UpdateLastLoginTime(userId); },
OnValidatePrincipal = async context => { // Validate user on each request var userId = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier); var userService = context.HttpContext.RequestServices .GetRequiredService<IUserService>();
var user = await userService.FindByIdAsync(userId); if (user == null || user.SecurityStamp != context.Properties.GetString("SecurityStamp")) { context.RejectPrincipal(); await context.HttpContext.SignOutAsync(); } },
OnSigningOut = async context => { // Cleanup actions before logout var userId = context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); await InvalidateUserSessions(userId); } } };});Implementation
Authentication Controller
Basic authentication controller implementation:
[Route("auth")]public class AuthController : Controller{ private readonly IUserService _userService; private readonly IAuthService _authService;
[HttpGet("login")] public IActionResult Login(string returnUrl = null) { return View(new LoginModel { ReturnUrl = returnUrl }); }
[HttpPost("login")] public async Task<IActionResult> Login(LoginModel model) { if (!ModelState.IsValid) { return View(model); }
var result = await _authService.PasswordSignInAsync( model.Username, model.Password, model.RememberMe);
if (result.Succeeded) { return LocalRedirect(model.ReturnUrl ?? "/"); }
ModelState.AddModelError("", "Invalid login attempt."); return View(model); }
[HttpPost("logout")] public async Task<IActionResult> Logout() { await _authService.SignOutAsync(); return RedirectToAction("Index", "Home"); }
[HttpGet("access-denied")] public IActionResult AccessDenied() { return View(); }}Protecting Routes
Use authorization attributes to protect routes:
[Authorize]public class AccountController : Controller{ private readonly IUserService _userService;
[HttpGet("profile")] public async Task<IActionResult> Profile() { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var user = await _userService.FindByIdAsync(userId); return View(user); }
[Authorize(Roles = "Admin")] [HttpGet("settings")] public IActionResult Settings() { return View(); }
[AllowAnonymous] [HttpGet("public")] public IActionResult PublicPage() { return View(); }}Advanced Features
Multi-Factor Authentication
Enable and configure MFA:
builder.Services.AddMokaAuth(options =>{ options.Cookie = new CookieOptions { // MFA settings EnableTwoFactorAuth = true, TwoFactorAuthOptions = new TwoFactorAuthOptions { RequireConfirmedEmail = true, RequireConfirmedPhone = false, AllowRememberBrowser = true, RememberBrowserExpireHours = 720, // 30 days CodeValidityMinutes = 5, MaxFailedAttempts = 5, LockoutMinutes = 15 } };});Session Management
Configure distributed session storage:
builder.Services.AddMokaAuth(options =>{ options.Cookie = new CookieOptions { // Enable distributed cache UseDistributedCache = true, DistributedCacheOptions = new DistributedCacheOptions { InstanceName = "MokaAuth_", SlidingExpiration = true, AbsoluteExpiration = TimeSpan.FromHours(24), ConnectionString = "your-redis-connection-string" } };});