Personalizar o FlutterFlow CustomAuthManager usando Logto SDK
FlutterFlow possui um recurso de autenticação personalizada embutido que permite autenticar usuários usando seu próprio backend. No entanto, o fluxo de autenticação personalizada embutido foi projetado para funcionar com uma única chamada de API de autenticação. Se você estiver usando um Provedor de Identidade (IdP) de terceiros, a solicitação de autenticação só pode ser feita usando o tipo de concessão Resource Owner Password Credentials
, o que não é recomendado para uso em produção. Veja Tipo de concessão ropc obsoleto para mais detalhes.
Um fluxo de autenticação padrão OpenID Connect (OIDC) envolve várias etapas, como autorização, troca de tokens e recuperação de informações do usuário. Para implementar um fluxo de autenticação OIDC padrão com um IdP como Logto, você precisa personalizar a classe CustomAuthManager
no FlutterFlow.
Este tutorial mostrará como personalizar a classe CustomAuthManager
no FlutterFlow usando o Logto Flutter SDK. Você pode aproveitar o Logto SDK para o fluxo de autenticação OIDC padrão enquanto mantém os benefícios do construtor de interface do FlutterFlow.
- O pacote Logto SDK está disponível no pub.dev e no repositório github do Logto.
- O SDK atualmente é adequado apenas para plataformas Android e iOS.
Pré-requisitos
- Uma conta Logto Cloud ou um Logto auto-hospedado.
- Criar um aplicativo Logto Flutter.
- Um projeto FlutterFlow.
Habilitar código personalizado no FlutterFlow
Para personalizar a classe CustomAuthManager
, você precisa habilitar o recurso de código personalizado no FlutterFlow. Siga o guia Gerenciar Código Personalizado no GitHub para sincronizar seu projeto FlutterFlow com o GitHub.
Gerenciar código personalizado no GitHub é um recurso premium no FlutterFlow. Você precisa atualizar seu FlutterFlow para o plano pro para habilitar esse recurso.
Uma vez feito isso, você terá três branches diferentes no seu repositório GitHub FlutterFlow:
main
: A branch principal para o projeto flutter. Você precisará dessa branch para implantar seu projeto.flutterflow
: A branch onde oFlutterFlow
sincronizará as alterações do editor FlutterFlow.develop
: A branch onde você pode modificar seu código personalizado.
Crie sua interface no FlutterFlow
Primeiro, crie sua interface no FlutterFlow. Você pode seguir a documentação do FlutterFlow para criar sua interface com base em seus requisitos. Para este tutorial, como requisito mínimo, criaremos duas páginas:
- Uma página inicial simples com um botão de login.
- Uma página de perfil do usuário para exibir informações do usuário e botão de logout.
Vá para App Settings
-> página Authentication
e habilite a autenticação personalizada. Isso criará uma classe CustomAuthManager
no seu projeto FlutterFlow.
Uma vez que você tenha a interface pronta, navegue até integrations
-> página GitHub
e clique no botão Push to Repository
para enviar as alterações para a branch flutterflow
.
Personalizar o CustomAuthManager
Mude para a branch develop
no seu repositório GitHub e mescle as últimas alterações da branch flutterflow
. Incluindo suas páginas de interface e a classe CustomAuthManager
pré-construída.
Instalar a dependência do Logto SDK
Adicione a dependência do Logto SDK ao seu projeto.
flutter pub add logto_dart_sdk
Pacote Http opcional:
O cliente Logto requer um cliente http para fazer chamadas de API. Você pode usar o pacote http
ou qualquer outro pacote de cliente http de sua escolha.
flutter pub add http
Atualizar o UserProvider
Adicione a classe OpenIdClaims
à classe CustomAuthUserProvider
para armazenar as informações do usuário.
A classe
OpenIdClaims
faz parte do Logto SDK, que fornecerá as reivindicações doid_token
para o usuário autenticado.
// 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;
}
/// Gera um fluxo do usuário autenticado.
BehaviorSubject<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserSubject =
BehaviorSubject.seeded(FlutterFlowAuthAuthUser(loggedIn: false));
Stream<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserStream() =>
flutterFlowAuthAuthUserSubject
.asBroadcastStream()
.map((user) => currentUser = user);
Inicializar o cliente logto no CustomAuthManager
Inicialize o cliente Logto na 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}) {
// Atualiza o fluxo do usuário atual.
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('Erro ao inicializar a autenticação: $e');
}
}
_updateCurrentUser(
loggedIn: idToken != null, uid: idToken?.subject, idToken: idToken);
}
}
FlutterFlowAuthAuthUser? currentUser;
bool get loggedIn => currentUser?.loggedIn ?? false;
O método initialize
inicializará o cliente Logto e atualizará o fluxo de usuário atual com o status de autenticação do usuário persistido no armazenamento local.
O Logto SDK usa o pacote flutter_secure_storage para armazenar as informações de autenticação do usuário de forma segura.
Implementar o método de login
Chame o método LogtoClient.signIn
para iniciar um fluxo de autenticação OIDC padrão. A página de login do Logto será aberta em uma webview usando 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,
);
}
O LogtoClient lidará com as etapas de autorização, troca de tokens e recuperação de informações do usuário. Uma vez que o usuário é autenticado, as idTokenClaims
serão armazenadas no armazenamento local.
Recupere as idTokenClaims
do LogtoClient e atualize o fluxo de usuário atual.
Implementar o método de logout
// lib/auth/custom_auth/custom_auth_manager.dart
Future signOut() async {
await logtoClient.signOut();
flutterFlowAuthAuthUserSubject.add(
FlutterFlowAuthAuthUser(loggedIn: false),
);
}
Atualizar os métodos utilitários de autenticação
- Adicione o getter
authManager
para acessar a instância doCustomAuthManager
. - Adicione o getter
currentUserUid
para obter o uid do usuário atual. - Adicione o getter
currentUserData
para obter os dados do usuário atual. - Adicione o getter
logtoClient
para acessar a instância do cliente 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;
Integrar a autenticação personalizada na sua interface
Página Inicial
Chame o método authManager.signIn
para iniciar o fluxo de autenticação quando o usuário clicar no botão de login.
redirectUri
é a URL de callback que será usada para capturar o callback de autorização da página de login do Logto. Veja o Flutter SDK para mais detalhes sobre o 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',
// ...
)
Página de Perfil do Usuário
Use os getters utilitários de autenticação para acessar os dados do usuário atual e a instância do cliente 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}',
),
]
Implemente o método de logout quando o usuário clicar no botão de logout.
// lib/pages/user/user_widget.dart
FFButtonWidget(
onPressed: () async {
await authManager.signOut();
context.replaceNamed('HomePage');
},
text: 'Sign Out',
// ...
)
Leituras adicionais
O Logto SDK fornece mais métodos para interagir com a API do Logto. Você pode personalizar ainda mais a classe CustomAuthManager
para implementar mais recursos.
Solução de problemas de dependência
flutter_secure_storage
Usamos flutter_secure_storage para implementar o armazenamento seguro persistente de tokens em várias plataformas. Sob o capô:
- Keychain é usado para iOS
- Criptografia AES é usada para Android.
Configurar versão do Android:
Em [project]/android/app/build.gradle defina minSdkVersion para >= 18.
android {
...
defaultConfig {
...
minSdkVersion 18
...
}
}
Desativar backup automático:
Por padrão, o Android faz backup dos dados no Google Drive. Isso pode causar a exceção java.security.InvalidKeyException:Failed to unwrap key.
Para evitar isso, você pode desativar o backup automático para seu aplicativo ou excluir sharedprefs do FlutterSecureStorage.
-
Para desativar o backup automático, vá para o arquivo de manifesto do seu aplicativo e defina o valor booleano android:allowBackup:
<manifest ... >
...
<application
android:allowBackup="false"
android:fullBackupContent="false"
...
>
...
</application>
</manifest> -
Excluir sharedprefs do FlutterSecureStorage.
Se você precisar habilitar o android:fullBackupContent para seu aplicativo. Configure uma regra de backup para excluir as prefs usadas pelo 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>Por favor, verifique flutter_secure_storage para mais detalhes.
flutter_web_auth
flutter_web_auth é usado por trás do SDK flutter do Logto. Nós confiamos em sua interface de interação baseada em webview para abrir as páginas de autorização do Logto.
Este plugin usa ASWebAuthenticationSession no iOS 12+ e macOS 10.15+, SFAuthenticationSession no iOS 11, Chrome Custom Tabs no Android e abre uma nova janela na Web. Você pode construí-lo com iOS 8+, mas atualmente é suportado apenas por iOS 11 ou superior.
Registrar a URL de callback no Android
Para capturar a URL de callback da página de login do Logto, você precisará registrar seu redirectUri de login no 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>