Skip to main content

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):

pubspec.yaml
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:

Your iOS Info.plist should look like this:

ios/Runner/Info.plist
<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

  1. Head to Manage Products
  2. Select your product
  3. If you don't have a client for your mobile app yet, create one by clicking "Create Application".
  4. 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.

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)