Flutter SDK (Android + iOS + Web)

Welcome to our Flutter plugin designed to seamlessly integrate with the Bureau's Device Intelligence, enhancing the functionality of mobile apps or webpages.

Overview: Device Intelligence

Our Device Intelligence module empowers you to gain comprehensive insights into your users by meticulously gathering data on their devices. This data serves as the foundation for creating a distinctive identifier for each user, known as a device fingerprint. The device fingerprint not only enables user identification but also facilitates the tracking of user activities across various sessions.

Key Features:

Seamless Integration: Effortlessly incorporate the Flutter plugin into your existing applications, ensuring a smooth and unobtrusive user experience.

Anti-Fraud Accuracy: Benefit from our solution's exceptional anti-fraud capabilities, safeguarding your platform against potential threats while maintaining accuracy and reliability.

Trusted Device View: Obtain a reliable view of trusted devices, allowing you to make informed decisions without compromising user interactions.

Getting Started:

To integrate our Flutter plugin into your project, follow the comprehensive documentation provided below. Ensure a seamless implementation and unlock the full potential of Device Intelligence for your application.


Getting Started

Integration Steps

At its core, the solution functions through three straightforward steps:

  1. Start by installing Device Intelligence SDK with mobile application.
  2. Initialize the SDK - this enables us to gather user and device data. We will then thoroughly analyze and enhance the collected data in the background.
  3. You can then utilize our API to access insights, aiding you in deciding the subsequent actions for your user, whether it's permitting, obstructing, or redirecting them.

Flow Diagram

This diagram shows the interactions between a merchant's mobile app and Bureau's SDK.

  1. sessionKey and userid are generated / retrieved by the client backend and sent to your application
  2. Your mobile application initialises our SDK through the init function by setting these attributes -
    1. Session ID (mandatory unique UUID)
    2. User ID (optional)
    3. Flow (optional)
  3. Invoke the submit function in SDK to pass the data to Bureau backend.
  4. Upon successful submission of the parameters, a callback is received in the SDK. The next steps can be taken based on the callback (success/failure).
  5. If the callback is successful, your mobile application relays the success to your backend
  6. Invoke Bureau's backend API /v1/suppliers/device-fingerprint to fetch insights
    1. Input :sessionId
  7. Based on the insights provided (fingerprint, and risk signals), you can determine the next steps for the user, such as allowing, blocking, or redirecting them.

Step 1 - SDK Installation

VersionRecommendation
Install onetaplogin 1.1.9 as a [dependency in your pubspec.yaml file]Use this version if you have disclosed the need to collect package names via "QUERY_ALL_PACKAGES" in your privacy policy for fraud signal detection
Install onetaplogin: 1.3.2Use this version if you DO NOT want to collect package names via "QUERY_ALL_PACKAGES" for fraud signal detection.

Step 2 - Initialise SDK

On Production

// Import package
import 'package:onetaplogin/onetaplogin.dart';


// To use Device Intelligence  
String status = await Onetaplogin.submitDeviceIntelligence(         //Here the status returned is a string and contains the finger print sdk's success or failure message
          clientID,
          sessionId,
          userId);
	  

On Sandbox

// Import package
import 'package:onetaplogin/onetaplogin.dart';
	  
String status = await Onetaplogin.submitDeviceIntelligence(                       //Here the status returned is a string and contains the finger print sdk's success or failure message
          clientID,
          sessionId,
          userId, env : "Sandbox");	  

The status object for submitDeviceIntelligence and authenticateWithDeviceIntelligence methods would be a Bureau's own custom class that has the following properties.

  1. isSuccess boolean to check the success of deviceintelligence.
  2. errorMessage and errorCode to pinpoint errors in the case isSuccess is false and empty for true cases.

Android outer level build.gradle changes

buildscript {
  repositories {
    maven {
      url = uri("https://storage.googleapis.com/r8-releases/raw")
    }
  }
  dependencies {
    classpath("com.android.tools:r8:8.2.24")
  }
}

Android Manifest changes (Only for Device Intelligence)

PERMISSIONUSAGE STATUS
USE_BIOMETRICREQUIRED
USE_FINGERPRINTREQUIRED
READ_GSERVICESREQUIRED
ACCESS_WIFI_STATEREQUIRED
ACCESS_NETWORK_STATEREQUIRED
ACCESS_GPSREQUIRED
CHANGE_WIFI_STATEREQUIRED
SYSTEM_ALERT_WINDOWREQUIRED
ACTION_MANAGE_OVERLAY_PERMISSIONREQUIRED
CHANGE_NETWORK_STATEREQUIRED
MANAGE_EXTERNAL STORAGEOPTIONAL
ACCESS_COARSE_LOCATIONREQUIRED
ACCESS_FINE_LOCATIONOPTIONAL
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.USE_BIOMETRIC" />
  <uses-permission android:name="android.permission.USE_FINGERPRINT" />
  <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_GPS" />

  <uses-feature android:name="android.hardware.location.gps" />
  <uses-feature android:name="android.hardware.location" />

  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />

iOS Changes

Make the below changes to Info.plist


//App would like to access IDFA for tracking purpose
<key>NSUserTrackingUsageDescription</key>
<string></string>

Step 3 - Invoke API for Insights

To access insights from users and devices, device fingerprint, and risk signals, integrating with Bureau's backend API is a must for Device Intelligence.

Please find below the link to the respective API documentations:

Device Intelligence - https://docs.bureau.id/reference/device-intelligence

API Requests

The URL to Bureau's API service is either:

Authenticaton

API's are authenticated via an clientID and secret, they have to be base64 encoded and sent in the header with the parameter name as Authorisation.

Authorisation : Base64(clientID:secret)

curl --location --request POST 'https://api.overwatch.stg.bureau.id/v1/suppliers/device-fingerprint' \
--header 'Authorization: Basic MzNiNxxxx2ItZGU2M==' \
--header 'Content-Type: application/json' \
--data-raw '{
    "sessionKey": "697bb2d6-1111-1111-1111-548d6a809360"
}'

curl --location --request POST 'https://api.overwatch.bureau.id/v1/suppliers/device-fingerprint' \
--header 'Authorization: Basic MzNiNxxxx2ItZGU2M==' \
--header 'Content-Type: application/json' \
--data-raw '{
    "sessionKey": "697bb2d6-1111-1111-1111-548d6a809360"
}'

API Response

Bureau's Backend API will return one of the following HTTP status codes for every request:

{
    "GPSLocation": {
        "city": "Madurai",
        "country": "India",
        "latitude": 9.961932591738853,
        "longitude": 78.12884837677319,
        "region": "Tamil Nadu"
    },
    "IP": "106.51.82.180",
    "IPLocation": {
        "city": "Bengaluru",
        "country": "India",
        "latitude": 12.97623,
        "longitude": 77.603287,
        "region": "Karnataka"
    },
    "IPSecurity": {
        "isCrawler": false,
        "isProxy": false,
        "isTor": false,
        "VPN": false,
        "threatLevel": "LOW"
    },
    "IPType": "v4",
    "OS": "android",
    "accessibilityEnabled": false,
    "adbEnabled": true,
    "debuggable": true,
    "developerMode": false,
    "emulator": true,
    "fingerprint": "1e3f8831-a062-4b55-ad37-ee5f414f1941",
    "firstSeenDays": 188,
    "googlePlayStoreInstall": false,
    "mitmAttackDetected" : false,
    "mockgps": false,
    "model": "M2006C3MII",
    "package": "com.prism.android.prismsampleapp",
    "rooted": true,
    "userId": "demo-session-shekh-prd-user-25677",
    "isAppTampered": null,
    "isAppCloned": false,
    "riskLevel": "HIGH",
    "totalUniqueUserId": 3,
    "remoteDesktop": false,
    "voiceCallDetected": false,
    "sessionId": "demo-session-shekh-dev-android-2023-5-30-fp-640-19",
    "confidenceScore": 100,
    "createdAt": 1686125656521,
    "riskLevel": "VERY_HIGH",
    "riskScore": 90.46
}

{
    "statusCode": 400,
    "error": {
        "code": 0,
        "type": "BAD_REQUEST",
        "message": "Session key is missing",
        "description": "request does not contain additionalData.sessionKey param in request",
        "referenceId": "24f94ae8-xxxx-48a4-xxxx-b25f99fb06d9",
        "metadata": null
    },
    "timestamp": 1658402143450,
    "merchantId": "auth0|61dfbbxxxx3420071be7021",
    "requestId": "66403193-xxxx-44bc-xxxx-14735a45dfeb"
}
{
  "data": null,
  "errors": {
    "status": 401,
    "errorCode": "UNAUTHORIZED",
    "service": "Overwatch"
  },
  "message": "",
  "meta": {
    "length": 0,
    "took": 0,
    "total": 0
  }
}
{
    "error": {
        "code": 422,
        "description": "Failed to find fingerprint for given session key",
        "message": "NO_RECORD_FOUND",
        "metadata": null,
        "referenceId": "",
        "type": "NO_RECORD_FOUND"
    },
    "merchantId": "auth0|61dfbbxxxx420071be7021",
    "requestId": "24e1aa7f-xxxx-404d-xxxx-5f8a0227e8f0",
    "statusCode": 422,
    "timestamp": 1658402132141
}
{
  "error": {
    "code": 0,
    "description": "",
    "message": "Server encountered an error",
    "metadata": null,
    "referenceId": "86529a18-a5cb-4da9-91b0-8d04cdb9167e",
    "type": "INTERNAL_SERVER_ERROR"
  },
  "merchantId": "auth0|61dfxxxx0071be7021",
  "requestId": "c69d86f0-xxxx-4ef0-xxxx-e687d595a507",
  "statusCode": 500,
  "timestamp": 1657009043753
}

Responses

HTTP Status Code Description

The Bureau's Backend API attempts to return the appropriate HTTP status code for every request. The following table illustrates the possible status codes and their meanings:

Status CodeStatus SummaryDescription
200Successful RequestThe request succeeded.
400Bad RequestRequest is not well-formed, syntactically incorrect, or violates schema. The server could not understand the request. Indicates one of these conditions:
1. The API cannot convert the payload data to the underlying data type.
2. The data is not in the expected data format.
3. A required field is not available.
4. A simple data validation error occurred.
401UnauthorisedThe server rejected the request because authentication credentials provided was not valid.
422No Record FoundThe API can't carry out the requested action to get the fingerprint generated from the provided Session Key or Session ID. It's possible that the sent Session Key or Session ID is incorrect.
500Internal Server ErrorA problem happened with the system or application. Even though the client's request seems right, something unexpected took place on the server.

Insight Response Descriptions

Bureau's Device Intelligence solution combines device and behavioral data to identify devices using fingerprints. With the application of Bureau's proprietary signal detection and fraud risk model, you can use these data to adeptly unveil and thwart fraudulent activities.

Signal AttributesDescription
GPSLocation(city, country, latitude, longitude, region)GPS Based location of the user's device. User's consent is required to be taken to get this details.
IPLocation(city, country, latitude, longitude, region)IP based location of the user.
IPIP address of the user.
VPNBoolean Flag to indicate if the IP being used by the user is a VPN. (Note the VPN within the IPSecurity JSON object should be used and not the one outside).
isCrawlerBoolean Flag to indicate if the IP being used by the user is associated with a crawler.
isProxyBoolean Flag to indicate if the IP being used by the user is a proxy.
isTorBoolean Flag to indicate if the IP being used by the user is of a Tor network.
threatLevelThe threat level associated with the IP. Possible values can be ["low", "medium", "high"]
IPTypeThe type of IP, ["v4", "v6"]
OSThe OS of the user's device.
developerModeBoolean Flag to indicate if the user has turned on developer options on their android OS
accessibilityEnabledBoolean Flag to indicate if the user has turned on the accessibility feature on android
adbEnabledBoolean Flag to indicate if the user enabled the android debugger bridge with the phone connecting the laptop and mobile
googlePlayStoreInstallBoolean Flag to indicate if the app has been installed outside of the Google Playstore
debuggableBoolean Flag to indicate if the app is in debug mode.
emulatorBoolean Flag to indicate if the app is being run on an emulator.
fingerprintA hash generated for the device, this identifier will be unique for a device.
firstSeenDaysThe number of days from which the device is identified on Bureau's network.
isAppClonedBoolean Flag to indicate if the app is cloned.
isAppTamperedBoolean Flag to indicate if the app is tampered.
mitmAttackDetectedBoolean Flag to indicate if the payload has been intercepted.
mockgpsBoolean Flag to indicate if the user is spoofing their GPS location. This will need users permission for background location.
modelThe device model.
packageThe package name.
rootedBoolean Flag to indicate if the device is rooted.
remoteDesktopBoolean Flag to indicate whether a remote desktop monitoring session is detected
voiceCallDetectedBoolean Flag to indicate if a voice call was active when device data was collected
sessionIdThe session identifier, that was used to invoke the SDK.
riskLevelAlternative scoring models that incorporates data that is derived from the above raw signals. The possible values for the score are Low, Medium, High, and Very High.
riskScoreAlternative scoring models that uses data derived from the above raw signals.
userIdThe userID that was sent as part of the request body.
totalUniqueUserIdThe total number of unique usersIDs associated to the fingerprint.
confidenceScoreThe confidence score of the generated fingerprint.

Go-live Checklist

To determine if your app has been tampered with, we will need your package name and signature hash code. Please share this information with us before going live.

The hash code can be obtained from the PackageManager using the GET_SIGNING_CERTIFICATES permission. The signingInfo.signingCertificateHistory property will return a byte array containing the hash code.