# Grimaud Login IAM Library

Bibliothèque PHP permettant d'encapsuler l'authentification OIDC avec Keycloak et la gestion des autorisations (rôles, groupes, permissions).

## 1. Installation

Dans l'application cible (par exemple `UsersManager`), ajoutez ce package en tant que dépôt local dans le fichier `composer.json` :

```json
    "repositories": [
        {
            "type": "path",
            "url": "c:/wamp64/www/LoginLibrary"
        }
    ],
```

Puis installez-le via la ligne de commande :
```bash
composer require grimaud/login-iam-library:@dev
```

## 2. Configuration (exemple avec Laravel)

Créez un fichier `config/keycloak.php` qui retourne les paramètres de connexion :

```php
<?php

return [
    'issuer'                 => env('KEYCLOAK_ISSUER', 'https://keycloak.mairie-grimaud.fr/realms/Users%20Authentification'),
    'client_id'              => env('KEYCLOAK_CLIENT_ID', 'usersmanager'),
    'client_secret'          => env('KEYCLOAK_CLIENT_SECRET', ''), // Optionnel si client public
    'authorization_endpoint' => env('KEYCLOAK_AUTH_ENDPOINT', 'https://keycloak.mairie-grimaud.fr/.../auth'),
    'end_session_endpoint'   => env('KEYCLOAK_LOGOUT_ENDPOINT', 'https://keycloak.mairie-grimaud.fr/.../logout'), // Optionnel (déduit auto. depuis auth)
    'scope'                  => env('KEYCLOAK_SCOPE', 'openid profile email'),
    'verify'                 => env('KEYCLOAK_VERIFY_SSL', true), // Mettre à false en dév si pas de certificat
];
```

## 3. Utilisation dans un Contrôleur (Flux OIDC)

### A. Rediriger l'utilisateur vers Keycloak (Login)

```php
use Grimaud\LoginIamLibrary\AuthService;
use Illuminate\Support\Str;

public function login()
{
    $authService = new AuthService(config('keycloak'));
    
    // PKCE et State pour la sécurité
    $state = Str::random(40);
    $codeVerifier = Str::random(128);
    
    // Sauvegarde en session pour vérifier au retour
    session(['oauth_state' => $state, 'oauth_code_verifier' => $codeVerifier]);
    
    $redirectUri = route('auth.callback');
    $url = $authService->getAuthorizationUrl($state, $codeVerifier, $redirectUri);
    
    return redirect($url);
}
```

### B. Traiter le retour de Keycloak (Callback)

```php
public function callback(\Illuminate\Http\Request $request)
{
    // Vérification du state (contre les attaques CSRF)
    if ($request->state !== session('oauth_state')) {
        abort(403, 'State invalide');
    }

    $authService = new AuthService(config('keycloak'));
    $codeVerifier = session('oauth_code_verifier');
    
    try {
        // 1. Échange du code contre les tokens
        $tokens = $authService->exchangeCodeForTokens(
            $request->code, 
            route('auth.callback'), 
            $codeVerifier
        );
        
        $accessToken = $tokens['access_token'];
        $idToken = $tokens['id_token'] ?? null;
        
        // 2. Validation du token et extraction des informations
        $checker = $authService->authenticateAndAuthorize($accessToken);
        $userInfo = $checker->getTokenInfo();
        
        // 3. Connecter l'utilisateur dans Laravel (optionnel)
        // ex: $user = User::firstOrCreate(['email' => $userInfo->getEmail()]);
        // Auth::login($user);
        
        // Stocker l'access_token et l'id_token en session (pour les APIs et la déconnexion)
        session([
            'access_token' => $accessToken,
            'id_token'     => $idToken
        ]);
        
        return redirect('/dashboard');
        
    } catch (\Exception $e) {
        return "Erreur d'authentification : " . $e->getMessage();
    }
}
```

## 4. Déconnexion (RP-Initiated Logout)

Pour déconnecter l'utilisateur proprement de votre application ET de Keycloak (Single Sign-Out) :

```php
public function logout()
{
    $authService = new AuthService(config('keycloak'));
    
    // Récupération de l'id_token stocké lors de la connexion
    $idToken = session('id_token');
    
    // On vide la session de l'application
    session()->flush();
    
    // On redirige vers Keycloak pour fermer la session globale
    // (Keycloak va ensuite rediriger l'utilisateur vers route('home'))
    $url = $authService->getLogoutUrl($idToken, route('home'));
    
    return redirect($url);
}
```

## 5. Vérifier les autorisations (Middlewares ou Contrôleurs)

Une fois que vous avez l' `access_token` (récupéré depuis la session ou via le header d'une API `Bearer Token`), vous pouvez vérifier les droits très facilement :

```php
use Grimaud\LoginIamLibrary\AuthService;
use Grimaud\LoginIamLibrary\Exceptions\TokenException;

$authService = new AuthService(config('keycloak'));
$accessToken = session('access_token'); // Ou request()->bearerToken()

try {
    $checker = $authService->authenticateAndAuthorize($accessToken);
    
    // -- Informations utilisateur --
    $email = $checker->getTokenInfo()->getEmail();
    $name = $checker->getTokenInfo()->getName();
    
    // -- Vérifications des Groupes --
    if ($checker->isInGroup('/Direction')) {
        // Action autorisée
    }
    
    // -- Vérifications des Rôles --
    if ($checker->hasRole('admin')) { // Cherche dans le realm et le client_id configuré
        // Action autorisée
    }
    
    if ($checker->hasRealmRole('super-admin')) {
        // ...
    }

} catch (TokenException $e) {
    // Token expiré ou signature invalide
    abort(401, 'Session expirée, veuillez vous reconnecter.');
}
```
