Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Installing and Configuring the JWT Bundle

Installing and Configuring the JWT Bundle

~15 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

lexik/jwt-authentication-bundle is the API-Platform-typical path to JWT authentication – IN CONTRAST to the session-based authentication of the Symfony course (SENSIBLE there for a server-rendered frontend, UNSUITABLE here for a stateless API).

Installing the bundle

docker compose exec php composer require lexik/jwt-authentication-bundle

The api-platform distribution usually comes with this bundle ALREADY pre-installed – if NOT, the command installs it AFTERWARD.

Generating keys

docker compose exec php bin/console lexik:jwt:generate-keypair

Generates a PRIVATE/PUBLIC key pair under config/jwt/ – the PRIVATE key SIGNS issued tokens, the PUBLIC key VERIFIES them on every request.

Achtung: config/jwt/private.pem must NEVER go into version control – the api-platform distribution already excludes config/jwt/ in .gitignore by default.

Automating password hashing

api/src/State/UserPasswordHasherProcessor.php
<?php

declare(strict_types=1);

namespace App\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\User;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

final class UserPasswordHasherProcessor implements ProcessorInterface
{
    public function __construct(
        private readonly ProcessorInterface $persistProcessor,
        private readonly UserPasswordHasherInterface $passwordHasher,
    ) {
    }

    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
    {
        if ($data instanceof User && null !== $data->getPlainPassword()) {
            $data->setPassword(
                $this->passwordHasher->hashPassword($data, $data->getPlainPassword())
            );
            $data->setPlainPassword(null);
        }

        return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
    }
}

A STATE PROCESSOR (the WRITE counterpart to the state provider from chapter 5/27) – brought forward HERE as a PRACTICAL example, a COMPLETE explanation of the concept follows in block 7 (chapter 61).

// User.php
use App\State\UserPasswordHasherProcessor;

#[ApiResource(
    normalizationContext: ['groups' => ['user:read']],
    denormalizationContext: ['groups' => ['user:write']],
    processor: UserPasswordHasherProcessor::class
)]

Tipp: $this->persistProcessor gets injected AUTOMATICALLY by API Platform with the DEFAULT Doctrine processor (dependency injection via autowiring, recognized via the interface) – the CUSTOM processor only WRAPS it, instead of REPLACING it.