Skip to main content

Flutter Quickstart

Use this guide to add ThunderID authentication to a Flutter application using the thunderid_flutter package.

What You Will Learn

  • Create a new Flutter project
  • Install the thunderid_flutter package
  • Add working sign-in and sign-out using Flutter widgets
  • Display the signed-in user's name

Prerequisites

  • About 20 minutes
  • Flutter 3.16+ and Dart 3.2+
  • iOS 16+ or Android API 26+ target device or simulator
1

Run ThunderID

Start a local ThunderID instance. Pick the method that works best for you:

$npx thunderid

Requires Node.js 18+

Full install guide →

Once it's running, the console is available at https://localhost:8090/console.

2

Create an Application

  1. Sign in to the Console.

    Test User

    If you used the default setup, sign in to the Console as admin with the password generated during setup and printed to the setup output (unless you supplied your own).

  2. Navigate to Applications.

  3. Click Add Application.

  4. From the Choose a type page, select Flutter.

  5. Enter a name (e.g. My Flutter App).

  6. Select how you want to sign in users (e.g., email/password, social login, etc.).

  7. Select Theme settings.

  8. Leave Sign-In Approach set to Bring Your Own UI (the default for Flutter applications).

  9. Click Create.

warning

Copy the Application ID from the General tab, under Quick Copy. You'll need it when configuring the SDK.

  1. Open the Advanced Settings tab, turn on Dev Mode under Platform Attestation, then click Save.
Platform attestation

Mobile applications prove their binary identity before starting a sign-in flow. If platform attestation is not configured and Dev Mode is off, sign-in fails with FES-1016, Attestation not configured. Dev Mode is a bypass for local development; configure platform attestation for production.

3

Create a Flutter App

Create a new Flutter project:

flutter create my_flutter_app
cd my_flutter_app
note

If you already have an existing Flutter project, skip this step.

4

Install thunderid_flutter Package

Add the package, which writes a version constraint to your pubspec.yaml and records the resolved version in pubspec.lock:

flutter pub add thunderid_flutter
5

Configure the Platforms

The flutter create template does not include the configuration the plugin needs.

For Android, add the JitPack repository, which hosts the plugin's native dependency:

android/build.gradle.kts
allprojects {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}

Then replace the template's minSdk = flutter.minSdkVersion with 26, which the plugin requires:

android/app/build.gradle.kts
android {
defaultConfig {
minSdk = 26
}
}

For iOS, build with CocoaPods rather than Swift Package Manager. This also generates ios/Podfile, which the next step edits:

flutter config --no-enable-swift-package-manager
flutter pub get

Then set the platform to 16 and add the native SDK as a Git pod:

ios/Podfile
platform :ios, '16.0'

# ...

target 'Runner' do
use_frameworks!

pod 'ThunderID', :git => 'https://github.com/thunder-id/ios-sdks', :branch => 'main'

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
6

Initialize the SDK

Wrap your root widget with ThunderIDProvider in lib/main.dart:

lib/main.dart
import 'package:flutter/material.dart';
import 'package:thunderid_flutter/thunderid_flutter.dart';
import 'root_screen.dart';

void main() {
runApp(
ThunderIDProvider(
config: ThunderIDConfig(
baseUrl: 'https://localhost:8090',
scopes: const ['openid', 'profile', 'email'],
applicationId: '<your-application-id>',
),
child: const MyApp(),
),
);
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return const MaterialApp(
home: RootScreen(),
);
}
}
Configuration

Replace <your-application-id> with the Application ID from your ThunderID application settings.

localhost works from the iOS Simulator. For Android, see Run the App.

Configuration Parameters

ParameterDescription
baseUrlYour ThunderID instance URL. Must use HTTPS.
scopesOAuth 2.0 scopes to request. Include 'openid' at minimum.
applicationIdThe Application ID used for the app-native sign-in and sign-up flows
7

Add Sign-In and Sign-Out

Create a root screen that reads auth state from ThunderIDProvider.of(context) and routes to either your auth or home screen.

Create lib/root_screen.dart:

lib/root_screen.dart
import 'package:flutter/material.dart';
import 'package:thunderid_flutter/thunderid_flutter.dart';
import 'auth_screen.dart';
import 'home_screen.dart';

class RootScreen extends StatelessWidget {
const RootScreen({super.key});

@override
Widget build(BuildContext context) {
final thunder = ThunderIDProvider.of(context);

if (!thunder.initialized || thunder.isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}

return thunder.isSignedIn ? const HomeScreen() : const AuthScreen();
}
}

Create lib/auth_screen.dart to display the sign-in form:

lib/auth_screen.dart
import 'package:flutter/material.dart';
import 'package:thunderid_flutter/thunderid_flutter.dart';

enum _AuthMode { signIn, signUp }

class AuthScreen extends StatefulWidget {
const AuthScreen({super.key});

@override
State<AuthScreen> createState() => _AuthScreenState();
}

class _AuthScreenState extends State<AuthScreen> {
_AuthMode _mode = _AuthMode.signIn;

@override
Widget build(BuildContext context) {
const applicationId = '<your-application-id>';

return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SegmentedButton<_AuthMode>(
segments: const [
ButtonSegment(value: _AuthMode.signIn, label: Text('Sign In')),
ButtonSegment(value: _AuthMode.signUp, label: Text('Create Account')),
],
selected: {_mode},
onSelectionChanged: (s) => setState(() => _mode = s.first),
),
const SizedBox(height: 28),
if (_mode == _AuthMode.signIn)
SignIn(applicationId: applicationId)
else
SignUp(applicationId: applicationId),
],
),
),
),
);
}
}
Configuration

Replace <your-application-id> with the Application ID from your ThunderID application settings.

8

Display User Profile Information

Create lib/home_screen.dart to show the authenticated user's name and a sign-out button:

lib/home_screen.dart
import 'package:flutter/material.dart';
import 'package:thunderid_flutter/thunderid_flutter.dart';

class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});

@override
Widget build(BuildContext context) {
final thunder = ThunderIDProvider.of(context);
final user = thunder.user;

return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (user != null) ...[
Text(
'Welcome, ${user.displayName ?? user.email ?? 'User'}!',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
user.email ?? '',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 24),
],
SignOutButton(),
],
),
),
);
}
}
9

Run the App

Start an iOS simulator or connect an Android device, then run:

flutter run
Reaching a local instance from Android

An emulator's localhost is the emulator itself. Map it to your machine with adb from the Android SDK's platform-tools:

adb reverse tcp:8090 tcp:8090
Test credentials

You'll need a user to sign in with. If you haven't created one yet, open https://localhost:8090/console, navigate to Users, and add a test user with an email and password.

Success

You should see the sign-in form. Enter your test user credentials and tap Submit. After successful authentication, the home screen displays the user's name and a Sign Out button.

What's Next

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.