Skip to content

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"
}
}
}

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
};
});

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"
}
};
});