#!/bin/bash # Script d'automatisation de la configuration Keycloak pour UnionFlow # Usage: ./setup-keycloak.sh echo "" echo "========================================================" echo "🔧 Configuration automatique de Keycloak pour UnionFlow" echo "========================================================" echo "" # Configuration KEYCLOAK_URL="http://localhost:8180" ADMIN_USER="admin" ADMIN_PASS="admin" REALM_NAME="unionflow" CLIENT_ID="unionflow-client" echo "📋 Paramètres:" echo " - Keycloak URL: $KEYCLOAK_URL" echo " - Admin User: $ADMIN_USER" echo " - Realm: $REALM_NAME" echo " - Client ID: $CLIENT_ID" echo "" # Vérifier que Keycloak est accessible echo "🔍 Vérification de Keycloak..." if ! curl -s "$KEYCLOAK_URL" > /dev/null; then echo "❌ ERREUR: Keycloak n'est pas accessible sur $KEYCLOAK_URL" echo " Assurez-vous que Keycloak est démarré." exit 1 fi echo "✅ Keycloak est accessible" echo "" # Étape 1: Obtenir le token admin echo "📝 Étape 1/7: Obtention du token admin..." TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$ADMIN_USER" \ -d "password=$ADMIN_PASS" \ -d "grant_type=password" \ -d "client_id=admin-cli") ADMIN_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4) if [ -z "$ADMIN_TOKEN" ]; then echo "❌ ERREUR: Impossible d'obtenir le token admin" echo " Vérifiez les identifiants: $ADMIN_USER / $ADMIN_PASS" exit 1 fi echo "✅ Token admin obtenu" echo "" # Étape 2: Créer le realm echo "📝 Étape 2/7: Création du realm '$REALM_NAME'..." curl -s -X POST "$KEYCLOAK_URL/admin/realms" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"realm\":\"$REALM_NAME\",\"enabled\":true,\"displayName\":\"UnionFlow\",\"registrationAllowed\":false,\"loginWithEmailAllowed\":true,\"duplicateEmailsAllowed\":false,\"resetPasswordAllowed\":true,\"editUsernameAllowed\":false,\"bruteForceProtected\":true}" > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "⚠️ Le realm existe peut-être déjà, continuation..." else echo "✅ Realm créé" fi echo "" # Étape 3: Créer les rôles echo "📝 Étape 3/7: Création des rôles..." curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"SUPER_ADMIN","description":"Super administrateur système"}' > /dev/null 2>&1 echo " ✅ Rôle SUPER_ADMIN créé" curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"ADMIN_ENTITE","description":"Administrateur d'\''entité"}' > /dev/null 2>&1 echo " ✅ Rôle ADMIN_ENTITE créé" curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"MEMBRE","description":"Membre standard"}' > /dev/null 2>&1 echo " ✅ Rôle MEMBRE créé" curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"GESTIONNAIRE_MEMBRE","description":"Gestionnaire des membres"}' > /dev/null 2>&1 echo " ✅ Rôle GESTIONNAIRE_MEMBRE créé" curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"GESTIONNAIRE_EVENEMENT","description":"Gestionnaire des événements"}' > /dev/null 2>&1 echo " ✅ Rôle GESTIONNAIRE_EVENEMENT créé" echo "" # Étape 4: Créer le client echo "📝 Étape 4/7: Création du client '$CLIENT_ID'..." curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"clientId\":\"$CLIENT_ID\",\"enabled\":true,\"protocol\":\"openid-connect\",\"publicClient\":false,\"directAccessGrantsEnabled\":true,\"standardFlowEnabled\":true,\"implicitFlowEnabled\":false,\"serviceAccountsEnabled\":false,\"authorizationServicesEnabled\":false,\"rootUrl\":\"http://localhost:8086\",\"baseUrl\":\"http://localhost:8086\",\"redirectUris\":[\"http://localhost:8086/*\"],\"webOrigins\":[\"http://localhost:8086\"],\"attributes\":{\"post.logout.redirect.uris\":\"http://localhost:8086/*\"}}" > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "⚠️ Le client existe peut-être déjà, continuation..." else echo "✅ Client créé" fi echo "" # Étape 5: Récupérer le client ID (UUID) et le secret echo "📝 Étape 5/7: Récupération du client secret..." CLIENTS=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" \ -H "Authorization: Bearer $ADMIN_TOKEN") CLIENT_UUID=$(echo "$CLIENTS" | grep -o "\"id\":\"[^\"]*\"" | grep -B5 "\"clientId\":\"$CLIENT_ID\"" | head -1 | cut -d'"' -f4) if [ -z "$CLIENT_UUID" ]; then # Méthode alternative avec jq si disponible if command -v jq &> /dev/null; then CLIENT_UUID=$(echo "$CLIENTS" | jq -r ".[] | select(.clientId==\"$CLIENT_ID\") | .id") fi fi if [ -z "$CLIENT_UUID" ]; then echo "❌ ERREUR: Impossible de trouver le client UUID" echo " Installez 'jq' pour un meilleur parsing JSON ou configurez manuellement" exit 1 fi # Récupérer le secret du client SECRET_RESPONSE=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients/$CLIENT_UUID/client-secret" \ -H "Authorization: Bearer $ADMIN_TOKEN") CLIENT_SECRET=$(echo "$SECRET_RESPONSE" | grep -o '"value":"[^"]*' | cut -d'"' -f4) if [ -z "$CLIENT_SECRET" ] && command -v jq &> /dev/null; then CLIENT_SECRET=$(echo "$SECRET_RESPONSE" | jq -r '.value') fi if [ -z "$CLIENT_SECRET" ]; then echo "❌ ERREUR: Impossible de récupérer le client secret" exit 1 fi echo "✅ Client Secret récupéré: $CLIENT_SECRET" echo "" # Étape 6: Configurer le client scope mapper pour les rôles echo "📝 Étape 6/7: Configuration du mapper de rôles..." SCOPES=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients/$CLIENT_UUID/default-client-scopes" \ -H "Authorization: Bearer $ADMIN_TOKEN") SCOPE_ID=$(echo "$SCOPES" | grep -o '"id":"[^"]*"' | grep -A5 "dedicated" | head -1 | cut -d'"' -f4) if [ -z "$SCOPE_ID" ] && command -v jq &> /dev/null; then SCOPE_ID=$(echo "$SCOPES" | jq -r '.[] | select(.name | contains("dedicated")) | .id') fi if [ -n "$SCOPE_ID" ]; then curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/client-scopes/$SCOPE_ID/protocol-mappers/models" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"realm-roles","protocol":"openid-connect","protocolMapper":"oidc-usermodel-realm-role-mapper","config":{"multivalued":"true","userinfo.token.claim":"true","id.token.claim":"true","access.token.claim":"true","claim.name":"roles","jsonType.label":"String"}}' > /dev/null 2>&1 echo "✅ Mapper de rôles configuré" else echo "⚠️ Impossible de trouver le client scope dédié, le mapper devra être configuré manuellement" fi echo "" # Étape 7: Créer un utilisateur test echo "📝 Étape 7/7: Création de l'utilisateur test..." curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"username":"test@unionflow.dev","email":"test@unionflow.dev","firstName":"Test","lastName":"User","enabled":true,"emailVerified":true}' > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "⚠️ L'utilisateur existe peut-être déjà, continuation..." else echo "✅ Utilisateur créé" fi # Récupérer l'ID de l'utilisateur USER_RESPONSE=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=test@unionflow.dev" \ -H "Authorization: Bearer $ADMIN_TOKEN") USER_ID=$(echo "$USER_RESPONSE" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4) if [ -z "$USER_ID" ] && command -v jq &> /dev/null; then USER_ID=$(echo "$USER_RESPONSE" | jq -r '.[0].id') fi if [ -n "$USER_ID" ]; then # Définir le mot de passe curl -s -X PUT "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$USER_ID/reset-password" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"type":"password","value":"test123","temporary":false}' > /dev/null 2>&1 echo " ✅ Mot de passe défini (test123)" # Récupérer les rôles ROLES=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \ -H "Authorization: Bearer $ADMIN_TOKEN") ROLE_MEMBRE_ID=$(echo "$ROLES" | grep -B2 '"name":"MEMBRE"' | grep '"id"' | cut -d'"' -f4) ROLE_ADMIN_ID=$(echo "$ROLES" | grep -B2 '"name":"ADMIN_ENTITE"' | grep '"id"' | cut -d'"' -f4) if command -v jq &> /dev/null; then ROLE_MEMBRE_ID=$(echo "$ROLES" | jq -r '.[] | select(.name=="MEMBRE") | .id') ROLE_ADMIN_ID=$(echo "$ROLES" | jq -r '.[] | select(.name=="ADMIN_ENTITE") | .id') fi if [ -n "$ROLE_MEMBRE_ID" ]; then curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$USER_ID/role-mappings/realm" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d "[{\"id\":\"$ROLE_MEMBRE_ID\",\"name\":\"MEMBRE\"}]" > /dev/null 2>&1 echo " ✅ Rôle MEMBRE assigné" fi if [ -n "$ROLE_ADMIN_ID" ]; then curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$USER_ID/role-mappings/realm" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d "[{\"id\":\"$ROLE_ADMIN_ID\",\"name\":\"ADMIN_ENTITE\"}]" > /dev/null 2>&1 echo " ✅ Rôle ADMIN_ENTITE assigné" fi else echo "⚠️ Impossible de configurer l'utilisateur" fi echo "" # Sauvegarder le client secret dans .env echo "" echo "💾 Sauvegarde de la configuration..." cat > .env << EOF # Configuration Keycloak générée automatiquement # Date: $(date) KEYCLOAK_CLIENT_SECRET=$CLIENT_SECRET UNIONFLOW_BACKEND_URL=http://localhost:8085 # Informations de connexion pour tests # Username: test@unionflow.dev # Password: test123 EOF echo "✅ Fichier .env créé avec le client secret" echo "" # Résumé echo "========================================================" echo "✅ Configuration Keycloak terminée avec succès!" echo "========================================================" echo "" echo "📋 Résumé:" echo " - Realm: $REALM_NAME" echo " - Client ID: $CLIENT_ID" echo " - Client Secret: $CLIENT_SECRET" echo " - Utilisateur test: test@unionflow.dev" echo " - Mot de passe: test123" echo " - Rôles assignés: MEMBRE, ADMIN_ENTITE" echo "" echo "📄 Le client secret a été sauvegardé dans le fichier .env" echo "" echo "🚀 Prochaines étapes:" echo " 1. Vérifiez le fichier .env" echo " 2. Lancez l'application avec: ./start-local.sh" echo " 3. Accédez à http://localhost:8086" echo " 4. Connectez-vous avec test@unionflow.dev / test123" echo "" echo "========================================================" echo ""