Flutter

This quickstart guide serves as an integration example for our trusted partners so that you will be able to test and/or evaluate LoginID’s authentication service for your own needs.

Steps to follow

Useful APIs

  1. Login

  2. Logout

Create your client API keys

The first step to onboard yourself with LoginID is to create your client credentials. This allows your servers to call LoginID services in an authenticated fashion.

Install LoginID SDK for your build environment

Our Flutter SDK is currently support flutter version >= 1.12.13+hotfix.5. Here we'll show how to add flutter login SDK to your environment. You will need additional setups for iOS and Android described below.

This SDK will work on Android devices running API 24+ (Nougat) and Apple devices running iOS 10+.

Download Flutter SDK

  • Download the API from LoginID developer's console

  • Add a flutter login SDK to your pubspec.yaml dependencies

dependencies:
flutter:
sdk: flutter
flutterpluginfidologinapi:
path: /path/to/download/api

Additional Setup for Android Build

Update your project's AndroidManifest.xml file to include the USE_FINGERPRINT permissions:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
<manifest>

This plugin requires the use of FragmentActivity instead of Activity. You need to change your MainActivity to use FlutterFragmentActivity instead of FlutterActivity.

Override of configureFlutterEngine is required as of Flutter version (1.12 - 1.17). However, this may not be required in our future updates.

Java
Kotlin
Java
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.embedding.engine.FlutterEngine;
public class MainActivity extends FlutterFragmentActivity {
@Override
public void configureFlutterEngine(FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
}
Kotlin
import androidx.annotation.NonNull
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterFragmentActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
}
}

The following fix is required for devices running Android API <28. You will received the error: You need to use a Theme.AppCompat theme (or descendant) with this activity while using default flutter LaunchTheme. (found in flutter version 1.12 - 1.17)

To change default LaunchTheme go to your flutter app android/app/src/main/res/values/styles.xml

Change from:

<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">

To dark theme biometric prompt:

<style name="LaunchTheme" parent="Theme.AppCompat.NoActionBar">

or to light theme biometric prompt:

<style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar">

Additional Setup for iOS Build

For iOS build, add NSFaceIDUsageDescription (Privacy - Face ID Usage Description) key/value to app's info.plist. You will find the info.plist file in your project ios/Runner of your Flutter application.

This is a privacy description for accessing a FaceID features on iOS. On devices with FaceID like iPhoneX+, users will be prompted with permission dialog based on this description about FaceID usage for the app.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSFaceIDUsageDescription</key>
<string>Privacy description regarding to usage of FaceID feature</string>
...
...
</plist>

Getting started with LoginID API SDK:

Set up API with clientId and baseURL

Import LoginID SDK:

import 'package:flutterpluginfidologinapi/flutterpluginfidologinapi.dart';

Configure clientId and baseURL obtained from the developer console. You should configure FIDO login at the init state of your flutter application.

// example app
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
initializeState();
}
// Fido login api plugin are asynchronous, so we initialize in an async method.
Future<void> initializeState() async {
String clientId = "032690b3-9bc4-4602-87c1-60c1fae782f2";
String baseURL = "https://060ce487-b934-43d0-a925-b66e80c7532f.";
await FPLoginApi.configure(clientId,baseURL);
// ...
// ...
}
// ...
// ...
}

Getting user Account Information

Here is a set of functions for retrieving user information and login status.

Check if the user has an existing registered account:

// return true or false
bool hasAccount = await FPLoginApi.hasAccount();

Get the current username:

// return username in string value
String username = await FPLoginApi.getCurrentUsername();

Check if the user has an active login session:

// return true or false
bool isLoggedIn = await FPLoginApi.isLoggedIn();

Get current access token which is the latest JWT token returned by the server after a successful registered or verified API called:

// return jwt in string value
String token = await FPLoginApi.getCurrentToken();

Here is an example of how to use the above functionalities:

if(await FPLoginApi.hasAccount()){
// get current username example
String username = await FPLoginApi.getCurrentUsername();
// check if user has active login session
if(await FPLoginApi.isLoggedIn()){
// get current token example
String token = await FPLoginApi.getCurrentToken();
...
} else {
//present login option here
...
}
...
} else {
// user has no account so can setup register user logic here
...
}

Register user account

For an overview of LoginID registration flow of our API, please see:

Register an Account with Username Specified

This API allows users to create new credentials with usernames via a FIDO2 registration. Having username registered will allow users to login with usernames from multiple platforms.

// Here is an example register handler when someone click on register button
Future<void> _registerButtonHandler (BuildContext context) async {
try{
String username = usernameController.text.toString();
final RegisterResponse response = await FPLoginApi.registerWithUsername(username);
if(response.success == true){
// example handling success register case
print ('Success: ${response.jwt}');
...
...
} else {
// display error message as snackbar message
print ('Error: ${response.errorMessage}' );
...
...
}
} on PlatformException catch(e){
print (e.message);
// handle error here ...
}
}

Login or Re-authenticate a Registered Account

Once the user has successfully registered, LoginID will assign a JWT token to the response field. The token has a timestamp associate with it. You can ask the user to re-authenticate at any time afterward based on your business logic or if the token expired.

Login to previously registered account:

// Here is an example login handler when someone click on login button
Future<void> _loginButtonHandler (BuildContext context) async {
try{
final LoginResponse response = await FPLoginApi.login();
if(response.success == true){
// example handling success login case
print ('Success: ${response.jwt}');
...
...
} else {
//display error message
print ('Error: ${response.errorMessage}' );
...
...
}
} on PlatformException catch(e){
print (e.message);
}
}

Login with username specified

This API allows you to signed into a specific account. Use this in a scenario where you want to support multiple registered accounts on the same device.

// Here is an example login handler when someone click on login button
Future<void> _loginButtonHandler (BuildContext context) async {
try{
String username = usernameController.text.toString();
final LoginResponse response = await FPLoginApi.loginWithUsername(username);
if(response.success == true){
// example handling success login case
print ('Success: ${response.jwt}');
...
...
} else {
//display error message
print ('Error: ${response.errorMessage}' );
...
...
}
} on PlatformException catch(e){
print (e.message);
}
}

Logout

Call logout operation to invalidate the current access token.

// logout handler when clicking on logout button
Future<void> _logout(BuildContext context) async{
await FPLoginApi.logout();
Navigator.push(context,MaterialPageRoute(builder: (context) => RegisterWidget()));
}