Files
unionflow-client-quarkus-pr…/configure-keycloak-mobile.sh
DahoudG f89f6167cc feat(mobile): Implement Keycloak WebView authentication with HTTP callback
- 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
2025-09-15 01:44:16 +00:00

241 lines
8.4 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Configuration automatique du client mobile Keycloak pour UnionFlow
# Ce script configure le client unionflow-mobile dans Keycloak
set -e
# Configuration
KEYCLOAK_URL="http://localhost:8180"
REALM="unionflow"
ADMIN_USER="admin"
ADMIN_PASSWORD="admin"
CLIENT_ID="unionflow-mobile"
echo "🔧 Configuration automatique du client mobile Keycloak..."
echo "📍 Keycloak URL: $KEYCLOAK_URL"
echo "🏛️ Realm: $REALM"
echo "📱 Client ID: $CLIENT_ID"
echo ""
# Fonction pour obtenir le token d'administration
get_admin_token() {
echo "🔑 Obtention du token d'administration..."
ADMIN_TOKEN=$(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_PASSWORD" \
-d "grant_type=password" \
-d "client_id=admin-cli" | jq -r '.access_token')
if [ "$ADMIN_TOKEN" = "null" ] || [ -z "$ADMIN_TOKEN" ]; then
echo "❌ Erreur: Impossible d'obtenir le token d'administration"
echo "Vérifiez les credentials Keycloak (admin/admin)"
exit 1
fi
echo "✅ Token d'administration obtenu"
}
# Fonction pour vérifier si le client existe déjà
check_client_exists() {
echo "🔍 Vérification de l'existence du client $CLIENT_ID..."
CLIENT_EXISTS=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM/clients" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" | jq -r ".[] | select(.clientId==\"$CLIENT_ID\") | .id")
if [ -n "$CLIENT_EXISTS" ] && [ "$CLIENT_EXISTS" != "null" ]; then
echo "⚠️ Client $CLIENT_ID existe déjà (ID: $CLIENT_EXISTS)"
return 0
else
echo " Client $CLIENT_ID n'existe pas, création nécessaire"
return 1
fi
}
# Fonction pour créer le client mobile
create_mobile_client() {
echo "📱 Création du client mobile $CLIENT_ID..."
CLIENT_CONFIG='{
"clientId": "'$CLIENT_ID'",
"name": "UnionFlow Mobile App",
"description": "Application mobile UnionFlow avec authentification OIDC",
"enabled": true,
"clientAuthenticatorType": "client-secret",
"publicClient": true,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"authorizationServicesEnabled": false,
"rootUrl": "com.unionflow.mobile://",
"baseUrl": "com.unionflow.mobile://home",
"redirectUris": [
"com.unionflow.mobile://login-callback",
"com.unionflow.mobile://login-callback/*"
],
"postLogoutRedirectUris": [
"com.unionflow.mobile://logout-callback",
"com.unionflow.mobile://logout-callback/*"
],
"webOrigins": ["+"],
"attributes": {
"pkce.code.challenge.method": "S256",
"access.token.lifespan": "900",
"client.session.idle.timeout": "1800",
"client.session.max.lifespan": "43200"
},
"defaultClientScopes": ["openid", "profile", "email", "roles"],
"optionalClientScopes": []
}'
RESPONSE=$(curl -s -w "%{http_code}" -X POST "$KEYCLOAK_URL/admin/realms/$REALM/clients" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "$CLIENT_CONFIG")
HTTP_CODE="${RESPONSE: -3}"
if [ "$HTTP_CODE" = "201" ]; then
echo "✅ Client mobile créé avec succès"
# Récupérer l'ID du client créé
CLIENT_UUID=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM/clients" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" | jq -r ".[] | select(.clientId==\"$CLIENT_ID\") | .id")
echo "📋 Client UUID: $CLIENT_UUID"
return 0
else
echo "❌ Erreur lors de la création du client (HTTP: $HTTP_CODE)"
echo "Response: ${RESPONSE%???}"
return 1
fi
}
# Fonction pour configurer les mappers de rôles
configure_role_mappers() {
echo "🎭 Configuration des mappers de rôles..."
# Mapper pour l'audience
AUDIENCE_MAPPER='{
"name": "audience-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"config": {
"included.client.audience": "unionflow-server",
"access.token.claim": "true"
}
}'
# Mapper pour les rôles client
ROLES_MAPPER='{
"name": "client-roles-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-client-role-mapper",
"config": {
"client.id": "unionflow-server",
"claim.name": "resource_access.unionflow-server.roles",
"access.token.claim": "true",
"id.token.claim": "false",
"userinfo.token.claim": "false",
"multivalued": "true"
}
}'
# Ajouter le mapper d'audience
curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM/clients/$CLIENT_UUID/protocol-mappers/models" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "$AUDIENCE_MAPPER" > /dev/null
# Ajouter le mapper de rôles
curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM/clients/$CLIENT_UUID/protocol-mappers/models" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "$ROLES_MAPPER" > /dev/null
echo "✅ Mappers de rôles configurés"
}
# Fonction pour tester la configuration
test_configuration() {
echo "🧪 Test de la configuration..."
# Test de l'endpoint d'autorisation
AUTH_URL="$KEYCLOAK_URL/realms/$REALM/protocol/openid-connect/auth"
echo "📍 URL d'autorisation: $AUTH_URL"
# Test de l'endpoint de token
TOKEN_URL="$KEYCLOAK_URL/realms/$REALM/protocol/openid-connect/token"
echo "📍 URL de token: $TOKEN_URL"
# Vérifier que les endpoints répondent
AUTH_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$AUTH_URL?client_id=$CLIENT_ID&response_type=code&redirect_uri=com.unionflow.mobile://login-callback")
if [ "$AUTH_STATUS" = "200" ] || [ "$AUTH_STATUS" = "302" ]; then
echo "✅ Endpoint d'autorisation accessible"
else
echo "⚠️ Endpoint d'autorisation: HTTP $AUTH_STATUS"
fi
echo "✅ Configuration testée"
}
# Fonction principale
main() {
echo "🚀 Début de la configuration automatique..."
echo ""
# Vérifier que jq est installé
if ! command -v jq &> /dev/null; then
echo "❌ Erreur: jq n'est pas installé"
echo "Installez jq avec: sudo apt-get install jq (Ubuntu) ou brew install jq (macOS)"
exit 1
fi
# Obtenir le token d'administration
get_admin_token
# Vérifier si le client existe déjà
if check_client_exists; then
echo " Client existant trouvé, récupération de l'UUID..."
CLIENT_UUID="$CLIENT_EXISTS"
else
# Créer le client mobile
if create_mobile_client; then
CLIENT_UUID=$(curl -s -X GET "$KEYCLOAK_URL/admin/realms/$REALM/clients" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" | jq -r ".[] | select(.clientId==\"$CLIENT_ID\") | .id")
else
echo "❌ Échec de la création du client"
exit 1
fi
fi
# Configurer les mappers de rôles
configure_role_mappers
# Tester la configuration
test_configuration
echo ""
echo "🎉 Configuration terminée avec succès !"
echo ""
echo "📋 Résumé de la configuration:"
echo " • Client ID: $CLIENT_ID"
echo " • Client UUID: $CLIENT_UUID"
echo " • Type: Public (PKCE activé)"
echo " • Redirect URI: com.unionflow.mobile://login-callback"
echo " • Logout URI: com.unionflow.mobile://logout-callback"
echo ""
echo "🔗 URLs importantes:"
echo " • Authorization: $KEYCLOAK_URL/realms/$REALM/protocol/openid-connect/auth"
echo " • Token: $KEYCLOAK_URL/realms/$REALM/protocol/openid-connect/token"
echo " • Logout: $KEYCLOAK_URL/realms/$REALM/protocol/openid-connect/logout"
echo ""
echo "✅ L'application mobile peut maintenant s'authentifier avec Keycloak !"
}
# Exécuter le script principal
main "$@"