Files
unionflow-server-api/configure-keycloak.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

339 lines
13 KiB
PowerShell

# Script PowerShell pour configurer Keycloak pour UnionFlow
# Auteur: UnionFlow Team
# Version: 1.0
Write-Host "🔐 Configuration automatique de Keycloak pour UnionFlow" -ForegroundColor Green
Write-Host "=======================================================" -ForegroundColor Green
# Configuration
$KEYCLOAK_URL = "http://localhost:8180"
$ADMIN_USER = "admin"
$ADMIN_PASSWORD = "admin"
$REALM_NAME = "unionflow"
$CLIENT_ID = "unionflow-server"
$CLIENT_SECRET = "unionflow-secret-2025"
# Fonction pour obtenir le token d'accès admin
function Get-AdminToken {
Write-Host "📡 Obtention du token d'administration..." -ForegroundColor Yellow
$body = @{
username = $ADMIN_USER
password = $ADMIN_PASSWORD
grant_type = "password"
client_id = "admin-cli"
}
try {
$response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
Write-Host "✅ Token obtenu avec succès" -ForegroundColor Green
return $response.access_token
}
catch {
Write-Host "❌ Erreur lors de l'obtention du token: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
}
# Fonction pour vérifier si un realm existe
function Test-RealmExists {
param($token, $realmName)
try {
$headers = @{ Authorization = "Bearer $token" }
$response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$realmName" -Method Get -Headers $headers
return $true
}
catch {
return $false
}
}
# Fonction pour créer le realm UnionFlow
function New-UnionFlowRealm {
param($token)
Write-Host "🏛️ Création du realm '$REALM_NAME'..." -ForegroundColor Yellow
$realmConfig = @{
realm = $REALM_NAME
displayName = "UnionFlow"
enabled = $true
registrationAllowed = $true
registrationEmailAsUsername = $true
rememberMe = $true
verifyEmail = $false
loginWithEmailAllowed = $true
duplicateEmailsAllowed = $false
resetPasswordAllowed = $true
editUsernameAllowed = $false
sslRequired = "external"
defaultLocale = "fr"
internationalizationEnabled = $true
supportedLocales = @("fr", "en")
} | ConvertTo-Json -Depth 10
try {
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms" -Method Post -Body $realmConfig -Headers $headers
Write-Host "✅ Realm '$REALM_NAME' créé avec succès" -ForegroundColor Green
Start-Sleep -Seconds 2
}
catch {
Write-Host "❌ Erreur lors de la création du realm: $($_.Exception.Message)" -ForegroundColor Red
throw
}
}
# Fonction pour créer le client UnionFlow Server
function New-UnionFlowClient {
param($token)
Write-Host "🔧 Création du client '$CLIENT_ID'..." -ForegroundColor Yellow
$clientConfig = @{
clientId = $CLIENT_ID
name = "UnionFlow Server API"
description = "Client pour l'API serveur UnionFlow"
enabled = $true
clientAuthenticatorType = "client-secret"
secret = $CLIENT_SECRET
protocol = "openid-connect"
publicClient = $false
serviceAccountsEnabled = $true
authorizationServicesEnabled = $true
standardFlowEnabled = $true
implicitFlowEnabled = $false
directAccessGrantsEnabled = $true
redirectUris = @("http://localhost:8080/*", "http://localhost:3000/*")
webOrigins = @("http://localhost:8080", "http://localhost:3000", "*")
fullScopeAllowed = $true
attributes = @{
"access.token.lifespan" = "3600"
"client.secret.creation.time" = [string][int64](Get-Date -UFormat %s)
}
protocolMappers = @(
@{
name = "email"
protocol = "openid-connect"
protocolMapper = "oidc-usermodel-property-mapper"
consentRequired = $false
config = @{
"userinfo.token.claim" = "true"
"user.attribute" = "email"
"id.token.claim" = "true"
"access.token.claim" = "true"
"claim.name" = "email"
"jsonType.label" = "String"
}
},
@{
name = "roles"
protocol = "openid-connect"
protocolMapper = "oidc-usermodel-realm-role-mapper"
consentRequired = $false
config = @{
"userinfo.token.claim" = "true"
"id.token.claim" = "true"
"access.token.claim" = "true"
"claim.name" = "roles"
"jsonType.label" = "String"
"multivalued" = "true"
}
}
)
} | ConvertTo-Json -Depth 10
try {
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" -Method Post -Body $clientConfig -Headers $headers
Write-Host "✅ Client '$CLIENT_ID' créé avec succès" -ForegroundColor Green
Write-Host "🔑 Secret du client: $CLIENT_SECRET" -ForegroundColor Cyan
}
catch {
Write-Host "❌ Erreur lors de la création du client: $($_.Exception.Message)" -ForegroundColor Red
throw
}
}
# Fonction pour créer les rôles
function New-UnionFlowRoles {
param($token)
Write-Host "👥 Création des rôles..." -ForegroundColor Yellow
$roles = @(
@{ name = "ADMIN"; description = "Administrateur système avec tous les droits" },
@{ name = "PRESIDENT"; description = "Président de l'union avec droits de gestion complète" },
@{ name = "SECRETAIRE"; description = "Secrétaire avec droits de gestion des membres et événements" },
@{ name = "TRESORIER"; description = "Trésorier avec droits de gestion financière" },
@{ name = "GESTIONNAIRE_MEMBRE"; description = "Gestionnaire des membres avec droits de CRUD sur les membres" },
@{ name = "ORGANISATEUR_EVENEMENT"; description = "Organisateur d'événements avec droits de gestion des événements" },
@{ name = "MEMBRE"; description = "Membre standard avec droits de consultation" }
)
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
foreach ($role in $roles) {
try {
$roleJson = $role | ConvertTo-Json
Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" -Method Post -Body $roleJson -Headers $headers
Write-Host " ✅ Rôle '$($role.name)' créé" -ForegroundColor Green
}
catch {
Write-Host " ⚠️ Rôle '$($role.name)' existe déjà ou erreur: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
# Fonction pour créer les utilisateurs de test
function New-TestUsers {
param($token)
Write-Host "👤 Création des utilisateurs de test..." -ForegroundColor Yellow
$users = @(
@{
username = "admin"
email = "admin@unionflow.dev"
firstName = "Administrateur"
lastName = "Système"
enabled = $true
emailVerified = $true
credentials = @(@{
type = "password"
value = "admin123"
temporary = $false
})
realmRoles = @("ADMIN", "PRESIDENT")
},
@{
username = "president"
email = "president@unionflow.dev"
firstName = "Jean"
lastName = "Dupont"
enabled = $true
emailVerified = $true
credentials = @(@{
type = "password"
value = "president123"
temporary = $false
})
realmRoles = @("PRESIDENT", "MEMBRE")
},
@{
username = "secretaire"
email = "secretaire@unionflow.dev"
firstName = "Marie"
lastName = "Martin"
enabled = $true
emailVerified = $true
credentials = @(@{
type = "password"
value = "secretaire123"
temporary = $false
})
realmRoles = @("SECRETAIRE", "GESTIONNAIRE_MEMBRE", "MEMBRE")
}
)
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
foreach ($user in $users) {
try {
# Créer l'utilisateur
$userJson = $user | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" -Method Post -Body $userJson -Headers $headers
Write-Host " ✅ Utilisateur '$($user.username)' créé" -ForegroundColor Green
# Attendre un peu pour que l'utilisateur soit créé
Start-Sleep -Seconds 1
# Récupérer l'ID de l'utilisateur pour assigner les rôles
$createdUser = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=$($user.username)" -Method Get -Headers $headers
if ($createdUser -and $createdUser.Count -gt 0) {
$userId = $createdUser[0].id
# Assigner les rôles
foreach ($roleName in $user.realmRoles) {
try {
$role = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles/$roleName" -Method Get -Headers $headers
$roleAssignment = @(@{
id = $role.id
name = $role.name
}) | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$userId/role-mappings/realm" -Method Post -Body $roleAssignment -Headers $headers
Write-Host " ✅ Rôle '$roleName' assigné à '$($user.username)'" -ForegroundColor Green
}
catch {
Write-Host " ⚠️ Erreur lors de l'assignation du rôle '$roleName': $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
}
catch {
Write-Host " ⚠️ Utilisateur '$($user.username)' existe déjà ou erreur: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
# Script principal
try {
# Obtenir le token d'administration
$adminToken = Get-AdminToken
# Vérifier si le realm existe déjà
if (Test-RealmExists -token $adminToken -realmName $REALM_NAME) {
Write-Host "⚠️ Le realm '$REALM_NAME' existe déjà. Suppression et recréation..." -ForegroundColor Yellow
$headers = @{ Authorization = "Bearer $adminToken" }
Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME" -Method Delete -Headers $headers
Start-Sleep -Seconds 2
}
# Créer le realm
New-UnionFlowRealm -token $adminToken
# Créer le client
New-UnionFlowClient -token $adminToken
# Créer les rôles
New-UnionFlowRoles -token $adminToken
# Créer les utilisateurs de test
New-TestUsers -token $adminToken
Write-Host ""
Write-Host "🎉 Configuration Keycloak terminée avec succès !" -ForegroundColor Green
Write-Host "=======================================" -ForegroundColor Green
Write-Host "📋 Informations de configuration :" -ForegroundColor Cyan
Write-Host " • Realm: $REALM_NAME" -ForegroundColor White
Write-Host " • Client ID: $CLIENT_ID" -ForegroundColor White
Write-Host " • Client Secret: $CLIENT_SECRET" -ForegroundColor White
Write-Host " • URL Auth Server: $KEYCLOAK_URL/realms/$REALM_NAME" -ForegroundColor White
Write-Host ""
Write-Host "👤 Utilisateurs de test créés :" -ForegroundColor Cyan
Write-Host " • admin / admin123 (ADMIN, PRESIDENT)" -ForegroundColor White
Write-Host " • president / president123 (PRESIDENT, MEMBRE)" -ForegroundColor White
Write-Host " • secretaire / secretaire123 (SECRETAIRE, GESTIONNAIRE_MEMBRE, MEMBRE)" -ForegroundColor White
Write-Host ""
Write-Host "🔧 Prochaine étape: Mettre à jour application.properties" -ForegroundColor Yellow
}
catch {
Write-Host "❌ Erreur lors de la configuration: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}