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
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../features/auth/presentation/pages/keycloak_login_page.dart';
|
||||
import '../../../features/navigation/presentation/pages/main_navigation.dart';
|
||||
import '../services/keycloak_webview_auth_service.dart';
|
||||
import '../models/auth_state.dart';
|
||||
import '../../di/injection.dart';
|
||||
|
||||
/// Wrapper qui gère l'authentification et le routage
|
||||
class AuthWrapper extends StatefulWidget {
|
||||
const AuthWrapper({super.key});
|
||||
|
||||
@override
|
||||
State<AuthWrapper> createState() => _AuthWrapperState();
|
||||
}
|
||||
|
||||
class _AuthWrapperState extends State<AuthWrapper> {
|
||||
late KeycloakWebViewAuthService _authService;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_authService = getIt<KeycloakWebViewAuthService>();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<AuthState>(
|
||||
stream: _authService.authStateStream,
|
||||
initialData: _authService.currentState,
|
||||
builder: (context, snapshot) {
|
||||
final authState = snapshot.data ?? const AuthState.unknown();
|
||||
|
||||
// Affichage de l'écran de chargement pendant la vérification
|
||||
if (authState.isChecking) {
|
||||
return const Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text('Vérification de l\'authentification...'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Si l'utilisateur est authentifié, afficher l'application principale
|
||||
if (authState.isAuthenticated) {
|
||||
return const MainNavigation();
|
||||
}
|
||||
|
||||
// Sinon, afficher la page de connexion
|
||||
return const KeycloakLoginPage();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user