Sécurité & Authentification
🔑 JWT (JSON Web Token)
L'authentification est gérée via LexikJWTAuthenticationBundle. Les routes sont segmentées en deux zones via le firewall Symfony : une zone publique (catalogue, recherche) et une zone sécurisée (commandes, profil, administration).
Flux d'authentification
sequenceDiagram
participant C as Client
participant API as API Symfony
participant DB as PostgreSQL
C->>API: POST /api/v1/login_check<br/>{ email, password }
API->>DB: Vérifie les credentials (bcrypt)
DB-->>API: User entity
API-->>C: 200 OK { token: "eyJ..." }
Note over C,API: Requêtes authentifiées suivantes
C->>API: GET /api/v1/orders<br/>Authorization: Bearer eyJ...
API->>API: Vérifie la signature JWT<br/>et l'expiration du token
API-->>C: 200 OK + données JSON
Configuration des zones Firewall
| Zone | Pattern | Accès |
|---|---|---|
api_public |
/api/v1/products, /api/v1/categories |
Anonyme |
api_secured |
/api/v1/orders, /api/v1/admin/** |
Token JWT requis |
🛡️ Autorisations Granulaires (Voters)
La hiérarchie de rôles classique (ROLE_USER, ROLE_ADMIN) est insuffisante pour modéliser des règles métier complexes. Les Voters Symfony permettent d'exprimer ces règles directement en code, de manière explicite et testable.
Segmentation des acteurs
| Type d'acteur | Rôle Symfony | Périmètre d'accès |
|---|---|---|
CUSTOMER |
ROLE_CUSTOMER |
Tunnel de commande, ses propres commandes, ses avis |
INTERNAL |
ROLE_INTERNAL |
Consultation des stocks, gestion des expéditions |
ADMIN |
ROLE_ADMIN |
Accès total : catalogue, utilisateurs, transporteurs |
Exemple : OrderVoter
Un utilisateur authentifié ne peut accéder qu'à ses propres commandes. Le RoleHierarchy seul ne peut pas exprimer cette règle — c'est le rôle du Voter :
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
/** @var User $user */
$user = $token->getUser();
// Seul un profil CUSTOMER peut créer une commande
if ($attribute === self::CREATE) {
return in_array('ROLE_CUSTOMER', $user->getRoles());
}
// Un utilisateur ne peut consulter QUE ses propres commandes
if ($attribute === self::VIEW) {
return $subject->getCustomer()->getId() === $user->getId();
}
return false;
}
Avantage : La règle métier est co-localisée avec la ressource concernée (
OrderVoter↔Order). Elle est lisible, explicite et testable unitairement sans contexte HTTP.