Apiplatform Keycloak Lexik
Pour intégrer API Platform 4 avec Keycloak 26 en utilisant OpenID Connect (OIDC), vous devez configurer l’authentification JWT et sécuriser vos routes API. Voici un guide détaillé pour configurer l’ensemble :
1. Prérequis
- API Platform 4 : Déjà installé et configuré.
- Keycloak 26 : Un fournisseur OIDC configuré avec un client pour votre application.
- LexikJWTAuthenticationBundle : Pour gérer les JWT dans Symfony.
2. Installation des dépendances
Installez les packages nécessaires via Composer :
composer require web-token/jwt-framework
composer require lexik/jwt-authentication-bundle
composer require league/oauth2-client
3. Configuration de LexikJWTAuthenticationBundle
a. Configurer les clés JWT
Générez les clés privée et publique pour signer les JWT :
mkdir -p config/jwt
openssl genpkey -out config/jwt/private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096
openssl pkey -in config/jwt/private.pem -out config/jwt/public.pem -pubout
Ajoutez les variables d’environnement dans .env
:
###> lexik/jwt-authentication-bundle ### JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem JWT_PASSPHRASE=your_passphrase ###< lexik/jwt-authentication-bundle ###
b. Configurer lexik_jwt_authentication.yaml
Ajoutez la configuration suivante dans config/packages/lexik_jwt_authentication.yaml
:
lexik_jwt_authentication:
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
pass_phrase: '%env(JWT_PASSPHRASE)%'
token_ttl: 3600 # Durée de validité du token (en secondes)
4. Configuration de Keycloak
a. Configurer Keycloak
- Créez un client dans Keycloak.
- Notez les informations suivantes :
- Client ID : Identifiant du client.
- Client Secret : Clé secrète du client.
- Issuer URL : URL du fournisseur (par exemple,
https://keycloak.example.com/auth/realms/{realm}
). - Authorization URL : URL d’autorisation.
- Token URL : URL pour obtenir les tokens.
- Userinfo URL : URL pour récupérer les informations de l’utilisateur.
b. Configurer Symfony
Ajoutez les informations du fournisseur dans votre fichier .env
:
###> OIDC Configuration ### OIDC_CLIENT_ID=your-client-id OIDC_CLIENT_SECRET=your-client-secret OIDC_ISSUER=https://keycloak.example.com/auth/realms/{realm} OIDC_AUTHORIZATION_URL=https://keycloak.example.com/auth/realms/{realm}/protocol/openid-connect/auth OIDC_TOKEN_URL=https://keycloak.example.com/auth/realms/{realm}/protocol/openid-connect/token OIDC_USERINFO_URL=https://keycloak.example.com/auth/realms/{realm}/protocol/openid-connect/userinfo ###< OIDC Configuration ###
5. Configurer le composant Security
Dans config/packages/security.yaml
, configurez le pare-feu pour utiliser JWT et OIDC.
security:
enable_authenticator_manager: true
providers:
jwt_provider:
lexik_jwt: ~
firewalls:
api:
pattern: ^/api
stateless: true
jwt: ~
access_control:
- { path: ^/api/login, roles: PUBLIC_ACCESS }
- { path: ^/api, roles: ROLE_USER }
6. Créer un contrôleur d’authentification
Créez un contrôleur pour gérer la connexion via OIDC et la génération des tokens JWT.
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\OidcService;
class AuthController extends AbstractController
{
#[Route('/api/login', name: 'api_login', methods: ['POST'])]
public function login(OidcService $oidcService): JsonResponse
{
$accessToken = $oidcService->getAccessToken($_POST['code']);
$userInfo = $oidcService->getUserInfo($accessToken);
// Authentifiez l'utilisateur avec les informations de $userInfo
// ...
// Générer un token JWT
$jwtToken = $this->getToken($userInfo);
return $this->json([
'user' => $userInfo['email'],
'token' => $jwtToken,
]);
}
private function getToken(array $userInfo): string
{
return $this->container->get('lexik_jwt_authentication.encoder')
->encode(['username' => $userInfo['email']]);
}
}
7. Configurer API Platform
a. Sécuriser les routes API
Dans config/packages/api_platform.yaml
, assurez-vous que les routes API sont sécurisées :
api_platform:
mapping:
paths: ['%kernel.project_dir%/src/Entity']
patch_formats:
json: ['application/merge-patch+json']
swagger:
versions: [3]
formats:
jsonld:
mime_types: ['application/ld+json']
json:
mime_types: ['application/json']
b. Ajouter des contrôles d’accès
Utilisez les annotations ou attributs pour restreindre l’accès aux ressources :
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Security\Core\User\UserInterface;
#[ApiResource(
collectionOperations: [
'get' => ['security' => "is_granted('ROLE_USER')"],
'post' => ['security' => "is_granted('ROLE_ADMIN')"],
],
itemOperations: [
'get' => ['security' => "is_granted('ROLE_USER')"],
'put' => ['security' => "is_granted('ROLE_ADMIN')"],
'delete' => ['security' => "is_granted('ROLE_ADMIN')"],
],
)]
class Product
{
// ...
}
8. Valider les tokens JWT
Utilisez Web-Token/JWT-Framework pour valider les tokens JWT reçus.
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\RS256;
use Jose\Component\Signature\JWSVerifier;
class TokenValidator
{
private $jwsVerifier;
public function __construct()
{
$algorithmManager = new AlgorithmManager([new RS256()]);
$this->jwsVerifier = new JWSVerifier($algorithmManager);
}
public function validateToken(string $token, JWK $jwk): bool
{
return $this->jwsVerifier->verifyWithKey($token, $jwk, 0);
}
}
9. Documentation supplémentaire
Voir Apiplatform TokenValidator Lexik
source:DeepSeek