Flutter Quickstart
This guide will only include the frontend integration. If you would like to also handle Session Management in your backend, select your backend technology below:
This is a quickstart guide to help you integrate Descope with your Flutter application. Follow the steps below to get started.
To learn more about how Native Flows work and how they provide a seamless, in-app authentication experience, see Native Flows.
For a live demo, check out our video on Adding Auth to Your Flutter App.
Use this pre-built prompt to get started faster.
Include the Descope Flutter Package
Incorporate the Descope Flutter SDK as a dependency. Run the following command:
flutter pub add descopeSet Minimum Platform Versions
The Descope Flutter SDK requires a minimum iOS deployment target of 13.0 and a minimum Android SDK version of 24. You would only need to change something here if your app currently targets a lower version.
The SDK's iOS plugin ships both a podspec and a Package.swift, so Flutter resolves it using whichever dependency manager your project is already set up with. On Flutter 3.44 and later that is Swift Package Manager, which is enabled by default. On earlier versions, or on projects that haven't run flutter config --enable-swift-package-manager, it is CocoaPods.
Either way, adding the SDK requires no Podfile changes, and existing CocoaPods projects are unaffected. Both manifests build from the same native source, so you can switch to Swift Package Manager whenever you're ready.
CocoaPods projects
- Navigate to
ios/Podfile - Uncomment
platform :ios, '11.0' - Set the version to
13.0
# Uncomment this line to define a global platform for your project
platform :ios, '13.0' # <-- Change this to 13.0
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
# ...Swift Package Manager projects
- Open
ios/Runner.xcworkspacein Xcode - Select the
Runnertarget, then the General tab - Under Minimum Deployments, set iOS to
13.0
- Navigate to
android/app/build.gradle - Replace
minSdkVersion flutter.minSdkVersionwithminSdkVersion 24
// ...
android {
// ...
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.flutter_sample_app"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 24 // <-- Change this to 24
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
// ...
}
// ...Import the Flutter SDK
Proceed to import the Descope Flutter dependency.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:descope/descope.dart'; // <-- Import the Descope SDK
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Descope Flutter Sample App',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
useMaterial3: true,
),
home: Descope.sessionManager.session?.refreshToken.isExpired == false
? const HomeScreen()
: const WelcomeScreen());
}
}
class WelcomeScreen extends StatefulWidget {
const WelcomeScreen({super.key});
@override
State<WelcomeScreen> createState() => _WelcomeScreenState();
}
// ...Initialize Descope with Custom Project ID
Set up Descope in main.dart using the Descope Project ID found on your Descope project page. This is needed to activate the SDK.
Note
Optionally, add the baseUrl parameter if using a custom domain in your Descope project (e.g., https://auth.company.com).
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
Descope.setup('__ProjectID__');
await Descope.sessionManager.loadSession();
runApp(const MyApp());
}Define and Host Your Flow
Your Descope console provides customizable, predefined authentication flows which are hosted for you. You can also host the flow yourself. You'll use the url of the hosted flow later in your code. If you are deploying to Web, you can set the flow id and container css in the options here as well. For more on web flows set up, read about it in our SDK README.
class WelcomeScreen extends StatefulWidget {
const WelcomeScreen({super.key});
@override
State<WelcomeScreen> createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen> {
Future<void> _startFlow() async {
try {
final options = DescopeFlowOptions(
mobile: DescopeMobileFlowOptions(
flowUrl: 'https://auth.descope.io/login/__ProjectID__', // <-- Your flow URL
deepLinkUrl: '<your_deep_link_url>' // <-- Your deep link URL
),
web: DescopeWebFlowOptions(
flowId: 'sign-up-or-in',
flowContainerCss: {
"background-color": "antiquewhite",
"width": "500px",
"min-height": "300px",
"margin": "auto",
"position": "relative",
"top": "50%",
"transform": "translateY(-50%)",
"display": "flex",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"box-shadow": "0px 0px 10px gray",
},
));
} catch (e) {
print('Error: $e');
return;
}
}(Android Only) Configure App Links, Activity & Routing
For Android (iOS works with just a flow url), follow the instructions in our SDK README to establish App Links, create an Activity, and manage routing.
Launch your Flow
Use the flow 'start' function to initiate authentication with a custom flow (URL from step 5). For Android, add the deep link (URL from step 6).
Note
If you're using Magic Link authentication, additional setup is required as mentioned in our README.
class _WelcomeScreenState extends State<WelcomeScreen> {
Future<void> _startFlow() async {
try {
final options = DescopeFlowOptions(
mobile: DescopeMobileFlowOptions(
flowUrl: 'https://auth.descope.io/login/__ProjectID__',
deepLinkUrl: '<your_deep_link_url>'
),
web: DescopeWebFlowOptions(
flowId: 'sign-up-or-in',
flowContainerCss: {
"background-color": "antiquewhite",
"width": "500px",
"min-height": "300px",
"margin": "auto",
"position": "relative",
"top": "50%",
"transform": "translateY(-50%)",
"display": "flex",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"box-shadow": "0px 0px 10px gray",
},
));
final authResponse = await Descope.flow.start(options); // <-- Start the flow
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
if (!mounted) return;
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const HomeScreen(),
),
);
} catch (e) {
print('Error: $e');
return;
}
}
}Leverage Flutter SDK's Session Management Functions
Descope offers the Session Manager to confirm user authentication or access user details like email, userId, etc. Personalize the user experience with:
user- Access user attributes (email, name, etc.)logout- Revoke and clear active sessionrefreshToken?.isExpired- Check if the user is authenticated
For more specifics on implementing session management, see Mobile sessions.
For backend Session Validation, continue reading!
class _HomeScreenState extends State<HomeScreen> {
DescopeUser? user = Descope.sessionManager.session?.user;
Future<void> _logout() async {
final refreshJwt = Descope.sessionManager.session?.refreshJwt;
if (refreshJwt != null) {
await Descope.auth.logout(refreshJwt);
Descope.sessionManager.clearSession();
}
if (!mounted) return;
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const WelcomeScreen(),
));
}
@override
Widget build(BuildContext context) {
if (user == null) {
return const Scaffold(
body: Center(
child: Text('No user data available'),
),
);
}
DescopeUser userInfo = user!;
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Hi, ${userInfo.name}!',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge),
Text('Email: ${userInfo.email}'),
Text('Phone: ${userInfo.phone}'),
const SizedBox(height: 20),
CupertinoButton(
color: Theme.of(context).primaryColorDark,
onPressed: _logout,
child: const Text('Log out'),
)
],
),
),
);
}
}Continue with Backend SDK
If you would like to also handle Session Management in your backend, keep on reading by selecting your backend technology below:
Checkpoint
Your application is now integrated with Descope. Please test with sign-up or sign-in use case.
Customize
Now that you have the end-to-end application working, you can choose to configure and personalize many different areas of Descope, including your brand, style, custom user authentication journeys, etc. We recommend starting with customizing your user-facing screens, such as signup and login.