- 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
339 lines
13 KiB
PowerShell
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
|
|
}
|