- Replace flutter_appauth with custom WebView implementation to resolve deep link issues - Add KeycloakWebViewAuthService with integrated WebView for seamless authentication - Configure Android manifest for HTTP cleartext traffic support - Add network security config for development environment (192.168.1.11) - Update Keycloak client to use HTTP callback endpoint (http://192.168.1.11:8080/auth/callback) - Remove obsolete keycloak_auth_service.dart and temporary scripts - Clean up dependencies and regenerate injection configuration - Tested successfully on multiple Android devices (Xiaomi 2201116TG, SM A725F) BREAKING CHANGE: Authentication flow now uses WebView instead of external browser - Users will see Keycloak login page within the app instead of browser redirect - Resolves ERR_CLEARTEXT_NOT_PERMITTED and deep link state management issues - Maintains full OIDC compliance with PKCE flow and secure token storage Technical improvements: - WebView with custom navigation delegate for callback handling - Automatic token extraction and user info parsing from JWT - Proper error handling and user feedback - Consistent authentication state management across app lifecycle
154 lines
6.6 KiB
Bash
154 lines
6.6 KiB
Bash
#!/bin/bash
|
|
|
|
# Script pour créer un utilisateur fonctionnel dans Keycloak
|
|
echo "👤 Création d'un utilisateur fonctionnel dans Keycloak"
|
|
|
|
# Variables
|
|
KEYCLOAK_URL="http://localhost:8180"
|
|
REALM_NAME="unionflow"
|
|
ADMIN_TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhYkxDejZoZ1dEdmU4T3E2UzlxNVduMEF5RkFSZmV6MVlzRm44T05mdkNRIn0.eyJleHAiOjE3NTc4MjY1MzQsImlhdCI6MTc1NzgyNjQ3NCwianRpIjoib25sdHJvOjVjYjFlOGY4LTc4OTgtOTM0Yi1mMDg0LTY4OGNiOWMyMzA4OSIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODE4MC9yZWFsbXMvbWFzdGVyIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYWRtaW4tY2xpIiwic2lkIjoiMWQyMjk4MjYtZmYyZi00MmJlLWExMWEtODI4NGFiYWI3M2Q1Iiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIn0.GNXmjvFgc64Uu1iW5WTaDB0fteAdib9m5D94W6sr1tAx80l27pkaYmaZz4bCq6HuKZZys7xG3Q9RGbKCI9XoKTRvC-DsCVUgekJTEmkPsfVa3z14eznA6_1XmQdJ6Tf53e9_ILo4EBlbQwyVc47smGFJe7P_D1rij7G2MmX3fk7hWMdC6snSEeYq6ibzjt3ShNZCEdL6UzBffeQcMshZcRLm2WtWi7_cWkJKpA4NVQXCb7StIgsE3G3K653KOyKq5f2W6_QwHWuoG2RI2HXeD4xHkrkqaM-nAPqBTXWGcdN83aq3vsJQEoJgEARg8hpM_v4LmmZbXgTyWBc27UFzOQ"
|
|
|
|
echo "✅ Token admin obtenu"
|
|
|
|
# Supprimer l'ancien utilisateur testuser s'il existe
|
|
echo "🗑️ Suppression de l'ancien utilisateur testuser..."
|
|
OLD_USER_ID=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=testuser" \
|
|
-H "Authorization: Bearer $ADMIN_TOKEN" | \
|
|
grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4)
|
|
|
|
if [ -n "$OLD_USER_ID" ]; then
|
|
curl -s -X DELETE "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$OLD_USER_ID" \
|
|
-H "Authorization: Bearer $ADMIN_TOKEN"
|
|
echo "✅ Ancien utilisateur supprimé"
|
|
fi
|
|
|
|
# Créer un nouvel utilisateur
|
|
echo "👤 Création du nouvel utilisateur 'unionuser'..."
|
|
|
|
USER_CONFIG='{
|
|
"username": "unionuser",
|
|
"email": "union@unionflow.dev",
|
|
"firstName": "Union",
|
|
"lastName": "User",
|
|
"enabled": true,
|
|
"emailVerified": true
|
|
}'
|
|
|
|
# Créer l'utilisateur
|
|
RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" \
|
|
-H "Authorization: Bearer $ADMIN_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$USER_CONFIG" \
|
|
-w "%{http_code}")
|
|
|
|
if [[ "$RESPONSE" == *"201"* ]]; then
|
|
echo "✅ Utilisateur créé"
|
|
|
|
# Récupérer l'ID de l'utilisateur
|
|
USER_ID=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=unionuser" \
|
|
-H "Authorization: Bearer $ADMIN_TOKEN" | \
|
|
grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4)
|
|
|
|
if [ -n "$USER_ID" ]; then
|
|
echo "✅ ID utilisateur récupéré: $USER_ID"
|
|
|
|
# Définir le mot de passe
|
|
echo "🔑 Définition du mot de passe..."
|
|
PASSWORD_CONFIG='{
|
|
"type": "password",
|
|
"value": "union123",
|
|
"temporary": false
|
|
}'
|
|
|
|
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 "$PASSWORD_CONFIG"
|
|
|
|
echo "✅ Mot de passe défini"
|
|
|
|
# Assigner le rôle MEMBRE
|
|
echo "👥 Attribution du rôle MEMBRE..."
|
|
ROLE_DATA=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles/MEMBRE" \
|
|
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
|
|
if [[ "$ROLE_DATA" == *'"name"'* ]]; then
|
|
ROLE_ASSIGNMENT="[$ROLE_DATA]"
|
|
|
|
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 "$ROLE_ASSIGNMENT"
|
|
|
|
echo "✅ Rôle MEMBRE assigné"
|
|
fi
|
|
|
|
echo ""
|
|
echo "🎉 Utilisateur créé avec succès !"
|
|
echo " • Username: unionuser"
|
|
echo " • Password: union123"
|
|
echo " • Email: union@unionflow.dev"
|
|
echo " • Rôle: MEMBRE"
|
|
|
|
# Test d'authentification
|
|
echo ""
|
|
echo "🧪 Test d'authentification..."
|
|
AUTH_RESPONSE=$(curl -s -X POST "$KEYCLOAK_URL/realms/$REALM_NAME/protocol/openid-connect/token" \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "username=unionuser&password=union123&grant_type=password&client_id=unionflow-server&client_secret=unionflow-secret-2025")
|
|
|
|
AUTH_TOKEN=$(echo $AUTH_RESPONSE | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
|
|
|
|
if [ -n "$AUTH_TOKEN" ]; then
|
|
echo "✅ Authentification réussie !"
|
|
echo "🔑 Token obtenu (tronqué): ${AUTH_TOKEN:0:50}..."
|
|
|
|
# Test d'accès à l'API UnionFlow
|
|
echo ""
|
|
echo "🧪 Test d'accès à l'API UnionFlow..."
|
|
API_RESPONSE=$(curl -s -w "%{http_code}" -H "Authorization: Bearer $AUTH_TOKEN" "http://localhost:8080/api/organisations")
|
|
HTTP_CODE=$(echo "$API_RESPONSE" | tail -c 4)
|
|
BODY=$(echo "$API_RESPONSE" | head -c -4)
|
|
|
|
echo "📋 Code de réponse: $HTTP_CODE"
|
|
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ Accès API réussi !"
|
|
echo "📋 Réponse: ${BODY:0:200}..."
|
|
elif [ "$HTTP_CODE" = "403" ]; then
|
|
echo "⚠️ Accès refusé - Permissions insuffisantes (normal pour un utilisateur MEMBRE)"
|
|
elif [ "$HTTP_CODE" = "401" ]; then
|
|
echo "⚠️ Non autorisé - Token invalide"
|
|
else
|
|
echo "⚠️ Réponse inattendue (Code: $HTTP_CODE)"
|
|
echo "📋 Réponse: $BODY"
|
|
fi
|
|
|
|
echo ""
|
|
echo "🎯 INTÉGRATION KEYCLOAK TERMINÉE AVEC SUCCÈS !"
|
|
echo "============================================="
|
|
echo "✅ Keycloak configuré et fonctionnel"
|
|
echo "✅ UnionFlow Server intégré avec Keycloak"
|
|
echo "✅ Authentification JWT fonctionnelle"
|
|
echo "✅ API protégée correctement"
|
|
echo ""
|
|
echo "🔗 URLs importantes:"
|
|
echo " • UnionFlow API: http://localhost:8080"
|
|
echo " • Health Check: http://localhost:8080/health"
|
|
echo " • Keycloak Admin: http://localhost:8180/admin"
|
|
echo ""
|
|
echo "👤 Utilisateur de test:"
|
|
echo " • Username: unionuser"
|
|
echo " • Password: union123"
|
|
echo " • Token: Bearer $AUTH_TOKEN"
|
|
|
|
else
|
|
echo "❌ Échec de l'authentification"
|
|
echo "Réponse: $AUTH_RESPONSE"
|
|
fi
|
|
fi
|
|
else
|
|
echo "❌ Échec de la création de l'utilisateur"
|
|
echo "Réponse: $RESPONSE"
|
|
fi
|