Flutter - Device Intelligence Integration Guide
December 3rd, 2022
A Flutter plugin for Bureau's Device Intelligence product. It helps you understand your user’s unique hardware with their device data. It efficiently syncs the data in the background and processes them. The processed data can be used to generate a fingerprint id.
Integration Overview
- Integrate Android SDK in your application
- Call the API to query device information
- SessionKey and UserID is generated from client backend and sent to the SDK.
- Invoke the submit function in SDK to pass the data to Bureau backend.
- Upon successful transmission of the parameters, a callback is received in the SDK, based on the callback (Success/Failure) next steps can be taken.
- If the callback is successful, Invoke Bureau's backend API /v1/suppliers/device-fingerprint to fetch the results.
- Use the fingerprint and risk signals to allow, block or redirect the user to a desired flow.
Usage
Install the package
Install onetaplogin ^ 1.1.9 as a [dependency in your pubspec.yaml file]
Refer the below change log for the latest dependency.
Initialise the SDK
// Import package
import 'package:onetaplogin/onetaplogin.dart';
// To use Device Intelligence as a standalone product
var status = await Onetaplogin.submitDeviceIntelligence(
//Here the status returned is a string and contains the finger print sdk's success or failure message
clientID,
txnID,
msisdn, env : "Sandbox");
Parameter Description
Key | Description | Mandatory/Optional |
---|---|---|
client_id | The client id shared by Bureau. | Mandatory |
environment | Environment in which SDK is being used. The SDK is configured to call the production endpoint by default, to change it to sandbox set the parameter env : "Sandbox" while initialising the SDK. | Mandatory |
txnID | Identifier to track a session, note we recommend you to generate it from your backend. This has to be unique for every request. | Mandatory |
msisdn | Identifier for a user, can be internal customer ID. | Mandatory |
The status object for the submitDeviceIntelligence method would be a Bureau's own custom class with the following properties.
- isSuccess boolean to check the success of device intelligence.
- errorMessage and errorCode to pinpoint errors in the case isSuccess is false and empty for 'true' cases.
Android Manifest changes
//Add the folowing call if targeting S+ devices
<activity>
android:exported="true"
</activity>
Serverside URL's
- Sandbox - https://api.overwatch.stg.bureau.id/v1/suppliers/device-fingerprint
- Production - https://api.overwatch.bureau.id/v1/suppliers/device-fingerprint
Serverside call to get details.
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-xxxx-487f-xxxx-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-xxxx-487f-xxxx-548d6a809360"
}'
Response
{
"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",
"debuggable": true,
"emulator": true,
"fingerprint": "1e3f8831-a062-4b55-ad37-ee5f414f1941",
"firstSeenDays": 188,
"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
}
{
"data": null,
"errors": {
"status": 401,
"errorCode": "UNAUTHORIZED",
"service": "Overwatch"
},
"message": "",
"meta": {
"length": 0,
"took": 0,
"total": 0
}
}
{
"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
}
{
"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
}
{
"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"
}
Response Description
Key | Description |
---|---|
GPSLocation(city, country, latitude, longitude, region) | GPS Based location of the user, user's consent is required to be taken to get this details. |
IPLocation(city, country, latitude, longitude, region) | IP based location of the user. |
IP | IP address of the user. |
VPN | 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. |
isCrawler | Flag to indicate if the IP being used by the user is associated with a crawler. |
isProxy | Flag to indicate if the IP being used by the user is a proxy. |
isTor | Flag to indicate if the IP being used by the user is of a Tor network. |
threatLevel | The threat level associated with the IP. Possible values can be ["low", "medium", "high"] |
IPType | The type of IP, ["v4", "v6"] |
OS | The OS of the user's device. |
debuggable | Flag to indicate if the app is in debug mode. |
emulator | Flag to indicate if the app is being run on an emulator |
fingerprint | A hash generated for the device, this identifier will be unique for a device. |
firstSeenDays | The number of days from which the device is identified on Bureau's network. |
isAppCloned | Flag to indicate if the app is cloned. |
isAppTampered | Flag to indicate if the app is tampered. |
mockgps | Flag to indicate if the user is spoofing their GPS location. This will need users permission for background location. |
model | The device model. |
package | The package name. |
rooted | Flag to indicate if the device is rooted. |
remoteDesktop | Whether a remote desktop is monitoring the session |
voiceCallDetected | Indicates if a voice call was active when device data was gathered |
sessionId | The session identifier, that was used to invoke the SDK. |
riskLevel | Risk level of the user, calculated based on the flags that are exposed in the above sections. Possible values ["LOW", "MEDIUM", "HIGH"] |
riskScore | Alternative scoring models incorporate the data that is essentially derived from the above raw signals. |
userId | The userID that was sent as part of the request body. |
totalUniqueUserId | The total number of unique usersIDs associated to the fingerprint. |
confidenceScore | The confidence score for the fingerprint that was generated. |
Go live Checklist
- For determining the app tamper check, we would require your package name and signature hash code, kindly ensure this is shared before going live. The hash code can be obtained from PackageManager GET_SIGNING_CERTIFICATES signingInfo.signingCertificateHistory this will be a byte array.