Files
2026-09-11 14:55:41 +02:00

53 lines
2.5 KiB
C#

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using SIFinance.Shared.Entities;
namespace SIFinance.Api;
// Émet le jeton "maison" utilisé pour authentifier les appels à l'API après la
// connexion Entra ID (voir EntraAuthEndpoints.MapGet("/api/auth/callback")). Le
// claim "id" porte directement l'Id de la ligne core.utilisateurs — CurrentUserService
// n'a donc plus besoin d'accéder à la base pour résoudre l'utilisateur courant.
public class JwtTokenService(IOptions<JwtOptions> options)
{
public string GenerateToken(Utilisateur user, IEnumerable<string>? roles = null, bool estResponsable = false)
{
var opts = options.Value;
if (string.IsNullOrWhiteSpace(opts.Secret))
throw new InvalidOperationException("Configuration Jwt:Secret manquante — voir appsettings.Development.json.");
var claims = new List<Claim>
{
new("id", user.Id.ToString()),
new(ClaimTypes.Email, user.Email),
new("nom", user.Nom),
new("prenom", user.Prenom),
new("profil", user.Profil),
// true seulement si au moins un utilisateur a ce compte comme responsable_id —
// pilote l'affichage "Responsable" côté frontend (Layout.tsx).
new("estResponsable", estResponsable ? "true" : "false"),
};
// Sert à scoper les vues (ex. Pilotage) au service du collaborateur connecté —
// absent si l'utilisateur n'est rattaché à aucun service.
if (user.ServiceId.HasValue)
claims.Add(new Claim("serviceId", user.ServiceId.Value.ToString()));
// Un utilisateur peut cumuler plusieurs rôles métier (ex. DEMANDEUR + FINANCE) —
// "profil" reste la colonne historique à valeur unique, "roles" (claim répétée)
// porte la liste réelle depuis core.utilisateur_roles, utilisée pour le bascule
// d'espace de travail côté frontend.
foreach (var role in roles ?? [])
claims.Add(new Claim("roles", role));
var key = new SymmetricSecurityKey(Convert.FromBase64String(opts.Secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.UtcNow.AddHours(opts.ExpiresHours <= 0 ? 8 : opts.ExpiresHours),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}