Refactoring - Bonne version améliorée
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.lions.dev.service;
|
||||
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.util.UserRoles;
|
||||
import io.smallrye.jwt.build.Jwt;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
@@ -9,13 +10,24 @@ import org.jboss.logging.Logger;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Service d'émission de JWT au login.
|
||||
* Le token contient sub (userId), groups (rôle) et est signé avec la clé secrète configurée.
|
||||
* La validation des tokens sur les requêtes est assurée par quarkus-smallrye-jwt
|
||||
*
|
||||
* Le token contient :
|
||||
* - sub (subject) : userId de l'utilisateur
|
||||
* - groups : rôles de l'utilisateur (pour @RolesAllowed)
|
||||
* - iss (issuer) : "afterwork"
|
||||
* - iat (issued at) : timestamp de création
|
||||
* - exp (expiration) : timestamp d'expiration
|
||||
*
|
||||
* La validation des tokens est assurée automatiquement par SmallRye JWT
|
||||
* lorsque les endpoints sont protégés avec @RolesAllowed.
|
||||
*
|
||||
* @since 2.0 - Implémentation sécurité JWT production-ready
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class JwtService {
|
||||
@@ -26,6 +38,9 @@ public class JwtService {
|
||||
@ConfigProperty(name = "afterwork.jwt.secret", defaultValue = "afterwork-jwt-secret-min-32-bytes-for-hs256!")
|
||||
String secret;
|
||||
|
||||
@ConfigProperty(name = "smallrye.jwt.new-token.lifespan", defaultValue = "86400")
|
||||
long tokenLifespanSeconds;
|
||||
|
||||
/**
|
||||
* Génère un JWT pour l'utilisateur authentifié.
|
||||
*
|
||||
@@ -36,18 +51,69 @@ public class JwtService {
|
||||
if (user == null || user.getId() == null) {
|
||||
throw new IllegalArgumentException("User et id obligatoires pour générer le JWT");
|
||||
}
|
||||
Set<String> groups = Set.of("user", user.getRole() != null ? user.getRole() : "USER");
|
||||
|
||||
// Construire les groupes (rôles) pour @RolesAllowed
|
||||
Set<String> groups = buildGroups(user);
|
||||
|
||||
SecretKey key = secretKeyFromConfig();
|
||||
|
||||
String token = Jwt.claims()
|
||||
.issuer(ISSUER)
|
||||
.subject(user.getId().toString())
|
||||
.groups(groups)
|
||||
.issuedAt(java.time.Instant.now())
|
||||
.expiresIn(Duration.ofSeconds(tokenLifespanSeconds))
|
||||
.jws()
|
||||
.algorithm(io.smallrye.jwt.algorithm.SignatureAlgorithm.HS256)
|
||||
.sign(key);
|
||||
LOG.debug("JWT généré pour l'utilisateur " + user.getId());
|
||||
|
||||
LOG.info("JWT généré pour l'utilisateur " + user.getId() + " avec rôles: " + groups);
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construit l'ensemble des groupes (rôles) pour le token JWT.
|
||||
* Inclut le rôle principal et les rôles implicites selon la hiérarchie.
|
||||
*
|
||||
* Hiérarchie : SUPER_ADMIN > ADMIN > MANAGER > USER
|
||||
*
|
||||
* @param user L'utilisateur
|
||||
* @return Set des groupes à inclure dans le token
|
||||
*/
|
||||
private Set<String> buildGroups(Users user) {
|
||||
Set<String> groups = new HashSet<>();
|
||||
String role = user.getRole() != null ? user.getRole().toUpperCase() : UserRoles.USER;
|
||||
|
||||
// Ajouter le rôle principal
|
||||
groups.add(role);
|
||||
|
||||
// Ajouter les rôles implicites selon la hiérarchie
|
||||
switch (role) {
|
||||
case UserRoles.SUPER_ADMIN:
|
||||
groups.add(UserRoles.ADMIN);
|
||||
groups.add(UserRoles.MANAGER);
|
||||
groups.add(UserRoles.USER);
|
||||
break;
|
||||
case UserRoles.ADMIN:
|
||||
groups.add(UserRoles.MANAGER);
|
||||
groups.add(UserRoles.USER);
|
||||
break;
|
||||
case UserRoles.MANAGER:
|
||||
groups.add(UserRoles.USER);
|
||||
break;
|
||||
case UserRoles.USER:
|
||||
default:
|
||||
// USER n'a pas de rôles implicites supplémentaires
|
||||
break;
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée la clé secrète à partir de la configuration.
|
||||
* Assure que la clé fait au moins 32 bytes pour HS256.
|
||||
*/
|
||||
private SecretKey secretKeyFromConfig() {
|
||||
byte[] decoded = secret.getBytes(StandardCharsets.UTF_8);
|
||||
if (decoded.length < 32) {
|
||||
@@ -58,3 +124,4 @@ public class JwtService {
|
||||
return new SecretKeySpec(decoded, "HmacSHA256");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user