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

273 lines
10 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
# Ce script configure le client unionflow-mobile dans Keycloak
param(
[string]$KeycloakUrl = "http://192.168.1.11:8180",
[string]$Realm = "unionflow",
[string]$AdminUser = "admin",
[string]$AdminPassword = "admin",
[string]$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 ""
# Fonction pour obtenir le token d'administration
function Get-AdminToken {
Write-Host "🔑 Obtention du token d'administration..." -ForegroundColor Yellow
$body = @{
username = $AdminUser
password = $AdminPassword
grant_type = "password"
client_id = "admin-cli"
}
try {
$response = Invoke-RestMethod -Uri "$KeycloakUrl/realms/master/protocol/openid-connect/token" -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
Write-Host "✅ Token d'administration obtenu" -ForegroundColor Green
return $response.access_token
}
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
}
}
# Fonction pour vérifier si le client existe déjà
function Test-ClientExists {
param([string]$Token)
Write-Host "🔍 Vérification de l'existence du client $ClientId..." -ForegroundColor Yellow
try {
$headers = @{ Authorization = "Bearer $Token" }
$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
return $existingClient.id
}
else {
Write-Host " Client $ClientId n'existe pas, création nécessaire" -ForegroundColor Blue
return $null
}
}
catch {
Write-Host "❌ Erreur lors de la vérification du client: $($_.Exception.Message)" -ForegroundColor Red
return $null
}
}
# Fonction pour créer le client mobile
function New-MobileClient {
param([string]$Token)
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 = @()
}
try {
$headers = @{
Authorization = "Bearer $Token"
"Content-Type" = "application/json"
}
$jsonBody = $clientConfig | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients" -Method Post -Headers $headers -Body $jsonBody
Write-Host "✅ Client mobile créé avec succès" -ForegroundColor Green
# Récupérer l'ID du client créé
Start-Sleep -Seconds 1
$clients = Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/clients" -Method Get -Headers $headers
$newClient = $clients | Where-Object { $_.clientId -eq $ClientId }
if ($newClient) {
Write-Host "📋 Client UUID: $($newClient.id)" -ForegroundColor Gray
return $newClient.id
}
else {
Write-Host "⚠️ Client créé mais UUID non trouvé" -ForegroundColor Yellow
return $null
}
}
catch {
Write-Host "❌ Erreur lors de la création du client: $($_.Exception.Message)" -ForegroundColor Red
return $null
}
}
# Fonction pour configurer les mappers de rôles
function Set-RoleMappers {
param([string]$Token, [string]$ClientUuid)
Write-Host "🎭 Configuration des mappers de rôles..." -ForegroundColor Yellow
$headers = @{
Authorization = "Bearer $Token"
"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 $headers -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 $headers -Body $rolesJson
Write-Host "✅ Mappers de rôles configurés" -ForegroundColor Green
}
catch {
Write-Host "⚠️ Erreur lors de la configuration des mappers: $($_.Exception.Message)" -ForegroundColor Yellow
Write-Host "Les mappers peuvent déjà exister" -ForegroundColor Gray
}
}
# Fonction pour tester la configuration
function Test-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: $($_.Exception.Message)" -ForegroundColor Yellow
}
Write-Host "✅ Configuration testée" -ForegroundColor Green
}
# Fonction principale
function Main {
Write-Host "🚀 Début de la configuration automatique..." -ForegroundColor Cyan
Write-Host ""
# Obtenir le token d'administration
$adminToken = Get-AdminToken
# Vérifier si le client existe déjà
$existingClientUuid = Test-ClientExists -Token $adminToken
if ($existingClientUuid) {
Write-Host " Client existant trouvé, utilisation de l'UUID existant..." -ForegroundColor Blue
$clientUuid = $existingClientUuid
}
else {
# Créer le client mobile
$clientUuid = New-MobileClient -Token $adminToken
if (-not $clientUuid) {
Write-Host "❌ Échec de la création du client" -ForegroundColor Red
exit 1
}
}
# Configurer les mappers de rôles
Set-RoleMappers -Token $adminToken -ClientUuid $clientUuid
# Tester la configuration
Test-Configuration
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: $KeycloakUrl/realms/$Realm/protocol/openid-connect/auth" -ForegroundColor Gray
Write-Host " • Token: $KeycloakUrl/realms/$Realm/protocol/openid-connect/token" -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
}
# Exécuter le script principal
Main