Personnaliser le FlutterFlow CustomAuthManager en utilisant le Logto SDK
FlutterFlow dispose d'une fonctionnalité intégrée de custom authentication qui vous permet d'authentifier les utilisateurs en utilisant votre propre backend. Cependant, le flux d'authentification personnalisé intégré a été conçu pour fonctionner avec un seul appel API d'authentification. Si vous utilisez un fournisseur d'identité tiers (IdP), la requête d’authentification ne peut être effectuée qu'en utilisant le type de subvention Resource Owner Password Credentials
, ce qui n'est pas recommandé pour une utilisation en production. Voir Deprecated ropc grant type pour plus de détails.
Un flux d'authentification OpenID Connect (OIDC) standard implique plusieurs étapes, telles que l'Autorisation (Authorization), l'échange de jetons et la récupération d'informations utilisateur. Pour implémenter un flux d'authentification OIDC standard avec un IdP comme Logto, vous devez personnaliser la classe CustomAuthManager
dans FlutterFlow.
Ce tutoriel vous montrera comment personnaliser la classe CustomAuthManager
dans FlutterFlow en utilisant le Logto Flutter SDK. Vous pouvez tirer parti du Logto SDK pour le flux d'authentification OIDC standard tout en conservant les avantages du constructeur d'interface utilisateur FlutterFlow.
- Le package Logto SDK est disponible sur pub.dev et le dépôt GitHub de Logto.
- Le SDK est actuellement uniquement adapté aux plateformes Android et iOS.
Prérequis
- Un compte Logto Cloud ou un Logto auto-hébergé.
- Créez une application Logto Flutter.
- Un projet FlutterFlow.
Activer le code personnalisé FlutterFlow
Pour personnaliser la classe CustomAuthManager
, vous devez activer la fonctionnalité de code personnalisé dans FlutterFlow. Suivez le guide Manage Custom Code In GitHub pour synchroniser votre projet FlutterFlow avec GitHub.
Gérer le code personnalisé dans GitHub est une fonctionnalité premium dans FlutterFlow. Vous devez mettre à niveau votre FlutterFlow vers le plan pro pour activer cette fonctionnalité.
Une fois cela fait, vous aurez trois branches différentes sous votre dépôt GitHub FlutterFlow :
main
: La branche principale pour le projet flutter. Vous aurez besoin de cette branche pour déployer votre projet.flutterflow
: La branche où leFlutterFlow
synchronisera les modifications depuis l'éditeur FlutterFlow.develop
: La branche où vous pouvez modifier votre code personnalisé.
Créez votre interface utilisateur dans FlutterFlow
Tout d'abord, créez votre interface utilisateur dans FlutterFlow. Vous pouvez suivre la documentation FlutterFlow pour créer votre interface utilisateur en fonction de vos besoins. Pour ce tutoriel, pour le minimum requis, nous créerons deux pages :
- Une page d'accueil simple avec un bouton de connexion.
- Une page de profil utilisateur pour afficher les informations utilisateur et le bouton de déconnexion.
Allez à la page App Settings
-> Authentication
et activez l'authentification personnalisée. Cela créera une classe CustomAuthManager
dans votre projet FlutterFlow.
Une fois que vous avez l'interface utilisateur prête, naviguez vers la page integrations
-> GitHub
et cliquez sur le bouton Push to Repository
pour pousser les modifications vers la branche flutterflow
.
Personnaliser le CustomAuthManager
Passez à la branche develop
dans votre dépôt GitHub et fusionnez les dernières modifications de la branche flutterflow
. Y compris vos pages d'interface utilisateur et la classe CustomAuthManager
pré-construite.
Installer la dépendance Logto SDK
Ajoutez la dépendance Logto SDK à votre projet.
flutter pub add logto_dart_sdk
Package Http optionnel :
Le client Logto nécessite un client http pour effectuer des appels API. Vous pouvez utiliser le package http
ou tout autre package client http de votre choix.
flutter pub add http
Mettre à jour le UserProvider
Ajoutez la classe OpenIdClaims
à la classe CustomAuthUserProvider
pour stocker les informations utilisateur.
La classe
OpenIdClaims
fait partie du Logto SDK, qui fournira les revendicationsid_token
pour l'utilisateur authentifié.
// lib/auth/custom_auth/custom_auth_user_provider.dart
import 'package:logto_dart_sdk/src/modules/id_token.dart';
import 'package:rxdart/rxdart.dart';
import 'custom_auth_manager.dart';
class FlutterFlowAuthAuthUser {
FlutterFlowAuthAuthUser({required this.loggedIn, this.uid, this.idToken});
bool loggedIn;
String? uid;
OpenIdClaims? idToken;
}
/// Génère un flux de l'utilisateur authentifié.
BehaviorSubject<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserSubject =
BehaviorSubject.seeded(FlutterFlowAuthAuthUser(loggedIn: false));
Stream<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserStream() =>
flutterFlowAuthAuthUserSubject
.asBroadcastStream()
.map((user) => currentUser = user);
Initialiser le client logto dans CustomAuthManager
Initialisez le client Logto dans la classe CustomAuthManager
.
// lib/auth/custom_auth/custom_auth_manager.dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:logto_dart_sdk/logto_client.dart';
import 'package:logto_dart_sdk/src/modules/id_token.dart';
import 'custom_auth_user_provider.dart';
export 'custom_auth_manager.dart';
class CustomAuthManager {
late LogtoClient logtoClient;
final logtoConfig = const LogtoConfig(
appId: '<YOUR-APP-ID>',
endpoint: '<YOUR-LOGTO-ENDPOINT>');
// ...
FlutterFlowAuthAuthUser? _updateCurrentUser(
{bool loggedIn = false, String? uid, OpenIdClaims? idToken}) {
// Mettre à jour le flux de l'utilisateur actuel.
final updatedUser = FlutterFlowAuthAuthUser(
loggedIn: loggedIn,
uid: uid,
idToken: idToken,
);
flutterFlowAuthAuthUserSubject.add(updatedUser);
return updatedUser;
}
Future initialize() async {
logtoClient = LogtoClient(config: logtoConfig, httpClient: http.Client());
late OpenIdClaims? idToken;
try {
idToken = await logtoClient.idTokenClaims;
} catch (e) {
if (kDebugMode) {
print('Erreur lors de l\'initialisation de l\'authentification : $e');
}
}
_updateCurrentUser(
loggedIn: idToken != null, uid: idToken?.subject, idToken: idToken);
}
}
FlutterFlowAuthAuthUser? currentUser;
bool get loggedIn => currentUser?.loggedIn ?? false;
La méthode initialize
initialisera le client Logto et mettra à jour le flux utilisateur actuel avec le statut d'authentification utilisateur persistant dans le stockage local.
Le Logto SDK utilise le package flutter_secure_storage pour stocker les informations d'authentification utilisateur en toute sécurité.
Implémenter la méthode de connexion
Appeler la méthode LogtoClient.signIn
initiera un flux d'authentification OIDC standard. La page de connexion Logto sera ouverte dans une webview en utilisant flutter_web_auth.
// lib/auth/custom_auth/custom_auth_manager.dart
Future<FlutterFlowAuthAuthUser?> signIn(
String redirectUri,
) async {
await logtoClient.signIn(redirectUri);
var idTokenClaims = await logtoClient.idTokenClaims;
return _updateCurrentUser(
loggedIn: idTokenClaims != null,
uid: idTokenClaims?.subject,
idToken: idTokenClaims,
);
}
LogtoClient gérera les étapes d'Autorisation (Authorization), d'échange de jetons et de récupération d'informations utilisateur. Une fois l'utilisateur authentifié, les idTokenClaims
seront stockées dans le stockage local.
Récupérez les idTokenClaims
du LogtoClient et mettez à jour le flux utilisateur actuel.
Implémenter la méthode de déconnexion
// lib/auth/custom_auth/custom_auth_manager.dart
Future signOut() async {
await logtoClient.signOut();
flutterFlowAuthAuthUserSubject.add(
FlutterFlowAuthAuthUser(loggedIn: false),
);
}
Mettre à jour les méthodes utilitaires d'authentification
- Ajoutez le getter
authManager
pour accéder à l'instanceCustomAuthManager
. - Ajoutez le getter
currentUserUid
pour obtenir l'uid de l'utilisateur actuel. - Ajoutez le getter
currentUserData
pour obtenir les données de l'utilisateur actuel. - Ajoutez le getter
logtoClient
pour accéder à l'instance du client Logto.
// lib/auth/custom_auth/auth_util.dart
import 'package:logto_dart_sdk/logto_client.dart';
import 'package:logto_dart_sdk/src/modules/id_token.dart';
import 'custom_auth_manager.dart';
export 'custom_auth_manager.dart';
final _authManager = CustomAuthManager();
CustomAuthManager get authManager => _authManager;
String get currentUserUid => currentUser?.uid ?? '';
OpenIdClaims? get currentUserData => currentUser?.idToken;
LogtoClient get logtoClient => _authManager.logtoClient;
Intégrer l'authentification personnalisée dans votre interface utilisateur
Page d'accueil
Appelez la méthode authManager.signIn
pour initier le flux d'authentification lorsque l'utilisateur clique sur le bouton de connexion.
redirectUri
est l'URL de rappel qui sera utilisée pour capturer le rappel d'autorisation depuis la page de connexion Logto. Voir le Flutter SDK pour plus de détails sur le redirectUri.
// lib/pages/home_page/home_page_widget.dart
final redirectUri = 'io.logto://callback';
// ...
FFButtonWidget(
onPressed: () async {
GoRouter.of(context).prepareAuthEvent();
await authManager.signIn(redirectUri);
context.replaceNamed('user');
},
text: 'Sign In',
// ...
)
Page de profil utilisateur
Utilisez les getters utilitaires d'authentification pour accéder aux données de l'utilisateur actuel et à l'instance du client Logto.
// lib/pages/user/user_widget.dart
import '/auth/custom_auth/auth_util.dart';
// ...
children: [
Text(
'User ID: $currentUserUid',
),
Text(
'Display Name: ${currentUserData?.name}',
),
Text(
'Username: ${currentUserData?.username}',
),
Text(
'Email: ${currentUserData?.emailVerified ?? currentUserData?.email}',
),
]
Implémentez la méthode de déconnexion lorsque l'utilisateur clique sur le bouton de déconnexion.
// lib/pages/user/user_widget.dart
FFButtonWidget(
onPressed: () async {
await authManager.signOut();
context.replaceNamed('HomePage');
},
text: 'Sign Out',
// ...
)
Lectures complémentaires
Le Logto SDK fournit plus de méthodes pour interagir avec l'API Logto. Vous pouvez personnaliser davantage la classe CustomAuthManager
pour implémenter plus de fonctionnalités.
Dépannage des dépendances
flutter_secure_storage
Nous utilisons flutter_secure_storage pour implémenter le stockage sécurisé persistant de jetons multiplateforme. Sous le capot :
- Keychain est utilisé pour iOS
- Le chiffrement AES est utilisé pour Android.
Configurer la version Android :
Dans [project]/android/app/build.gradle, définissez minSdkVersion sur >= 18.
android {
...
defaultConfig {
...
minSdkVersion 18
...
}
}
Désactiver la sauvegarde automatique :
Par défaut, Android sauvegarde les données sur Google Drive. Cela peut provoquer l'exception java.security.InvalidKeyException:Failed to unwrap key.
Pour éviter cela, vous pouvez désactiver la sauvegarde automatique pour votre application ou exclure sharedprefs de FlutterSecureStorage.
-
Pour désactiver la sauvegarde automatique, allez dans le fichier manifeste de votre application et définissez la valeur booléenne android:allowBackup :
<manifest ... >
...
<application
android:allowBackup="false"
android:fullBackupContent="false"
...
>
...
</application>
</manifest> -
Exclure sharedprefs de FlutterSecureStorage.
Si vous devez activer android:fullBackupContent pour votre application. Configurez une règle de sauvegarde pour exclure les prefs utilisées par le plugin :
<application ...
android:fullBackupContent="@xml/backup_rules">
</application><?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>Veuillez consulter flutter_secure_storage pour plus de détails.
flutter_web_auth
flutter_web_auth est utilisé derrière le SDK flutter de Logto. Nous nous appuyons sur son interface d'interaction basée sur webview pour ouvrir les pages d'Autorisation (Authorization) de Logto.
Ce plugin utilise ASWebAuthenticationSession sur iOS 12+ et macOS 10.15+, SFAuthenticationSession sur iOS 11, Chrome Custom Tabs sur Android et ouvre une nouvelle fenêtre sur le Web. Vous pouvez le construire avec iOS 8+, mais il est actuellement uniquement pris en charge par iOS 11 ou supérieur.
Enregistrer l'URL de rappel sur Android
Afin de capturer l'URL de rappel depuis la page de connexion de Logto, vous devrez enregistrer votre redirectUri de connexion dans le fichier AndroidManifest.xml.
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="io.logto"/>
</intent-filter>
</activity>