Backend JWT Authentication
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The Backend JWT Authentication system provides a secure mechanism for managing user sessions and resource access within the application. By leveraging JSON Web Tokens (JWT), the system ensures that stateless communication between the client and the server remains authenticated and tamper-proof.
The implementation encompasses the generation of tokens upon successful login, the validation of these tokens during incoming requests, and the management of user session persistence. This system integrates directly with the application's middleware and dependency injection container to provide a robust security layer across all API endpoints.
Authentication Architecture
The system follows a standard provider pattern where specialized services handle token generation, user validation, and session persistence. The central configuration resides in the application startup, where JWT bearer authentication is registered and configured.
Core Components
| Component | Description |
|---|---|
JwtTokenServicio | Responsible for creating, parsing, and validating JWT strings using a symmetric security key. |
InicioSesionController | The API entry point for authentication requests, handling the /login route. |
UsuarioSesionServicio | Manages the database-level session records and validates user credentials against stored hashes. |
Program.cs | Configures the authentication middleware and defines validation parameters like lifetime and issuer keys. |
Sources: Back/Alumnos/Api/Program.cs:59-101, Back/Alumnos/Api/Servicios/JwtTokenServicio.cs:9-11
Authentication Flow
The following sequence diagram illustrates the process from user login to token issuance and subsequent authorized requests.
Token Generation and Structure
Tokens are generated using the JwtTokenServicio class. The tokens include specific claims that identify the session's characteristics and security state.
Token Claims
The system embeds the following claims into the JWT payload:
- IsPersistent: Boolean indicating if the session should survive browser restarts.
- SerialNumber: A security stamp (
EstampaSeguridad) used to invalidate tokens globally if the secret changes. - FechaTicks: A timestamp in ticks used for granular expiration checks.
var tokenDescriptor = new SecurityTokenDescriptor
{
Expires = reclamos.EsPersistente
? DateTime.MaxValue
: DateTime.UtcNow.AddDays(1),
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.IsPersistent, reclamos.EsPersistente.ToString()),
new Claim(ClaimTypes.SerialNumber, reclamos.EstampaSeguridad),
new Claim(nameof(ReclamosTokenIdentidad.FechaTicks), reclamos.FechaTicks.ToString()),
}),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(llave),
SecurityAlgorithms.HmacSha256Signature)
};
Sources: Back/Alumnos/Api/Servicios/JwtTokenServicio.cs:25-39
Server-Side Validation Logic
Validation occurs at two levels: the standard JWT middleware validation and a custom logic implementation within JwtBearerEvents.
Middleware Configuration
The backend is configured to validate the issuer signing key, the lifetime of the token, and requires no clock skew for immediate expiration.
| Parameter | Configuration |
|---|---|
ValidateIssuerSigningKey | True |
ValidateIssuer | False |
ValidateAudience | False |
ValidateLifetime | True |
ClockSkew | TimeSpan.Zero |
Sources: Back/Alumnos/Api/Program.cs:68-78
Custom Validation Event
Upon token validation, the system executes an OnTokenValidated event. This event retrieves the ITokenIdentidadServicio to perform a secondary check on the security stamp and expiration ticks.
opt.Events = new JwtBearerEvents
{
OnTokenValidated = async (contexto) =>
{
var tokenIdentidadServicio = contexto.HttpContext.RequestServices
.GetRequiredService<ITokenIdentidadServicio>();
var tokenJwt = contexto.SecurityToken as JwtSecurityToken;
var reclamos = tokenIdentidadServicio.ObtenerReclamos(tokenJwt.Claims);
var tokenValido = await tokenIdentidadServicio.ValidarAsync(reclamos);
if (tokenValido == false)
{
contexto.Fail("Token expirado/invlido.");
}
}
};
Sources: Back/Alumnos/Api/Program.cs:79-98
Frontend Integration
The client-side implementation manages the lifecycle of the JWT by storing it in localStorage and attaching it to every outgoing request via an Axios interceptor.
Token Storage and Interception
The api.ts service handles the persistent storage of the token and ensures it is included in the Authorization header using the Bearer scheme.
// Interceptor to handle tokens
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
Sources: Front/src/services/api.ts:39-45
Response Handling
When the server sends a token (usually during login or token refresh), the frontend extracts it from the response headers and updates the local storage.
const handleResponse = async <T>(response: Response): Promise<T> => {
// ... check response.ok
const token = response.headers.get('Authorization');
if (token) {
localStorage.setItem('token', token);
}
return response.json();
};
Sources: Front/src/services/api.ts:48-57
Security Configuration
The application settings defined in Program.cs establish the security boundaries for the API.
Summary
The Backend JWT Authentication module implements a secure, stateless authentication layer. It coordinates token generation through JwtTokenServicio, session tracking via UsuarioSesionServicio, and middleware enforcement in Program.cs. By utilizing custom claims and tick-based expiration, the system provides precise control over session validity, complemented by automated token management in the React frontend.