Flutter
Implementing the identity service in your Flutter App is easier than you might think. Follow this guide to get started in no time.
Make sure your flutter development environment is up to date and working. For a quick start visit flutter.dev.
info
This document is focused on the mobile authentication flow. There is also a custom PKCE implementation in the identity boilerplate for desktop: Boilerplate
Getting started
With Flutter:
flutter pub add flutter_appauth
This will add a line like this to your package's pubspec.yaml
(and run an implicit flutter pub get):
dependencies:
flutter_appauth: ^2.4.1
Alternatively add the dependency manually. Make sure to use the latest version. 2.4.1 was current as of March 22, 2022.
Configuration
For the SSO App to return the authentication result to the app a custom url scheme is needed. The AppAuth library expects you to define this yourself and replace it in relevant parts of this document.
Example for a custom scheme: com.your.awesome-app://
.
caution
Your scheme must consist of a sequence of characters beginning with a letter and followed by any combination of letters, digits, plus (+
), period (.
), or hyphen (-
). (RFC 3986: Uniform Resource Identifier).
Next we follow the instructions of the flutter app auth package:
- Android instructions (https://pub.dev/packages/flutter_appauth#android-setup)
- iOS instructions (https://pub.dev/packages/flutter_appauth#ios-setup)
Your iOS Info.plist
should look like this:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.your.awesome-app</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.your.awesome-app://login-callback</string>
</array>
</dict>
</array>
Update the Callback URL
- Head to Manage Products
- Select your product
- If you don't have a client for your mobile app yet, create one by clicking "Create Application".
- Navigate to your client and add your custom scheme to the Callback URLs.
Let's get coding!
info
For the full source code, a service wrapping this logic and handling token refreshing check the example repository.
To trigger a sign in we use the AppAuth login method. This will prompt the user to sign in by opening a webview that serves the login page of the identity service
import 'package:flutter_appauth/flutter_appauth.dart';
We create a new instance of the FlutterAppAuth class that handles the OAuth flow.
final FlutterAppAuth appAuth = FlutterAppAuth();
To open the login dialog we can call the following.
- The client id you can obtain from the identity management portal.
- The redirect url is the custom url scheme specified above (e.g.
com.your.awesome-app://login-callback
) - The discovery URL is also called "openid-configuration" (https://login.emddigital.com/.well-known/openid-configuration)
final AuthorizationTokenResponse? result = await appAuth.authorizeAndExchangeCode(
AuthorizationTokenRequest(
clientId,
redirectUrl,
discoveryUrl: discoveryUrl,
scopes: ["openid", "email"],
),
);
This will return a result that contains several tokens.
String? accessToken = response.accessToken;
String? refreshToken = response.refreshToken;
String? idToken = response.idToken;
It is recommended to save the refresh and id token to keep the user signed in. (e.g. using flutter_secure_storage)
If you need to refresh the access token you can do so by calling:
final TokenResponse? result = await appAuth.token(
TokenRequest(
clientId, redirectUrl,
discoveryUrl: discoveryUrl,
refreshToken: refreshToken,
scopes: scopes)
);
You can calculate when this is necessary by looking at the date provided in the token.
TokenResponse result; // From .login or .token
result.accessTokenExpirationDateTime
Security
Store the credentials like the refresh token in a save place (e.g. using flutter_secure_storage persisting to keychain or secure preferences on android).
iOS Appstore compliance
In some cases Apple will require you to provide a "Sign in with Apple" strategy for your app. (https://developer.apple.com/app-store/review/guidelines/, Section 4.8)