Skip to content

DEA SDK for Flutter

Detect whether an app session comes from a real person. The SDK observes touch, stylus, mouse, scroll and device-motion input across your whole Flutter app and scores the session on the device.

On this page: Prerequisites · Install · Initialize the SDK · Ask for consent · Use the classification · Verify your setup · Before you release · Next steps

Prerequisites

  • An appId and appKey for each platform your app ships on — see Accounts and keys. DEA registers your Android app and your iOS app as two apps, each with its own pair.
  • Flutter 3.24 or later, Dart 3.5 or later
  • Android: minSdkVersion 21 (Android 5.0) or later
  • iOS: deployment target 12.0 or later

The SDK runs on Android and iOS. The package ships the scoring engine for Android arm64-v8a and x86_64 (so 64-bit emulators work), and for iOS devices and the iOS Simulator.

Note: On an Android device that can only run 32-bit apps (armeabi-v7a), the scoring engine does not load. The SDK still starts, isScoring is false, and error says why — see Troubleshooting.

Install

The Flutter SDK is distributed as three zip files, dea_sdk and its companions dea_base and dea_automation_detection, which you vendor into your project. All three must come from the same release.

Note: The packages are downloaded from DEA's release URL below. They are not on pub.dev.

Download the packages

From your app's root folder:

mkdir -p vendor/dea && cd vendor/dea
curl -sSO https://sdk.dep-protocol.com/0.19.0/flutter/base/dea-base-0.19.0.zip
curl -sSO https://sdk.dep-protocol.com/0.19.0/flutter/automation-detection/dea-automation-detection-0.19.0.zip
curl -sSO https://sdk.dep-protocol.com/0.19.0/flutter/sdk/dea-sdk-0.19.0.zip
unzip -qo dea-base-0.19.0.zip && unzip -qo dea-automation-detection-0.19.0.zip && unzip -qo dea-sdk-0.19.0.zip

This creates vendor/dea/base, vendor/dea/automation_detection and vendor/dea/sdk.

pubspec.yaml

dependencies:
  dea_sdk:
    path: vendor/dea/sdk

dependency_overrides:
  dea_base:
    path: vendor/dea/base
  dea_automation_detection:
    path: vendor/dea/automation_detection

Then run flutter pub get.

dea_sdk requires dea_base and dea_automation_detection at exactly its own version; the overrides point them at the copies you downloaded. dea_automation_detection is needed even when automation detection is off. To upgrade, download all three zips again at the new version. A mismatched pair does not fail the build, but the SDK refuses to run — see Troubleshooting.

Platform setup

No platform setup is needed for capture. The plugin registers itself, and on Android it adds the INTERNET permission to your app's manifest.

On iOS, make sure your ios/Podfile targets at least iOS 12:

platform :ios, '12.0'

Attest has additional Android and iOS setup.

Initialize the SDK

Initialize once, in main(), before runApp, so that capture covers the whole session. Pass the appId and appKey of the platform the app is running on:

import 'dart:io' show Platform;

import 'package:dea_sdk/dea_sdk.dart';
import 'package:flutter/material.dart';

void main() {
  DeaSdk.init(
    DeaOptions(
      appId: Platform.isIOS ? 'YOUR_IOS_APP_ID' : 'YOUR_ANDROID_APP_ID',
    ),
    appKey: Platform.isIOS ? 'YOUR_IOS_APP_KEY' : 'YOUR_ANDROID_APP_KEY',
  );
  runApp(const MyApp());
}
  • appId is a field of DeaOptions; appKey is a named argument of DeaSdk.init. The app key is not a secret: it identifies your app to DEA and ships inside it. See Accounts and keys.
  • appKey is needed for Attest, which sends it to DEA as the X-App-Key header. Without it, attest() answers unsupported without contacting DEA. Capture and the classification do not use it.
  • You do not need to call WidgetsFlutterBinding.ensureInitialized() first. init does it.
  • init is safe to call more than once. A repeat call returns the running instance and keeps its options.
  • init never throws. If something fails while starting, the SDK keeps running without a score and reports the problem on error.
  • Capture is global: every pointer Flutter routes in the app, the motion sensors, and app lifecycle. There is no widget to wrap and nothing to register. Input Flutter does not route — typing, and touches inside a web view — is reported by your app; see Human Scoring.
  • Nothing is recorded until the user consents. See the next step.

Anywhere else in your code, get the running instance with DeaSdk.instance:

final dea = DeaSdk.instance; // null before init

By default the SDK records nothing until the user agrees. This step is required: an app that never asks records nothing and never gets a classification.

The SDK ships a ready-made dialog. Show it once your first screen is on screen:

import 'package:dea_sdk/dea_sdk.dart';
import 'package:flutter/material.dart';

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) showDeaConsentDialog(context);
    });
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(body: Center(child: Text('Home')));
  }
}

The answer is stored on the device, so the dialog is only shown until the user has answered. To use your own UI, change the wording, or ask again, see User Consent.

Use the classification

Read the classification at the moment you make a decision. The read is synchronous and makes no network call.

import 'package:dea_sdk/dea_sdk.dart';

Future<void> onSignUp(SignUpForm form) async {
  final result =
      DeaSdk.instance?.getClassification().result ?? ClassificationResult.insufficient;
  if (result == ClassificationResult.human) {
    await submitSignUp(form);
  } else {
    showChallenge(); // bot, undetermined or insufficient: a captcha, a delay, a manual review
  }
}

Note: The classification is one signal about the session, not a decision on its own. Keep a fallback path for bot, undetermined and insufficient, as above. How the score is built is explained in How scoring works.

Verify your setup

The published Flutter package writes no log, so check the SDK from code.

  1. Run the app on a device or emulator with flutter run, accept the consent dialog, and use the app — tap, scroll, swipe. Each tap, drag or scroll is an action. The score is sufficient once there are as many as the model asks for: 8 with the built-in model. See Evidence.

  2. Print the SDK's state, for example from a debug button:

import 'package:dea_sdk/dea_sdk.dart';
import 'package:flutter/foundation.dart';

void printDeaState() {
  final dea = DeaSdk.instance!;
  debugPrint('error: ${dea.error}');                // null
  debugPrint('scoring: ${dea.isScoring}');          // true
  debugPrint('consent: ${dea.consent.decision}');   // ConsentDecision.granted

  final info = dea.getSessionInfo();
  debugPrint('session: ${info.session}');           // a UUID
  debugPrint('sdk: ${info.sdk.version}');           // 0.19.0

  final read = dea.getClassification();
  debugPrint('actions: ${read.actions}, result: ${read.result}, '
      'score: ${read.value}, model: ${read.modelVersion}');
}
  1. Call it again after more interaction. actions should grow as you use the app, and result should leave insufficient once it reaches 8. If it stays at 0, see Troubleshooting.

Before you release

  • [ ] Each platform passes its own appId and appKey to DeaSdk.init — see Options
  • [ ] The consent dialog is shown, or your own consent flow calls setConsent — see User Consent
  • [ ] The classification is read at the decision point, with a fallback for bot, undetermined and insufficient — see Human Scoring
  • [ ] Capture is paused on password and payment screens — see Sensitive Screens
  • [ ] reset() is called on logout — see Sessions
  • [ ] If a decision follows input in a web view, its touches are forwarded — see Human Scoring
  • [ ] modelDirectory is passed to DeaSdk.init, so the SDK can receive model updates — see Options
  • [ ] Android: the app is set up for Play Integrity; iOS: the App Attest capability is added — see Attest
  • [ ] The rest of the cross-platform checklist — see Going to production

Next steps