Autenticación basada en Cookies en ASP.NET Core

ASP.NET Core ofrece un robusto framework para la gestión de la autenticación. Es recomendable aprovechar estas funcionalidades integradas en lugar de implementar soluciones personalizadas.

Configuración de la Autenticación

La configuración se realiza principalmente en el archivo Startup.cs dentro del método ConfigureServices.


using Microsoft.AspNetCore.Authentication.Cookies;
using Uap.Areas.Admin.Service; // Asegúrate de que este namespace sea correcto

public class Startup
{
   public Startup(IConfiguration configuration)
   {
       Configuration = configuration;
   }

   public IConfiguration Configuration;

   public void ConfigureServices(IServiceCollection services)
   {
       services.AddControllersWithViews(); // O AddMvc() si prefieres

       // Registrar servicios
       services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
       services.AddScoped<IAdminService, AdminServiceImpl>(); // Servicio de ejemplo

       // Configurar autenticación basada en Cookies
       services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
           .AddCookie(options =>
           {
               options.LoginPath = "/Account/Login"; // Ruta a la página de inicio de sesión
               options.LogoutPath = "/Account/Logout"; // Ruta para cerrar sesión
               options.AccessDeniedPath = "/Shared/AccessDenied"; // Ruta para acceso denegado
               options.ExpireTimeSpan = TimeSpan.FromMinutes(30); // Duración de la cookie de autenticación
               options.SlidingExpiration = true; // Extiende la cookie si el usuario está activo
           });

       // Configurar políticas de cookies
       services.Configure<CookiePolicyOptions>(options =>
       {
           options.CheckConsentNeeded = context => true; // Solicitar consentimiento del usuario para cookies no esenciales
           options.MinimumSameSitePolicy = SameSiteMode.Lax; // Política SameSite
       });

       services.AddHttpContextAccessor();
   }

   public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
   {
       if (env.IsDevelopment())
       {
           app.UseDeveloperExceptionPage();
       }
       else
       {
           app.UseExceptionHandler("/Home/Error");
           app.UseHsts();
       }

       app.UseHttpsRedirection();
       app.UseStaticFiles();

       app.UseRouting();

       // Importante: Asegurarse de que UseAuthentication se ejecute antes de UseAuthorization
       app.UseAuthentication();
       app.UseAuthorization();

       app.UseEndpoints(endpoints =>
       {
           endpoints.MapControllerRoute(
               name: "default",
               pattern: "{controller=Home}/{action=Index}/{id?}");

           // Si usas áreas, como en el ejemplo original
           endpoints.MapAreaControllerRoute(
               name: "areas",
               areaName: "Admin",
               pattern: "Admin/{controller=Home}/{action=Index}/{id?}");
       });
   }
}
   

Implementación del Inicio de Sesión

En tu controlador, por ejemplo, un controlador de cuenta o de administración, puedes implementar la lógica de inicio de sesión.


using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Uap.Areas.Admin.Models; // Asume que AdminModel está aquí
using Uap.Areas.Admin.Service; // Asume que IAdminService está aquí

[Route("[controller]")]
public class AccountController : Controller
{
   private readonly IAdminService _adminService;

   public AccountController(IAdminService adminService)
   {
       _adminService = adminService;
   }

   [HttpPost("login")]
   [AllowAnonymous] // Permite acceso anónimo a esta acción
   public async Task<IActionResult> Login([FromBody] LoginViewModel model)
   {
       if (!ModelState.IsValid)
       {
           return BadRequest(ModelState);
       }

       // Aquí iría tu lógica para validar las credenciales del usuario
       // Ejemplo: bool isValid = _adminService.AuthenticateUser(model.Username, model.Password);
       // Supongamos que _adminService.AuthenticateUser devuelve un objeto User si es válido
       var authenticatedUser = _adminService.AuthenticateUser(model.Username, model.Password); // Método de ejemplo

       if (authenticatedUser == null)
       {
           return Unauthorized("Credenciales inválidas.");
       }

       // Crear las claims del usuario
       var claims = new List<Claim>
       {
           new Claim(ClaimTypes.Name, authenticatedUser.Username),
           new Claim(ClaimTypes.Role, authenticatedUser.Role), // Por ejemplo, "Admin" o "User"
           // Puedes añadir más claims según necesites
       };

       // Crear la identidad del usuario
       var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

       // Crear el principal de seguridad
       var principal = new ClaimsPrincipal(identity);

       // Iniciar sesión al usuario
       await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties
       {
           IsPersistent = model.RememberMe // Opción para recordar al usuario
       });

       // Redireccionar al usuario a la página de origen o a una página por defecto
       var returnUrl = Request.Form["returnUrl"]; // Si se pasa como parámetro en el form
       if (string.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))
       {
           returnUrl = Url.Content("~/"); // Página principal por defecto
       }
       
       // Podrías devolver Ok() si el cliente maneja la redirección, o redirigir aquí
       // return LocalRedirect(returnUrl); 
       return Ok(new { Message = "Login successful", ReturnUrl = returnUrl });
   }

   [HttpPost("logout")]
   [Authorize] // Requiere autenticación para cerrar sesión
   public async Task<IActionResult> Logout()
   {
       await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
       return RedirectToAction("Login", "Account"); // Redirigir a la página de login tras cerrar sesión
   }
}

// ViewModel de ejemplo para el login
public class LoginViewModel
{
   public string Username { get; set; }
   public string Password { get; set; }
   public bool RememberMe { get; set; }
}

// Modelo de usuario de ejemplo
public class User
{
   public string Username { get; set; }
   public string Role { get; set; }
   // Otros datos del usuario
}
   

Protección de Rutas con Atributos

  • [Authorize]: Aplica este atributo a nivel de controlador o acción para restringir el acceso solo a usuarios autenticados. Si un usuario no autenticado intenta acceder a un recurso protegido, será redirigido a la ruta especificada en options.LoginPath.
  • [AllowAnonymous]: Permite el acceso anónimo a una acción específica, incluso si el atributo [Authorize] está aplicado a nivel de controlador. Esto es útil para páginas de inicio de sesión, registro, etc.

Flujo de Autenticación

Tras un inicio de sesión exitoso, el servidor emite una cookie de autenticación cifrada. En las solicitudes posteriores, el navegador incluirá esta cookie, permitiendo al servidor identificar al usuario autenticado sin necesidad de que vuelva a ingresar sus credenciales. Si se intenta acceder a un recurso protegido por [Authorize] y el usuario no está autenticado, el flujo de autenticación lo redirigirá automáticamente a la página de inicio de sesión definida, usualmente incluyendo un parámetro returnUrl para redirigir de vuelta a la página solicitada originalmente tras el éxito del login.

Etiquetas: ASP.NET Core autenticación Cookies seguridad MVC

Publicado el 6-14 01:32