inrae-umrh / iam-bundle
Bundle Symfony pour l'authentification OAuth2/OIDC avec le système IAM de l'INRAE
Package info
forge.inrae.fr/symfony_iam/iam-symfony-bundle
Type:symfony-bundle
pkg:composer/inrae-umrh/iam-bundle
Requires
- php: >=8.1
- doctrine/doctrine-bundle: ^2.0
- symfony/config: ^6.0|^7.0
- symfony/dependency-injection: ^6.0|^7.0
- symfony/filesystem: ^6.0|^7.0
- symfony/http-kernel: ^6.0|^7.0
- symfony/security-bundle: ^6.0|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.1
README
Bundle Symfony pour l'authentification OAuth2/OIDC avec le système IAM de l'INRAE.
Ce bundle fournit une intégration facile avec l'authentification INRAE tout en maintenant la rétrocompatibilité avec l'ancienne méthode d'utilisation.
Installation
composer require inrae-umrh/iam-bundle
Ou ajoutez le bundle à votre composer.json :
{
"require": {
"inrae-umrh/iam-bundle": "^1.0.0"
}
}
Installation automatique
Le bundle s'installe automatiquement lors de l'exécution de composer install ou composer update. Le script d'installation effectue les actions suivantes :
- ✓ Ajoute le bundle à
config/bundles.php - ✓ Crée le fichier
config/packages/inrae_iam.yaml - ✓ Ajoute les variables d'environnement au
.env
Vous n'avez aucune configuration manuelle à faire après l'installation du bundle.
Configuration
Le script d'installation a automatiquement créé le fichier config/packages/inrae_iam.yaml et ajouté les variables d'environnement à votre .env.
Il ne vous reste qu'à configurer les valeurs dans votre fichier .env :
AUTH_URL="https://authentification.inrae.fr/.well-known/openid-configuration"
CLIENT_ID="votre_client_id"
CLIENT_SECRET="votre_client_secret"
REDIRECT_URI="https://votre-domaine.com/login"
USER_INFO_ENDPOINT="https://authentification.inrae.fr/oauth2/userinfo"
Utilisation
Mode rétrocompatible (code existant)
Si vous utilisiez déjà l'ancienne méthode avec new Authenticator(...), votre code continue de fonctionner sans modification :
use InraeIamBundle\Authenticator;
$auth = new Authenticator(
$this->getParameter('app.authurl'),
$this->getParameter('app.clientid'),
$this->getParameter('app.clientsecret'),
$this->getParameter('app.redirecturi'),
);
if (isset($_GET['code'])) {
if ($auth->connexion() && $auth->isActive()) {
$tokenData = $auth->getToken();
$userDetails = $auth->getUserDetails();
// ... votre logique existante
}
} else {
$auth->redirect(['customScope']);
}
Mode moderne (injection de dépendances)
Utilisez l'injection de dépendances pour une intégration Symfony plus propre :
use InraeIamBundle\Authenticator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class LoginController extends AbstractController
{
#[Route('/login', name: 'login')]
public function login(Authenticator $auth): Response
{
if ($auth->getCode()) {
if ($auth->connexion() && $auth->isActive()) {
$tokenData = $auth->getToken();
$userDetails = $auth->getUserDetails();
// ... votre logique avec les données utilisateur
return $this->redirectToRoute('home');
}
}
// Redirection vers l'IAM
$auth->redirect(['customScope']);
}
}
Ou utilisez la méthode authenticate() pour une approche encore plus simple :
$result = $auth->authenticate();
if ($result['success']) {
$tokenData = $result['token'];
$userDetails = $result['user_details'];
// ... votre logique
return $this->redirectToRoute('home');
}
$auth->redirect(['customScope']);
Mode avancé (avec IamUserService)
Le service IamUserService simplifie la gestion complète du flux OAuth2 et la création d'utilisateurs :
Configuration du service :
Dans config/services.yaml, configurez la classe utilisateur :
services:
InraeIamBundle\Service\IamUserService:
arguments:
$authenticator: '@InraeIamBundle\Authenticator'
$entityManager: '@doctrine.orm.entity_manager'
$tokenStorage: '@security.token_storage'
$userClass: 'App\Entity\Utilisateur'
Utilisation dans un controller :
use InraeIamBundle\Service\IamUserService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class LoginController extends AbstractController
{
#[Route('/login', name: 'login')]
public function login(IamUserService $iamService): Response
{
if (isset($_GET['code'])) {
$result = $iamService->handleCallback();
if ($result['success']) {
return $this->redirectToRoute('home');
}
return $this->render('login.html.twig', [
'error' => $result['error']
]);
}
$iamService->redirectToAuth(['customScope']);
}
}
API exposée
Authenticator
Classe principale rétrocompatible pour l'authentification IAM.
Constructeur :
__construct(string $authurl, string $client_id, string $client_secret, string $redirect_uri)
Méthodes :
getCode(): ?string- Retourne le code d'autorisation depuis la requêteauthenticate(): array- Gère le flux OAuth2 complet (callback + validation). Retourne['success' => bool, 'token' => ?array, 'user_details' => ?array, 'error' => ?string]connexion(): bool- Traite le callback OAuth2isActive(): bool- Vérifie si le token est actifgetToken(): ?array- Retourne les données du tokengetUserDetails(): ?array- Retourne les informations utilisateurredirect(array $customScopes = []): void- Redirige vers l'endpoint d'autorisationhttp(string $url, array|false $params = false): ?array- Effectue une requête HTTPinfoUser(string $url, string $token): ?array- Récupère les infos utilisateur
IamUserService
Service helper pour simplifier l'intégration avec Symfony Security.
Méthodes :
redirectToAuth(array $customScopes = []): void- Redirige vers l'authentification IAMhandleCallback(): array- Traite le callback et authentifie l'utilisateursetUserConfig(EntityManagerInterface $entityManager, string $userClass): void- Configure la gestion des utilisateurssetTokenStorage(TokenStorageInterface $tokenStorage): void- Configure le token storage
Migration depuis l'ancienne méthode
Si vous utilisiez l'ancienne méthode, vous avez 3 options :
Option 1 : Aucun changement (rétrocompatibilité)
Votre code existant fonctionne tel quel. Il suffit d'installer le bundle et de configurer les paramètres.
Option 2 : Injection de dépendances simple
Remplacez l'instanciation manuelle par l'injection de dépendances :
// Avant
$auth = new Authenticator(
$this->getParameter('app.authurl'),
$this->getParameter('app.clientid'),
// ...
);
// Après
public function login(Authenticator $auth): Response
{
// Utilisez $auth directement
}
Option 3 : Utilisation de IamUserService
Simplifiez votre controller en utilisant le service helper :
// Avant
if ($auth->connexion() && $auth->isActive()) {
$tokenData = $auth->getToken();
$username = $tokenData['sub'];
$user = $entityManager->getRepository(Utilisateur::class)->findOneBy(['username' => $username]);
if (null === $user) {
$infos = $auth->getUserDetails();
$user = new Utilisateur();
// ... création utilisateur
}
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());
$tokenStorage->setToken($token);
}
// Après
$result = $iamService->handleCallback();
if ($result['success']) {
return $this->redirectToRoute('home');
}
Structure du bundle
InraeIamBundle/
├── InraeIamBundle.php # Classe principale du bundle
├── Authenticator.php # Classe d'authentification rétrocompatible
├── DependencyInjection/
│ ├── Configuration.php # Configuration YAML du bundle
│ └── InraeIamExtension.php # Extension du conteneur DI
├── Resources/
│ └── config/
│ └── services.yaml # Définition des services
└── Service/
└── IamUserService.php # Service helper pour Symfony Security
Licence
Ce bundle est développé pour l'INRAE.