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 options) { public string GenerateToken(Utilisateur user, IEnumerable? 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 { 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); } }