Files
unionflow-mobile-apps/configure-keycloak-simple.ps1
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

217 lines
8.5 KiB
PowerShell
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.

# Configuration automatique du client mobile Keycloak pour UnionFlow
# Version simplifiée pour Windows PowerShell
$KeycloakUrl = "http://localhost:8180"
$Realm = "unionflow"
$AdminUser = "admin"
$AdminPassword = "admin"
$ClientId = "unionflow-mobile"
Write-Host "🔧 Configuration automatique du client mobile Keycloak..." -ForegroundColor Cyan
Write-Host "📍 Keycloak URL: $KeycloakUrl" -ForegroundColor Gray
Write-Host "🏛️ Realm: $Realm" -ForegroundColor Gray
Write-Host "📱 Client ID: $ClientId" -ForegroundColor Gray
Write-Host ""
# Obtenir le token d'administration
Write-Host "🔑 Obtention du token d'administration..." -ForegroundColor Yellow
$tokenBody = @{
username = $AdminUser
password = $AdminPassword
grant_type = "password"
client_id = "admin-cli"
}
try {
$tokenResponse = Invoke-RestMethod -Uri "$KeycloakUrl/realms/master/protocol/openid-connect/token" -Method Post -Body $tokenBody -ContentType "application/x-www-form-urlencoded"
$adminToken = $tokenResponse.access_token
Write-Host "✅ Token d'administration obtenu" -ForegroundColor Green
}
catch {
Write-Host "❌ Erreur: Impossible d'obtenir le token d'administration" -ForegroundColor Red
Write-Host "Vérifiez les credentials Keycloak ($AdminUser/$AdminPassword)" -ForegroundColor Red
Write-Host "Erreur: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# Vérifier si le client existe déjà
Write-Host "🔍 Vérification de l'existence du client $ClientId..." -ForegroundColor Yellow
$headers = @{ Authorization = "Bearer $adminToken" }
try {
$clients = Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients" -Method Get -Headers $headers
$existingClient = $clients | Where-Object { $_.clientId -eq $ClientId }
if ($existingClient) {
Write-Host "⚠️ Client $ClientId existe déjà (ID: $($existingClient.id))" -ForegroundColor Yellow
$clientUuid = $existingClient.id
}
else {
Write-Host " Client $ClientId n'existe pas, création nécessaire" -ForegroundColor Blue
# Créer le client mobile
Write-Host "📱 Création du client mobile $ClientId..." -ForegroundColor Yellow
$clientConfig = @{
clientId = $ClientId
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 = @()
}
$jsonHeaders = @{
Authorization = "Bearer $adminToken"
"Content-Type" = "application/json"
}
$jsonBody = $clientConfig | ConvertTo-Json -Depth 10
try {
Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients" -Method Post -Headers $jsonHeaders -Body $jsonBody
Write-Host "✅ Client mobile créé avec succès" -ForegroundColor Green
# Récupérer l'ID du client créé
Start-Sleep -Seconds 2
$clients = Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients" -Method Get -Headers $headers
$newClient = $clients | Where-Object { $_.clientId -eq $ClientId }
if ($newClient) {
$clientUuid = $newClient.id
Write-Host "📋 Client UUID: $clientUuid" -ForegroundColor Gray
}
else {
Write-Host "⚠️ Client créé mais UUID non trouvé" -ForegroundColor Yellow
exit 1
}
}
catch {
Write-Host "❌ Erreur lors de la création du client: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
}
}
catch {
Write-Host "❌ Erreur lors de la vérification du client: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# Configurer les mappers de rôles
Write-Host "🎭 Configuration des mappers de rôles..." -ForegroundColor Yellow
$mapperHeaders = @{
Authorization = "Bearer $adminToken"
"Content-Type" = "application/json"
}
# Mapper pour l'audience
$audienceMapper = @{
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
$rolesMapper = @{
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"
}
}
try {
# Ajouter le mapper d'audience
$audienceJson = $audienceMapper | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients/$clientUuid/protocol-mappers/models" -Method Post -Headers $mapperHeaders -Body $audienceJson
# Ajouter le mapper de rôles
$rolesJson = $rolesMapper | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients/$clientUuid/protocol-mappers/models" -Method Post -Headers $mapperHeaders -Body $rolesJson
Write-Host "✅ Mappers de rôles configurés" -ForegroundColor Green
}
catch {
Write-Host "⚠️ Erreur lors de la configuration des mappers (peuvent déjà exister): $($_.Exception.Message)" -ForegroundColor Yellow
}
# Tester la configuration
Write-Host "🧪 Test de la configuration..." -ForegroundColor Yellow
$authUrl = "$KeycloakUrl/realms/$Realm/protocol/openid-connect/auth"
$tokenUrl = "$KeycloakUrl/realms/$Realm/protocol/openid-connect/token"
Write-Host "📍 URL d'autorisation: $authUrl" -ForegroundColor Gray
Write-Host "📍 URL de token: $tokenUrl" -ForegroundColor Gray
try {
$testUrl = $authUrl + "?client_id=" + $ClientId + "&response_type=code&redirect_uri=com.unionflow.mobile://login-callback"
$response = Invoke-WebRequest -Uri $testUrl -Method Get -UseBasicParsing
if ($response.StatusCode -eq 200 -or $response.StatusCode -eq 302) {
Write-Host "✅ Endpoint d'autorisation accessible" -ForegroundColor Green
}
else {
Write-Host "⚠️ Endpoint d'autorisation: HTTP $($response.StatusCode)" -ForegroundColor Yellow
}
}
catch {
Write-Host "⚠️ Test d'endpoint (normal si pas de session): $($_.Exception.Message)" -ForegroundColor Yellow
}
Write-Host "✅ Configuration testée" -ForegroundColor Green
Write-Host ""
Write-Host "🎉 Configuration terminée avec succès !" -ForegroundColor Green
Write-Host ""
Write-Host "📋 Résumé de la configuration:" -ForegroundColor Cyan
Write-Host " • Client ID: $ClientId" -ForegroundColor Gray
Write-Host " • Client UUID: $clientUuid" -ForegroundColor Gray
Write-Host " • Type: Public (PKCE activé)" -ForegroundColor Gray
Write-Host " • Redirect URI: com.unionflow.mobile://login-callback" -ForegroundColor Gray
Write-Host " • Logout URI: com.unionflow.mobile://logout-callback" -ForegroundColor Gray
Write-Host ""
Write-Host "🔗 URLs importantes:" -ForegroundColor Cyan
Write-Host " • Authorization: $authUrl" -ForegroundColor Gray
Write-Host " • Token: $tokenUrl" -ForegroundColor Gray
Write-Host " • Logout: $KeycloakUrl/realms/$Realm/protocol/openid-connect/logout" -ForegroundColor Gray
Write-Host ""
Write-Host "✅ L'application mobile peut maintenant s'authentifier avec Keycloak !" -ForegroundColor Green