« JWT SPA symfony exercice pratique » : différence entre les versions

Aucun résumé des modifications
Aucun résumé des modifications
Ligne 61 : Ligne 61 :
Depuis la version 0.7.0, le bundle de jetons d'actualisation contient une nouvelle option single_use qui supprime un jeton d'actualisation après utilisation et en émet un nouveau. Cela signifie qu'une fois qu'un attaquant vole un jeton d'actualisation, il n'a que jusqu'à la prochaine utilisation de l'utilisateur pour utiliser le jeton d'actualisation. Après c'est déjà inutile. Alors activons cela dans le fichier gesdinet_jwt_refresh_token.yml.
Depuis la version 0.7.0, le bundle de jetons d'actualisation contient une nouvelle option single_use qui supprime un jeton d'actualisation après utilisation et en émet un nouveau. Cela signifie qu'une fois qu'un attaquant vole un jeton d'actualisation, il n'a que jusqu'à la prochaine utilisation de l'utilisateur pour utiliser le jeton d'actualisation. Après c'est déjà inutile. Alors activons cela dans le fichier gesdinet_jwt_refresh_token.yml.


gesdinet_jwt_refresh_token.yaml
==== gesdinet_jwt_refresh_token.yaml ====
<pre>
<pre>
gesdinet_jwt_refresh_token:
gesdinet_jwt_refresh_token:
Ligne 74 : Ligne 74 :
Pour cela, nous ajoutons un gestionnaire de déconnexion personnalisé à notre pare-feu qui est généralement appelé api dans mes applications. Cela signifie que j'utilise la fonctionnalité de déconnexion par défaut de Symfony, mais en étendant la gestion.
Pour cela, nous ajoutons un gestionnaire de déconnexion personnalisé à notre pare-feu qui est généralement appelé api dans mes applications. Cela signifie que j'utilise la fonctionnalité de déconnexion par défaut de Symfony, mais en étendant la gestion.


security.yaml
==== security.yaml ====
<pre>
<pre>
security:
security:
Ligne 87 : Ligne 87 :
Dans le gestionnaire, nous injectons simplement la connexion à la base de données et supprimons les jetons. Le référentiel du bundle ne prend pas en charge la suppression de tous les jetons d'actualisation pour un utilisateur, mais vous pouvez également étendre l'implémentation RefreshTokenManager, ajouter une méthode de référentiel et l'injecter ici à la place.
Dans le gestionnaire, nous injectons simplement la connexion à la base de données et supprimons les jetons. Le référentiel du bundle ne prend pas en charge la suppression de tous les jetons d'actualisation pour un utilisateur, mais vous pouvez également étendre l'implémentation RefreshTokenManager, ajouter une méthode de référentiel et l'injecter ici à la place.


LogoutHandler
==== LogoutHandler ====
<pre>
<pre>
     <?php
     <?php
Ligne 131 : Ligne 131 :
Et la meilleure chose: nous pouvons créer le cookie au-dessus du jeton d'actualisation de l'utilisateur. Cela signifie que chaque fois que le jeton d'actualisation est supprimé, le cookie est également invalidé.
Et la meilleure chose: nous pouvons créer le cookie au-dessus du jeton d'actualisation de l'utilisateur. Cela signifie que chaque fois que le jeton d'actualisation est supprimé, le cookie est également invalidé.


*Configuration des cookies :
==== Configuration des cookies ====


La valeur doit être basée sur l'utilisateur, le jeton d'actualisation valide actuel et un sel aléatoire. De cette façon, il ne dépend toujours pas de la session du serveur mais des valeurs de la base de données. Nous aurions également la possibilité de forcer une déconnexion globale en modifiant le sel utilisé sur le serveur. Une petite méthode pour cela pourrait ressembler à ceci:
La valeur doit être basée sur l'utilisateur, le jeton d'actualisation valide actuel et un sel aléatoire. De cette façon, il ne dépend toujours pas de la session du serveur mais des valeurs de la base de données. Nous aurions également la possibilité de forcer une déconnexion globale en modifiant le sel utilisé sur le serveur. Une petite méthode pour cela pourrait ressembler à ceci:


generateSecurityCookieHash
==== generateSecurityCookieHash ====
<pre>
<pre>
     private function generateSecurityCookieHash(User $user, RefreshTokenInterface $refreshToken): string
     private function generateSecurityCookieHash(User $user, RefreshTokenInterface $refreshToken): string
Ligne 149 : Ligne 149 :
Dans celui-ci, nous créerons le cookie en fonction du jeton d'actualisation de l'utilisateur authentifié. Le service complet ressemblera à ceci:
Dans celui-ci, nous créerons le cookie en fonction du jeton d'actualisation de l'utilisateur authentifié. Le service complet ressemblera à ceci:


AuthenticationService
==== AuthenticationService ====
<pre>
<pre>
     <?php
     <?php
Ligne 231 : Ligne 231 :
Pour définir le cookie, nous ajoutons un gestionnaire de réussite de connexion et utilisons notre service d'authentification là-bas:
Pour définir le cookie, nous ajoutons un gestionnaire de réussite de connexion et utilisons notre service d'authentification là-bas:


security.yaml
==== security.yaml ====
<pre>
<pre>
security:
security:
Ligne 242 : Ligne 242 :
</pre>
</pre>


LoginSuccessHandler
==== LoginSuccessHandler ====
<pre>   
<pre>   
     <?php
     <?php
Ligne 294 : Ligne 294 :
Nous allons maintenant obtenir un cookie de sécurité que nous vous enverrons à chaque demande et qui n'est pas accessible par Javascript. Mais ce n'est pas évalué pour le moment, alors faisons-le.
Nous allons maintenant obtenir un cookie de sécurité que nous vous enverrons à chaque demande et qui n'est pas accessible par Javascript. Mais ce n'est pas évalué pour le moment, alors faisons-le.


*Validez le cookie à chaque demande :
==== Validez le cookie à chaque demande ====


Vient maintenant la partie qui ne me satisfait toujours pas, car je n'ai pas trouvé de bon point d'entrée. Le garde utilisé lors de l'utilisation du bundle JWT est le JWTTokenAuthenticator. Le moyen le plus simple d'attacher le cookie serait d'écouter la réponse, mais malheureusement, il n'y a aucun moyen d'y parvenir. Et dans tous les cas où j'ai accès à l'utilisateur, nous n'avons pas accès à la réponse. Donc, le seul moyen que j'ai trouvé était de créer mon propre authentificateur, d'étendre le JWTTokenAuthenticator, d'utiliser la même méthode onAuthenticationSuccess et d'appeler la méthode parente pour avoir le même comportement qu'avant juste avec la vérification des cookies ajoutée. L'authentificateur complet sera configuré comme authentificateur dans le fichier security.yml et ressemble à ceci.
Vient maintenant la partie qui ne me satisfait toujours pas, car je n'ai pas trouvé de bon point d'entrée. Le garde utilisé lors de l'utilisation du bundle JWT est le JWTTokenAuthenticator. Le moyen le plus simple d'attacher le cookie serait d'écouter la réponse, mais malheureusement, il n'y a aucun moyen d'y parvenir. Et dans tous les cas où j'ai accès à l'utilisateur, nous n'avons pas accès à la réponse. Donc, le seul moyen que j'ai trouvé était de créer mon propre authentificateur, d'étendre le JWTTokenAuthenticator, d'utiliser la même méthode onAuthenticationSuccess et d'appeler la méthode parente pour avoir le même comportement qu'avant juste avec la vérification des cookies ajoutée. L'authentificateur complet sera configuré comme authentificateur dans le fichier security.yml et ressemble à ceci.


security.yaml
==== security.yaml ====
<pre>
<pre>
security:
security:
Ligne 311 : Ligne 311 :
</pre>
</pre>


JWTAndSecurityCookieAuthenticator
==== JWTAndSecurityCookieAuthenticator ====
<pre>     
<pre>     
     <?php
     <?php
Ligne 373 : Ligne 373 :
Nous avons un problème similaire à celui du bundle JWT en ce sens qu'il y a des événements que nous pourrions écouter, mais jamais ceux avec un accès à la demande et à la réponse en même temps. Par conséquent, la seule solution que j'ai trouvée était de copier le service de jeton d'actualisation utilisé comme point de terminaison pour l'itinéraire de jeton d'actualisation et de l'étendre. Signification au lieu de cette route qui est la valeur par défaut:
Nous avons un problème similaire à celui du bundle JWT en ce sens qu'il y a des événements que nous pourrions écouter, mais jamais ceux avec un accès à la demande et à la réponse en même temps. Par conséquent, la seule solution que j'ai trouvée était de copier le service de jeton d'actualisation utilisé comme point de terminaison pour l'itinéraire de jeton d'actualisation et de l'étendre. Signification au lieu de cette route qui est la valeur par défaut:


routes.yaml
==== routes.yaml ====
<pre>
<pre>
api_refresh_token:
api_refresh_token:
Ligne 381 : Ligne 381 :
</pre>
</pre>


*Nous utilisons le suivant :
==== Nous utilisons le suivant ====


routes.yaml
==== routes.yaml ====
</pre>
</pre>
api_refresh_token:
api_refresh_token:
Ligne 393 : Ligne 393 :
La copie complète est annotée avec les espaces où je place la validation du cookie et la création du cookie après l'ajout du nouveau jeton d'actualisation.
La copie complète est annotée avec les espaces où je place la validation du cookie et la création du cookie après l'ajout du nouveau jeton d'actualisation.


RefreshTokenSecurityCookieService
==== RefreshTokenSecurityCookieService ====
<pre>
<pre>
     <?php
     <?php