Skip to content

Commit 542f53d

Browse files
committed
feat(docs): add flutterflow integration guide
add flutterflow integration guide
1 parent 1dcd90b commit 542f53d

File tree

9 files changed

+451
-1
lines changed

9 files changed

+451
-1
lines changed
Loading
Loading

docs/quick-starts/framework/flutter/_tip.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
- Flutter SDK is written based on [Dart](https://dart.dev/).
44
- The SDK dart package is available on [pub.dev](https://pub.dev/packages/logto_dart_sdk) and Logto [github repository](https://github.com/logto-io/dart).
55
- The example is written using the [Flutter material](https://flutter.dev). The sample project is available on [pub.dev](https://pub.dev/packages/logto_dart_sdk/example) and our [github repository](https://github.com/logto-io/dart).
6-
- Supported
76
- The SDK is suitable for Android and iOS platforms only.
87

98
:::
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
---
2+
slug: /quick-starts/flutter-flow
3+
sidebar_label: FlutterFlow
4+
sidebar_custom_props:
5+
description: FlutterFlow is a low code framework for building hybrid flutter apps.
6+
---
7+
8+
import flutterFlowCustomAuth from '../../assets/flutter-flow-custom-authentication.png';
9+
import flutterFlowGitHub from '../../assets/flutter-flow-github-push.png';
10+
11+
import InitCustomAuthManagerCode from './code-snippets/_flutter-flow-auth-manager-init.md';
12+
import AuthUserProviderCode from './code-snippets/_flutter-flow-auth-user-provider.md';
13+
import FlutterSecureStorageCode from './code-snippets/_flutter-secure-storage.md';
14+
import FlutterWebAuthCode from './code-snippets/_flutter-web-auth.md';
15+
16+
# Customize the FlutterFlow CustomAuthManager using Logto SDK
17+
18+
FlutterFlow has a built-in [custom authentication](https://docs.flutterflow.io/data-and-backend/custom-authentication) feature that allows you to authenticate users using your own backend. However, the build-in custom authentication flow was designed to work with a single authentication API call. If you are using a third-party Identity Provider (IdP) the authentication request can only be done using the `Resource Owner Password Credentials` grant type, which is not recommended for production use. See [Deprecated ropc grant type](https://blog.logto.io/deprecated-ropc-grant-type/) for more details.
19+
20+
A standard OpenID Connect (OIDC) authentication flow involves multiple steps, such as authorization, token exchange, and user information retrieval. To implement a standard OIDC authentication flow with a IdP like Logto, you need to customize the `CustomAuthManager` class in FlutterFlow.
21+
22+
This tutorial will show you how to customize the `CustomAuthManager` class in FlutterFlow using Logto [Flutter SDK](../flutter/README.mdx). You may take advantage of the Logto SDK for the standard OIDC authentication flow while keeping the benefits of the FlutterFlow UI builder.
23+
24+
:::tip
25+
26+
- Logto SDK package is available on [pub.dev](https://pub.dev/packages/logto_dart_sdk) and Logto [github repository](https://github.com/logto-io/dart).
27+
- The SDK is currently only suitable for Android and iOS platforms.
28+
29+
:::
30+
31+
## Prerequisites
32+
33+
- A [Logto Cloud](https://cloud.logto.io) account or a self-hosted Logto (Check out the [⚡ Get started](../../../docs/tutorials/get-started/) guide to create one if you don't have).
34+
- Create a Logto Flutter application.
35+
- A FlutterFlow project.
36+
37+
## Enable FlutterFlow custom code
38+
39+
In order to customize the `CustomAuthManager` class, you need to enable the custom code feature in FlutterFlow. Following the [Manage Custom Code In GitHub](https://docs.flutterflow.io/customizing-your-app/manage-custom-code-in-github) guide to sync your FlutterFlow project with GitHub.
40+
41+
:::note
42+
Manage custom code in GitHub is a premium feature in FlutterFlow. You need to upgrade your FlutterFlow to pro plan to enable this feature.
43+
:::
44+
45+
Once it is done, you will have three different branches under your GitHub FlutterFlow repository:
46+
47+
1. `main`: The main branch for the flutter project. You will need this branch to deploy your project.
48+
2. `flutterflow`: The branch where the `FlutterFlow` will sync the changes from the FlutterFlow editor.
49+
3. `develop`: The branch where you can modify your custom code.
50+
51+
## Create your UI in FlutterFlow
52+
53+
First, create your UI in FlutterFlow. You can follow the [FlutterFlow documentation](https://docs.flutterflow.io/) to create your UI based on your requirements. For this tutorial, for the minimum requirement, we will create two pages:
54+
55+
1. A simple home page with a login button.
56+
2. A user profile page to display user information and logout button.
57+
58+
Got to the `App Settings` -> `Authentication` page and enable the custom authentication. This will create a `CustomAuthManager` class in your FlutterFlow project.
59+
60+
<center>
61+
<img src={flutterFlowCustomAuth} alt="FlutterFlow custom authentication" />
62+
</center>
63+
64+
Once you have the UI ready, navigate to the `integrations` -> `GitHub` page and click on the `Push to Repository` button to push the changes to the `flutterflow` branch.
65+
66+
<center>
67+
<img src={flutterFlowGitHub} alt="FlutterFlow GitHub push" />
68+
</center>
69+
70+
## Customize the CustomAuthManager
71+
72+
Switch to the `develop` branch in your GitHub repository and merge the latest changes from the `flutterflow` branch. Including your UI pages, and the pre built `CustomAuthManager` class.
73+
74+
### Install Logto SDK dependency
75+
76+
Add the Logto SDK dependency to your project.
77+
78+
```bash
79+
flutter pub add logto_dart_sdk
80+
```
81+
82+
:::note
83+
Optional Http package:
84+
85+
Logto client requires a http client to make API calls. You can use the `http` package or any other http client package of your choice.
86+
87+
```bash
88+
flutter pub add http
89+
```
90+
91+
:::
92+
93+
### Update the UserProvider
94+
95+
Add the `OpenIdClaims` class to the `CustomAuthUserProvider` class to store the user information.
96+
97+
> `OpenIdClaims` class is a part of the Logto SDK, which will provide the `id_token` claims for the authenticated user.
98+
99+
<AuthUserProviderCode />
100+
101+
### Init the logto client in CustomAuthManager
102+
103+
Initialize the Logto client in the `CustomAuthManager` class.
104+
105+
<InitCustomAuthManagerCode />
106+
107+
The `initialize` method will initialize the Logto client and update the current user stream with the user authentication status persisted in the local storage.
108+
109+
> Logto SDK uses the [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage) package to store the user authentication information securely.
110+
111+
### Implement the Sign-in method
112+
113+
Call the `LogtoClient.signIn` method will initiate a standard OIDC authentication flow. The Logto Sign-In page will be opened in a webview using [flutter_web_auth](https://pub.dev/packages/flutter_web_auth).
114+
115+
```dart
116+
// lib/auth/custom_auth/custom_auth_manager.dart
117+
118+
Future<FlutterFlowAuthAuthUser?> signIn(
119+
String redirectUri,
120+
) async {
121+
await logtoClient.signIn(redirectUri);
122+
123+
var idTokenClaims = await logtoClient.idTokenClaims;
124+
125+
return _updateCurrentUser(
126+
loggedIn: idTokenClaims != null,
127+
uid: idTokenClaims?.subject,
128+
idToken: idTokenClaims,
129+
);
130+
}
131+
132+
```
133+
134+
LogtoClient will handle the authorization, token exchange, and user information retrieval steps. Once the user is authenticated, the `idTokenClaims` will be stored in the local storage.
135+
Retrieve the `idTokenClaims` from the LogtoClient and update the current user stream.
136+
137+
### Implement the Sign-out method
138+
139+
```dart
140+
// lib/auth/custom_auth/custom_auth_manager.dart
141+
142+
Future signOut() async {
143+
await logtoClient.signOut();
144+
145+
flutterFlowAuthAuthUserSubject.add(
146+
FlutterFlowAuthAuthUser(loggedIn: false),
147+
);
148+
}
149+
```
150+
151+
### Update the auth util methods
152+
153+
- Add the `authManager` getter to access the `CustomAuthManager` instance.
154+
- Add the `currentUserUid` getter to get the current user uid.
155+
- Add the `currentUserData` getter to get the current user data.
156+
- Add the `logtoClient` getter to access the Logto client instance.
157+
158+
```dart
159+
// lib/auth/custom_auth/auth_util.dart
160+
161+
import 'package:logto_dart_sdk/logto_client.dart';
162+
import 'package:logto_dart_sdk/src/modules/id_token.dart';
163+
164+
import 'custom_auth_manager.dart';
165+
166+
export 'custom_auth_manager.dart';
167+
168+
final _authManager = CustomAuthManager();
169+
CustomAuthManager get authManager => _authManager;
170+
String get currentUserUid => currentUser?.uid ?? '';
171+
OpenIdClaims? get currentUserData => currentUser?.idToken;
172+
LogtoClient get logtoClient => _authManager.logtoClient;
173+
```
174+
175+
## Integrate the custom authentication in your UI
176+
177+
### Home Page
178+
179+
Call the `authManager.signIn` method to initiate the authentication flow when the user clicks on the sign-in button.
180+
181+
> `redirectUri` is the callback URL that will be used to capture the authorization callback from the Logto sign-in page.
182+
> See the [Flutter SDK](../flutter/README.mdx#implement-sign-in) for more details on the redirectUri.
183+
184+
```dart
185+
// lib/pages/home_page/home_page_widget.dart
186+
187+
final redirectUri = 'io.logto://callback';
188+
189+
// ...
190+
191+
FFButtonWidget(
192+
onPressed: () async {
193+
GoRouter.of(context).prepareAuthEvent();
194+
195+
await authManager.signIn(redirectUri);
196+
197+
context.replaceNamed('user');
198+
},
199+
text: 'Sign In',
200+
// ...
201+
)
202+
```
203+
204+
### User Profile Page
205+
206+
Use the auth util getters to access the current user data and the Logto client instance.
207+
208+
```dart
209+
// lib/pages/user/user_widget.dart
210+
211+
import '/auth/custom_auth/auth_util.dart';
212+
213+
// ...
214+
215+
children: [
216+
Text(
217+
'User ID: $currentUserUid',
218+
),
219+
Text(
220+
'Display Name: ${currentUserData?.name}',
221+
),
222+
Text(
223+
'Username: ${currentUserData?.username}',
224+
),
225+
Text(
226+
'Email: ${currentUserData?.emailVerified ?? currentUserData?.email}',
227+
),
228+
]
229+
230+
```
231+
232+
Implement the sign-out method when the user clicks on the sign-out button.
233+
234+
```dart
235+
// lib/pages/user/user_widget.dart
236+
237+
FFButtonWidget(
238+
onPressed: () async {
239+
await authManager.signOut();
240+
241+
context.replaceNamed('HomePage');
242+
},
243+
text: 'Sign Out',
244+
// ...
245+
)
246+
```
247+
248+
## Further readings
249+
250+
Logto SDK provides more methods to interact with the Logto API. You may further customize the `CustomAuthManager` class to implement more features.
251+
252+
- [User Profile](../flutter/README.mdx#get-user-information)
253+
- [API Resources](../flutter/README.mdx#api-resources)
254+
- [Organization](../flutter/README.mdx#organization)
255+
256+
## Dependency troubleshooting
257+
258+
<FlutterSecureStorageCode />
259+
260+
<FlutterWebAuthCode />
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
```dart
2+
// lib/auth/custom_auth/custom_auth_manager.dart
3+
4+
import 'dart:async';
5+
6+
import 'package:flutter/foundation.dart';
7+
import 'package:http/http.dart' as http;
8+
import 'package:logto_dart_sdk/logto_client.dart';
9+
import 'package:logto_dart_sdk/src/modules/id_token.dart';
10+
11+
import 'custom_auth_user_provider.dart';
12+
13+
export 'custom_auth_manager.dart';
14+
15+
16+
class CustomAuthManager {
17+
late LogtoClient logtoClient;
18+
19+
final logtoConfig = const LogtoConfig(
20+
appId: '<YOUR-APP-ID>',
21+
endpoint: '<YOUR-LOGTO-ENDPOINT>');
22+
23+
24+
// ...
25+
26+
FlutterFlowAuthAuthUser? _updateCurrentUser(
27+
{bool loggedIn = false, String? uid, OpenIdClaims? idToken}) {
28+
// Update the current user stream.
29+
final updatedUser = FlutterFlowAuthAuthUser(
30+
loggedIn: loggedIn,
31+
uid: uid,
32+
idToken: idToken,
33+
);
34+
35+
flutterFlowAuthAuthUserSubject.add(updatedUser);
36+
37+
return updatedUser;
38+
}
39+
40+
Future initialize() async {
41+
logtoClient = LogtoClient(config: logtoConfig, httpClient: http.Client());
42+
43+
late OpenIdClaims? idToken;
44+
45+
try {
46+
idToken = await logtoClient.idTokenClaims;
47+
} catch (e) {
48+
if (kDebugMode) {
49+
print('Error initializing auth: $e');
50+
}
51+
}
52+
53+
_updateCurrentUser(
54+
loggedIn: idToken != null, uid: idToken?.subject, idToken: idToken);
55+
}
56+
}
57+
58+
FlutterFlowAuthAuthUser? currentUser;
59+
bool get loggedIn => currentUser?.loggedIn ?? false;
60+
61+
```
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
```dart
2+
// lib/auth/custom_auth/custom_auth_user_provider.dart
3+
4+
import 'package:logto_dart_sdk/src/modules/id_token.dart';
5+
import 'package:rxdart/rxdart.dart';
6+
7+
import 'custom_auth_manager.dart';
8+
9+
class FlutterFlowAuthAuthUser {
10+
FlutterFlowAuthAuthUser({required this.loggedIn, this.uid, this.idToken});
11+
12+
bool loggedIn;
13+
String? uid;
14+
OpenIdClaims? idToken;
15+
}
16+
17+
/// Generates a stream of the authenticated user.
18+
BehaviorSubject<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserSubject =
19+
BehaviorSubject.seeded(FlutterFlowAuthAuthUser(loggedIn: false));
20+
Stream<FlutterFlowAuthAuthUser> flutterFlowAuthAuthUserStream() =>
21+
flutterFlowAuthAuthUserSubject
22+
.asBroadcastStream()
23+
.map((user) => currentUser = user);
24+
25+
```

0 commit comments

Comments
 (0)