In ASP.NET Core MVC, using a Custom Filter Attribute makes managing a logging system not only effortless but also incredibly powerful. Today, I’ll walk you through how to set this up in no time.
Building a Login Controller in ASP.NET Core MVC with Claims-Based Identity
using Microsoft.AspNetCore.Authentication;using Microsoft.AspNetCore.Authentication.Cookies;using Microsoft.AspNetCore.Authorization;using Microsoft.AspNetCore.Diagnostics;using Microsoft.AspNetCore.Mvc;using OnlineCv.Factory.Users;using OnlineCv.Models;using OnlineCv.Models.ViewModel.RequestViewModel;using OnlineCv.Utility;using System.Diagnostics;using System.Security.Claims;namespace OnlineCv.Controllers{public class HomeController : Controller{private readonly ILogger<HomeController> _logger;private readonly IUserFactory _userFactory;private readonly IUtility _utility;public HomeController(ILogger<HomeController> logger,IUserFactory userFactory,IUtility utility){_logger = logger;_userFactory = userFactory;_utility = utility;}[AllowAnonymous]public IActionResult Login(){return View(new LoginViewModel());}[AllowAnonymous][HttpPost]public async Task<IActionResult> Login(LoginViewModel loginViewModel){var user = await _userFactory.GetUserByCredential(loginViewModel.Email,loginViewModel.Password);if (user is not null){ClaimsIdentity identity = null;identity = new ClaimsIdentity(new[] {new Claim(ClaimTypes.Email,loginViewModel.Email),new Claim(ClaimTypes.Role,Constent.Roles[0])}, CookieAuthenticationDefaults.AuthenticationScheme);var principal = new ClaimsPrincipal(identity);if(HttpContext.Session.Keys.Contains("userId"))HttpContext.Session.Remove("userId");if (HttpContext.Session.Keys.Contains("token"))HttpContext.Session.Remove("token");await HttpContext.SignOutAsync(Constent.Roles[0]);await HttpContext.SignInAsync(Constent.Roles[0], principal);HttpContext.Session.SetString("userId", user.Id.ToString());var token = _utility.GenerateToken(loginViewModel.Email, user.Id.ToString(), "User");HttpContext.Session.SetString("token", token);return RedirectToAction(controllerName: "Resume", actionName: "BasicInfo");}ModelState.AddModelError(string.Empty,"Login Failed");return View();}public IActionResult Registration(){return View(new RegistrationViewModel());}[HttpPost]public async Task<IActionResult> Registration(RegistrationViewModel registrationViewModel){if (ModelState.IsValid){var res = await _userFactory.UserRegistration(registrationViewModel);ViewBag.Result = res.success;ViewBag.Message = res.message;}return View();}}}
Middleware
builder.Services.AddAuthentication(options =>{options.DefaultScheme = Constent.Roles[0];}).AddCookie(Constent.Roles[0], options =>{options.Cookie.Name = Constent.Roles[0]+".Says";options.LoginPath = "/Home/Login";});builder.Services.AddDistributedMemoryCache();builder.Services.AddSession(options =>{options.Cookie.Name = ".Online.Cv.Session";options.IdleTimeout = TimeSpan.FromHours(1);options.Cookie.IsEssential = true;});
Get User Token
public string GenerateToken(string email, string userId, string role){var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Constent.Key));var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);var secToken = new JwtSecurityToken(signingCredentials: credentials,issuer: Constent.Issuer,audience: Constent.Audiunce,claims: new[]{new Claim(JwtRegisteredClaimNames.Sub, email),new Claim(ClaimTypes.Role, role),new Claim("userId", userId)},expires: DateTime.UtcNow.AddHours(1));var handler = new JwtSecurityTokenHandler();return handler.WriteToken(secToken);}
Make sure you have assigned Middleware Methods as well
app.UseAuthentication();app.UseAuthorization();app.UseSession();
Custom Filter Attribute
public class AuthenticationAttribute : Attribute, IAsyncActionFilter{public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){var token = context.HttpContext.Session.GetString("token");var userId = context.HttpContext.Session.GetString("userId");if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(userId)){context.Result = new RedirectToActionResult(actionName: "Login", controllerName: "Home", routeValues: "");return;}if (!ValidateToken(token.ToString()).success){context.Result = new RedirectToActionResult(actionName: "Login", controllerName: "Home", routeValues: "");return;}if (!ValidateUser(token, userId).success){context.Result = new RedirectToActionResult(actionName: "Login", controllerName: "Home", routeValues: "");return;}await next();}private (bool success, string message) ValidateToken(string authToken){var tokenHandler = new JwtSecurityTokenHandler();var validationParameters = GetValidationParameters();SecurityToken validatedToken;try{IPrincipal principal = tokenHandler.ValidateToken(authToken, validationParameters, out validatedToken);}catch (Exception e){return (false,e.Message);}return (true,"Token Verified");}private (bool success, string? userId, string message) ValidateUser(string authToken, string userId){var tokenHandler = new JwtSecurityTokenHandler();var key = Encoding.UTF8.GetBytes(Constent.Key);var tokenValidationParameters = GetValidationParameters();ClaimsPrincipal principal;try{principal = tokenHandler.ValidateToken(authToken, tokenValidationParameters, out _);}catch (SecurityTokenException ex){return (false, null, ex.Message);}var userIdClaim = principal.FindFirst("userId");if (userIdClaim == null)return (false, null, "User not found");return (userIdClaim.Value.ToLower()==userId.ToLower(), userIdClaim.Value, "user found");}private TokenValidationParameters GetValidationParameters(){return new TokenValidationParameters(){ClockSkew = TimeSpan.Zero,ValidIssuer = Constent.Issuer,ValidAudience = Constent.Audiunce,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Constent.Key))};}}
Useage of Custom Filter Attribute
//Microsoft Default Singin Management Attribute[Authorize(Roles = "User", AuthenticationSchemes = "User")]//Custom Attribue[Authentication]