#!/usr/bin/env python3 """ Script de diagnostic pour Keycloak UnionFlow """ import requests import json class KeycloakDiagnostic: def __init__(self, base_url: str = "http://localhost:8180"): self.base_url = base_url self.session = requests.Session() self.admin_token = None def get_admin_token(self) -> bool: """Obtient le token admin""" try: data = { "username": "admin", "password": "admin", "grant_type": "password", "client_id": "admin-cli" } response = self.session.post( f"{self.base_url}/realms/master/protocol/openid-connect/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded"} ) if response.status_code == 200: token_data = response.json() self.admin_token = token_data.get("access_token") return self.admin_token is not None except Exception as e: print(f"Erreur obtention token: {e}") return False def check_realm(self, realm_name: str = "unionflow") -> bool: """Vérifie le realm""" print(f"🔍 Vérification du realm {realm_name}...") try: response = self.session.get( f"{self.base_url}/admin/realms/{realm_name}", headers={"Authorization": f"Bearer {self.admin_token}"} ) if response.status_code == 200: realm_data = response.json() print(f"✅ Realm {realm_name} existe") print(f" - Enabled: {realm_data.get('enabled')}") print(f" - Login with email: {realm_data.get('loginWithEmailAllowed')}") return True else: print(f"❌ Realm {realm_name} non trouvé: {response.status_code}") return False except Exception as e: print(f"❌ Erreur vérification realm: {e}") return False def check_client(self, realm_name: str = "unionflow", client_id: str = "unionflow-mobile") -> bool: """Vérifie le client""" print(f"🔍 Vérification du client {client_id}...") try: response = self.session.get( f"{self.base_url}/admin/realms/{realm_name}/clients", headers={"Authorization": f"Bearer {self.admin_token}"} ) if response.status_code == 200: clients = response.json() for client in clients: if client.get("clientId") == client_id: print(f"✅ Client {client_id} trouvé") print(f" - Enabled: {client.get('enabled')}") print(f" - Public: {client.get('publicClient')}") print(f" - Direct Access Grants: {client.get('directAccessGrantsEnabled')}") print(f" - Standard Flow: {client.get('standardFlowEnabled')}") return True print(f"❌ Client {client_id} non trouvé") print("Clients disponibles:") for client in clients: print(f" - {client.get('clientId')}") return False else: print(f"❌ Erreur récupération clients: {response.status_code}") return False except Exception as e: print(f"❌ Erreur vérification client: {e}") return False def check_users(self, realm_name: str = "unionflow") -> bool: """Vérifie les utilisateurs""" print(f"🔍 Vérification des utilisateurs...") expected_users = ["superadmin", "marie.active", "jean.simple", "tech.lead", "rh.manager"] try: response = self.session.get( f"{self.base_url}/admin/realms/{realm_name}/users", headers={"Authorization": f"Bearer {self.admin_token}"} ) if response.status_code == 200: users = response.json() found_users = [user.get("username") for user in users] print(f"✅ {len(users)} utilisateurs trouvés") for expected in expected_users: if expected in found_users: print(f" ✓ {expected}") else: print(f" ✗ {expected} manquant") return len([u for u in expected_users if u in found_users]) == len(expected_users) else: print(f"❌ Erreur récupération utilisateurs: {response.status_code}") return False except Exception as e: print(f"❌ Erreur vérification utilisateurs: {e}") return False def test_direct_auth(self, realm_name: str = "unionflow", client_id: str = "unionflow-mobile"): """Teste l'authentification directe""" print(f"🔍 Test d'authentification directe...") # Test avec marie.active try: data = { "username": "marie.active", "password": "Marie123!", "grant_type": "password", "client_id": client_id } response = self.session.post( f"{self.base_url}/realms/{realm_name}/protocol/openid-connect/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded"} ) print(f"Status: {response.status_code}") print(f"Response: {response.text[:200]}...") if response.status_code == 200: print("✅ Authentification réussie") else: print("❌ Authentification échouée") except Exception as e: print(f"❌ Erreur test auth: {e}") def diagnose(self): """Lance le diagnostic complet""" print("=" * 80) print("🔍 DIAGNOSTIC KEYCLOAK UNIONFLOW") print("=" * 80) print() # 1. Vérifier connexion Keycloak try: response = self.session.get(f"{self.base_url}", timeout=5) if response.status_code == 200: print("✅ Keycloak accessible") else: print(f"❌ Keycloak non accessible: {response.status_code}") return except: print("❌ Keycloak non accessible") return print() # 2. Obtenir token admin if not self.get_admin_token(): print("❌ Impossible d'obtenir le token admin") return print("✅ Token admin obtenu") print() # 3. Vérifier realm self.check_realm() print() # 4. Vérifier client self.check_client() print() # 5. Vérifier utilisateurs self.check_users() print() # 6. Test authentification self.test_direct_auth() print() print("=" * 80) print("🔍 DIAGNOSTIC TERMINÉ") print("=" * 80) def main(): diagnostic = KeycloakDiagnostic() diagnostic.diagnose() if __name__ == "__main__": main()