|
| 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 /> |
0 commit comments