Login / Logout

Login

Pour vérifier que nous somme bien identifié nous rajoutons dans notre entité User la condition is_granted('ROLE_USER') à l'opération GET collection d'utilisateurs.

 *       collectionOperations={
 *           "get"={
 *               "security"="is_granted('ROLE_USER')",
 *           },

Ainsi quand on fait une requete GET /users nous avons la réponse 401 suivante :

{
    "@context": "/api/contexts/Error",
    "@type": "hydra:Error",
    "hydra:title": "An error occurred",
    "hydra:description": "Full authentication is required to access this resource.",
// ...

Nous allons également déclarer une nouvelle route sur notre entité User qui nous permettra de nous identifier :

 *            "login"={
 *                "method"="POST",
 *                "path"="/login",
 *                "controller"=LoginAction::class
 *           },

LoginAction.php

<?php

namespace App\Security;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class LoginAction extends AbstractController
{
    public function __invoke(Request $request)
    {
        if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
            return $this->json([
                'error' => 'Invalid login request: check that the Content-Type header is "application/json".'
            ], Response::HTTP_BAD_REQUEST);
        }

        return $this->json($this->getUser());
    }
}

Nous avons besoin de connaitre le nom de cette route pour l'indiquer dans notre firewall. Pour ça nous utilisons la commande php bin/console debug:router qui nous liste toutes les routes et nous avons le nom que nous cherchons affiché :

debug router find login route

Dans config/packages/security.yaml nous pouvons indiquer un nouveau firewall et la route est api_users_login_collection.

security:
    encoders:
        App\Entity\User:
            algorithm: auto

    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: true

            json_login:
                check_path: api_users_login_collection
                username_path: email
                password_path: password

Maintenant, nous pouvons faire un POST /api/login

{
    "email": "Immanuel_Bradtke7@yahoo.com",
    "password": "P@sswordS3cure"
}

et nous avons comme réponse

{
    "id": 12,
    "email": "Immanuel_Bradtke7@yahoo.com",
    "roles": [
        "ROLE_USER"
    ]
}

Qui nous indique que nous nous sommes bien identifiés. Dans le cas contraire (avec un mauvais mot de passe par exemple) nous avons :

{
    "error": "Invalid credentials."
}

Maintenant si nous refaisons un GET /api/users nous avons une réponse 200 qui nous liste les utilisateurs.

Avec cette configuration, lorsque nous envoyons une requête POST /api/login, l'authentificateur json_login va automatiquement se mettre en route, chercher du JSON dans la requête, le décoder, et utiliser les clés email et mot de passe qu'il contient pour nous connecter.

Avec le provider app_user_provider cela indique au système de sécurité que notre utilisateur est dans Doctrine et qu'il doit le rechercher via la propriété email.

Logout

Nous allons créer une nouvelle route pour se déconnecter. Dans notre entité User nous la rajoutons :

 *           "logout"={
 *               "method"="POST",
 *               "path"="/logout",
 *               "controller"=LogoutAction::class,
 *           },

Le contenu de LogoutAction est le suivant

<?php

namespace App\Security;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class LogoutAction extends AbstractController
{
    public function __invoke()
    {
        throw new \Exception('should not be reached');
    }
}
logout route name

Maintenant, en faisant un POST /api/logout puis à nouveau un GET /api/users/ vous verrez que vous aurez à nouveau le message Full authentication is required to access this resource.

prev next

Commentaires

Connectez-vous pour laisser un commentaire