Configuración y Validación de Tokens JWT en ASP.NET Core

Instalación de dependencias

Para habilitar la autenticación basada en JSON Web Tokens (JWT) en un proyecto de ASP.NET Core, es necesario incorporar los paquetes NuGet adecuados. Ejecute los siguientes comandos en la consola del administrador de paquetes:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt

Modelo de configuración

Defina una clase POCO para mapear los parámetros de seguridad desde el archivo de configuración de la aplicación. Esto permite centralizar y gestionar fácilmente las credenciales del token.

public class JwtConfiguration
{
    public string Issuer { get; set; }
    public string Audience { get; set; }
    public string Secret { get; set; }
}

Configuración del entorno

Añada la sección correspondiente en el archivo appsettings.json. Asegúrese de que la clave secreta tenga una longitud suficiente (mínimo 32 caracteres para algoritmos HMAC SHA256) para evitar excepciones en tiempo de ejecución.

{
  "JwtConfig": {
    "Issuer": "BackendApiServer",
    "Audience": "FrontendClientApp",
    "Secret": "EstaEsUnaClaveSecretaMuySeguraYDebeSerLarga123!"
  }
}

Registro de servicios de autenticación y autorización

En la clase Startup, configure el middlewrae de autenticación y defina las políticas de autorización basadas en claims.

public void ConfigureServices(IServiceCollection services)
{
    var jwtConfig = Configuration.GetSection("JwtConfig").Get<JwtConfiguration>();
    services.AddSingleton(jwtConfig);

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = jwtConfig.Issuer,
                ValidAudience = jwtConfig.Audience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.Secret)),
                ClockSkew = TimeSpan.Zero
            };
        });

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdministrator", policy => policy.RequireClaim("Role", "Admin"));
        options.AddPolicy("RequireStandardUser", policy => policy.RequireClaim("Role", "User"));
    });

    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Generación y validación de tokens en el controlador

Implemente un controlador que exponga un endponit público para la generación del token y endpoints protegidos que requieran validación mediante el atributo [Authorize].

[ApiController]
[Route("api/[controller]")]
public class SecurityController : ControllerBase
{
    private readonly JwtConfiguration _jwtConfig;

    public SecurityController(JwtConfiguration jwtConfig)
    {
        _jwtConfig = jwtConfig;
    }

    [HttpPost("authenticate")]
    public IActionResult Authenticate([FromBody] CredentialRequest credentials)
    {
        if (credentials.Username != "admin" || credentials.Password != "password123")
        {
            return Unauthorized(new { message = "Credenciales inválidas" });
        }

        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConfig.Secret));
        var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var claims = new List<Claim>
        {
            new Claim(JwtRegisteredClaimNames.Sub, credentials.Username),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            new Claim("Role", "Admin")
        };

        var securityToken = new JwtSecurityToken(
            issuer: _jwtConfig.Issuer,
            audience: _jwtConfig.Audience,
            claims: claims,
            expires: DateTime.UtcNow.AddHours(3),
            signingCredentials: signingCredentials);

        var tokenString = new JwtSecurityTokenHandler().WriteToken(securityToken);

        return Ok(new 
        { 
            token = tokenString, 
            expiration = securityToken.ValidTo 
        });
    }

    [Authorize(Policy = "RequireAdministrator")]
    [HttpGet("confidential-data")]
    public IActionResult GetConfidentialData()
    {
        var currentUser = User.FindFirst(JwtRegisteredClaimNames.Sub)?.Value;
        var userRole = User.FindFirst("Role")?.Value;

        return Ok(new 
        { 
            message = "Acceso a datos confidenciales concedido.", 
            user = currentUser, 
            role = userRole 
        });
    }
}

Etiquetas: asp-net-core JWT c-sharp Authentication Middleware

Publicado el 8-8 22:32