167 lines
5.9 KiB
C#
167 lines
5.9 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
using System.Security.Cryptography;
|
|
using ldap_cesi.Context;
|
|
using ldap_cesi.Entities;
|
|
using ldap_cesi.Services.Interfaces;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
namespace ldap_cesi.Services;
|
|
|
|
public class JwtService : IJwtService
|
|
{
|
|
private readonly IRsaKeyService _rsaKeyService;
|
|
private readonly IConfiguration _configuration;
|
|
private readonly PgContext _context;
|
|
private readonly ILogger<JwtService> _logger;
|
|
|
|
public JwtService(
|
|
IConfiguration configuration,
|
|
PgContext context,
|
|
IRsaKeyService rsaKeyService,
|
|
ILogger<JwtService> logger)
|
|
{
|
|
_configuration = configuration;
|
|
_context = context;
|
|
_rsaKeyService = rsaKeyService;
|
|
_logger = logger;
|
|
}
|
|
|
|
public string GenerateToken(Utilisateur utilisateur)
|
|
{
|
|
try
|
|
{
|
|
var claims = new[]
|
|
{
|
|
new Claim(JwtRegisteredClaimNames.Sub, utilisateur.Email),
|
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
|
new Claim(ClaimTypes.Name, utilisateur.Nom),
|
|
new Claim(ClaimTypes.Role, utilisateur.IdRoleNavigation.Nom),
|
|
new Claim(ClaimTypes.NameIdentifier, utilisateur.Id.ToString())
|
|
};
|
|
|
|
var key = new RsaSecurityKey(_rsaKeyService.GetRsaKey());
|
|
var creds = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
|
|
|
|
var tokenExpiryMinutes = _configuration.GetValue<int>("Jwt:TokenExpiryMinutes", 30);
|
|
var token = new JwtSecurityToken(
|
|
issuer: _configuration["Jwt:Issuer"],
|
|
audience: _configuration["Jwt:Audience"],
|
|
claims: claims,
|
|
expires: DateTime.UtcNow.AddMinutes(tokenExpiryMinutes),
|
|
signingCredentials: creds);
|
|
|
|
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
|
|
utilisateur.AccessToken = tokenString;
|
|
_context.Utilisateurs.Update(utilisateur);
|
|
_context.SaveChanges();
|
|
|
|
return tokenString;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Une erreur s'est produitel lors de la génération du token.");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public string GetPublicKey()
|
|
{
|
|
try
|
|
{
|
|
var publicKey = _rsaKeyService.GetRsaKey().ExportSubjectPublicKeyInfo();
|
|
return Convert.ToBase64String(publicKey);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Une erreur s'est produite pendant la récupération de la clé.");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// Ajouter cette méthode à votre JwtService.cs
|
|
public async Task<bool> InvalidateToken(string token)
|
|
{
|
|
try
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
|
|
// récupération du token
|
|
var jwtToken = tokenHandler.ReadJwtToken(token);
|
|
|
|
// identifiant de l'utilisateur
|
|
var userIdClaim = jwtToken.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
|
|
|
|
if (userIdClaim == null || !int.TryParse(userIdClaim.Value, out var userId))
|
|
{
|
|
_logger.LogWarning("Erreur d'invalidation du token : Id utilisateur non trouvé ou invalide.");
|
|
return false;
|
|
}
|
|
|
|
var utilisateur = await _context.Utilisateurs.FindAsync(userId);
|
|
if (utilisateur == null)
|
|
{
|
|
_logger.LogWarning("Erreur d'invalidation du token : Utilisateur non trouvé.");
|
|
return false;
|
|
}
|
|
|
|
// delte le token stocké
|
|
utilisateur.AccessToken = null;
|
|
_context.Utilisateurs.Update(utilisateur);
|
|
await _context.SaveChangesAsync();
|
|
|
|
_logger.LogInformation($"Token invalidé pour l'utilisateur {userId}.");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Une erreur s'est produite pendant l'invalidation du token JWT.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> ValidateToken(string token, int userId)
|
|
{
|
|
try
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var validationParameters = new TokenValidationParameters
|
|
{
|
|
ValidateIssuerSigningKey = true,
|
|
IssuerSigningKey = new RsaSecurityKey(_rsaKeyService.GetRsaKey()),
|
|
ValidateIssuer = true,
|
|
ValidateAudience = true,
|
|
ValidIssuer = _configuration["Jwt:Issuer"],
|
|
ValidAudience = _configuration["Jwt:Audience"],
|
|
ClockSkew = TimeSpan.Zero,
|
|
ValidateLifetime = true
|
|
};
|
|
|
|
var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
|
|
var nameIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier);
|
|
if (nameIdClaim == null || !int.TryParse(nameIdClaim.Value, out var tokenUserId) || tokenUserId != userId)
|
|
{
|
|
_logger.LogWarning("Erreur de validation : Id utilisateur invalide.");
|
|
return false;
|
|
}
|
|
|
|
var utilisateur = await _context.Utilisateurs.FindAsync(userId);
|
|
if (utilisateur == null)
|
|
{
|
|
_logger.LogWarning("Erreur de validation : Utilisateur non trouvé.");
|
|
return false;
|
|
}
|
|
|
|
utilisateur.AccessToken = token;
|
|
_context.Utilisateurs.Update(utilisateur);
|
|
await _context.SaveChangesAsync();
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Une erreur s'est produite lors pendant la validation du token JWT.");
|
|
return false;
|
|
}
|
|
}
|
|
} |