#!/usr/bin/env python3 """ Test d'authentification avec les vrais usernames (emails) trouvés dans Keycloak """ import requests import json class EmailUsernameTester: 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 reset_password_for_email_user(self, user_id: str, email_username: str, password: str) -> bool: """Remet à zéro le mot de passe pour un utilisateur identifié par email""" print(f"🔑 Réinitialisation du mot de passe pour {email_username}...") try: # Définir le mot de passe password_data = { "type": "password", "value": password, "temporary": False } response = self.session.put( f"{self.base_url}/admin/realms/unionflow/users/{user_id}/reset-password", json=password_data, headers={ "Authorization": f"Bearer {self.admin_token}", "Content-Type": "application/json" } ) if response.status_code == 204: print(f" ✓ Mot de passe défini") return True else: print(f" ❌ Erreur: {response.status_code}") return False except Exception as e: print(f" ❌ Exception: {e}") return False def test_user_auth(self, username: str, password: str) -> bool: """Teste l'authentification d'un utilisateur""" print(f"🧪 Test de {username}...") try: data = { "username": username, "password": password, "grant_type": "password", "client_id": "unionflow-mobile" } response = self.session.post( f"{self.base_url}/realms/unionflow/protocol/openid-connect/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded"} ) print(f" 📊 Status: {response.status_code}") if response.status_code == 200: token_data = response.json() if "access_token" in token_data: print(f" ✅ {username} FONCTIONNE !") # Décoder le token pour voir les infos try: import base64 token_parts = token_data['access_token'].split('.') if len(token_parts) >= 2: payload = token_parts[1] payload += '=' * (4 - len(payload) % 4) decoded = base64.b64decode(payload) token_info = json.loads(decoded) print(f" 👤 Utilisateur: {token_info.get('preferred_username', 'N/A')}") print(f" 📧 Email: {token_info.get('email', 'N/A')}") if 'realm_access' in token_info and 'roles' in token_info['realm_access']: roles = token_info['realm_access']['roles'] user_roles = [r for r in roles if not r.startswith('default-') and r != 'offline_access' and r != 'uma_authorization'] if user_roles: print(f" 🎭 Rôles: {', '.join(user_roles)}") except: pass return True else: print(f" ❌ Token manquant") else: print(f" ❌ Authentification échouée: {response.text}") except Exception as e: print(f" ❌ Exception: {e}") return False def fix_and_test_email_users(self): """Corrige et teste les utilisateurs avec leurs emails comme usernames""" print("=" * 80) print("🔧 CORRECTION ET TEST AVEC LES VRAIS USERNAMES (EMAILS)") print("=" * 80) print() if not self.get_admin_token(): print("❌ Impossible d'obtenir le token admin") return False print("✅ Token admin obtenu") print() # Récupérer tous les utilisateurs try: response = self.session.get( f"{self.base_url}/admin/realms/unionflow/users", headers={"Authorization": f"Bearer {self.admin_token}"} ) if response.status_code != 200: print("❌ Impossible de récupérer les utilisateurs") return False users = response.json() except: print("❌ Erreur récupération utilisateurs") return False # Mapping des utilisateurs trouvés avec leurs mots de passe attendus user_mappings = { "marie.active@unionflow.com": "Marie123!", "superadmin@unionflow.com": "SuperAdmin123!", "jean.simple@unionflow.com": "Jean123!", "tech.lead@unionflow.com": "TechLead123!", "rh.manager@unionflow.com": "RhManager123!" } success_count = 0 working_users = [] print("🔧 Réinitialisation des mots de passe...") print() # Corriger les mots de passe for user in users: username = user.get("username", "") user_id = user.get("id", "") if username in user_mappings: password = user_mappings[username] if self.reset_password_for_email_user(user_id, username, password): print(f" ✓ Mot de passe mis à jour pour {username}") print() print("🧪 Test d'authentification avec les emails comme usernames...") print() # Tester l'authentification for email_username, password in user_mappings.items(): if self.test_user_auth(email_username, password): success_count += 1 working_users.append((email_username, password)) print() print("=" * 80) print(f"📊 RÉSULTAT FINAL: {success_count}/{len(user_mappings)} comptes fonctionnent") print("=" * 80) if success_count > 0: print() print("🎉 COMPTES QUI FONCTIONNENT (avec emails comme usernames) :") print() for username, password in working_users: print(f" ✅ {username} / {password}") print() print("🚀 VOTRE APPLICATION MOBILE PEUT S'AUTHENTIFIER !") print() print("📱 PARAMÈTRES POUR L'APPLICATION :") print(f" • Keycloak URL: {self.base_url}") print(" • Realm: unionflow") print(" • Client ID: unionflow-mobile") print(" • Redirect URI: dev.lions.unionflow-mobile://auth/callback") print() print("⚠️ IMPORTANT : Utilisez les EMAILS comme usernames !") print(f" • Exemple: {working_users[0][0]} / {working_users[0][1]}") print() print("✅ TOUS LES COMPTES UNIONFLOW SONT MAINTENANT OPÉRATIONNELS !") return True else: print() print("❌ Aucun compte ne fonctionne") return False def main(): tester = EmailUsernameTester() tester.fix_and_test_email_users() if __name__ == "__main__": main()