Device Security (Flutter)

Estimated reading: 4 minutes 102 views

Overview

Device Security's SDK is used to perform a number of checks on the target device inclusive of checks for whether or not the device is rooted/jailbroken, using a VPN ....

Minimum Requirements

iOS: 11.0

Android: API level 21

Installation

Installation of Device Security's SDK in flutter requires using the native SDK's for Android and iOS, and the use of Method Channels to utilize the SDK's functions.

iOS

Android

There are a few steps to getting started:

  • Import the SDK aars into your project
    • Create a folder inside android/app called libs
    • copy sdk files inside the libs folder
  • Depend on SDK
    • in your app level build.gradle (android/app/build.gradle) add implementation statements for the SDKs.
android {

    // ...

}
flutter {
    // ...
}
dependencies {
    // ...

    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation files('libs/TMXAuthentication-rl-7.0-60.aar')
    implementation files('libs/TMXBehavioSec-rl-7.0-60.aar')
    implementation files('libs/TMXDeviceSecurityHealth-rl-7.0-60.aar')
    implementation files('libs/TMXProfilingConnections-rl-7.0-60.aar')
    implementation files('libs/TMXProfiling-rl-7.0-60.aar')

   // ...
 
}

Code Implementation

After importing the library and frameworks on both android and iOS respectively we then must implement our method channel code.

Dart Implementation

We first need to setup our method channel. For this example we'll be using Getx for state management and placing our business logic code inside a class called Device Security Controller.

First let's create our class and create our method channel and supply it with a string. This string is important as it is used in the native code later to set up communication between the dart, java/kotlin and swift code.

class DeviceSecurityController extends GetxController{

MethodChannel functionChannel = MethodChannel("com.example.function");

}

Next let's write a function to start the device security code in dart that will then communicate with the native code.

startDeviceSecurity() async {
   await functionChannel.invokeMethod("startDeviceSecurityCheck");
  }

Now the last thing we need is some code that is triggered once the checks are completed

void handleMethodChannelCallback(){ 
functionChannel.setMethodCallHandler((call) async {
      if (call.method == "reportStatusTmx" && call.arguments != null) {
     
       
        // save the apSession to send to AwareID

  
        } else {

        // Throw some error

        }
      }
    }
}

Please note that you must set your method call handler (see in the above code) by calling the handleMethodChannelCallback() before calling startDeviceSecurity().

We do this at the initialization of our class and calling startDeviceSecurity when the state is ready.

Put together our class now looks like:

class DeviceSecurityController extends GetxController{

MethodChannel functionChannel = MethodChannel("com.example.function");


  @override
  void onInit() {
    handleMethodChannelCallback()
    super.onInit();
  }

  @override
  void onReady() {
    startDeviceSecurity()
    super.onReady();
  }

void handleMethodChannelCallback(){ 
functionChannel.setMethodCallHandler((call) async {
      if (call.method == "reportStatusTmx" && call.arguments != null) {
     
       
        // save the apSession to send to AwareID

  
        } else {

        // Throw some error

        }
      }
    }
}

startDeviceSecurity() async {
   await functionChannel.invokeMethod("startDeviceSecurityCheck");
  }

}

Swift Implementation

Let's first create a class to configure our SDK

import Foundation
import RLTMXProfiling
import RLTMXProfilingConnections

public class DeviceSecurityManager {
    static let shared = DeviceSecurityManager()
    private var profile: AnyObject?
    private var sessionID: String?

    private init() {}
    
    func getDeviceSecuritySessionId(completion: @escaping (String?) -> Void) {
        let profilingConnections = RLTMXProfilingConnections()

        profilingConnections.connectionTimeout = // Timeout in seconds
        profilingConnections.connectionRetryCount = // Number of retries if connection fails

        profile = RLTMXProfiling.sharedInstance()
        profile?.configure(configData: [
            RLTMXOrgID: // Please contact Aware for your OrgID ,
            RLTMXFingerprintServer: "content.maxconnector.com",
            RLTMXProfileTimeout: profilingConnections.connectionTimeout,
            RLTMXProfilingConnectionsInstance: profilingConnections
        ])
        _ = profile?.profileDevice { result in
            guard let results = result else {
                completion(nil)
                return
            }
            
            let status = RLTMXStatusCode(rawValue: (results[RLTMXProfileStatus] as! NSNumber).intValue)!
            if status == .ok, let sessionID = results[RLTMXSessionID] as? String {
                self.sessionID = sessionID
                completion(sessionID)
            } else {
                completion(nil)
            }
        }
    }
}

Now we can use this class in our app delegate to allow calls into it using our Method Channel.

First we need to make a variable for our method channel

 var functionChannel: FlutterMethodChannel?

We also need to use the DispatchQueue in our main function as well as setting the name of our method channel and setting up the call handler

DispatchQueue.main.async {

            let controller: FlutterViewController = self.window?.rootViewController as! FlutterViewController
            self.functionChannel = FlutterMethodChannel(name: "com.aware.function", binaryMessenger: controller.binaryMessenger)
            self.functionChannel?.setMethodCallHandler({(call: FlutterMethodCall, result: @escaping FlutterResult)-> Void in
                switch call.method{

                case "startDeviceSecurityCheck":
                            DeviceSecurityManager.shared.getDeviceSecuritySessionId { sessionId in
                                DispatchQueue.main.async {
                                    if let sessionId = sessionId {
                                        // Reporting back the session ID
                                        self.functionChannel?.invokeMethod("startDeviceSecurityCheck", arguments: sessionId)
                                        result(true) // Indicating the process completion
                                    } else {
                                      
                             //Pass back an error incase the session ID is null
                                    }
                                }
                            }
}

Example in Dart using device security

After all this set up then we can use our session id to send to the backend to complete our transaction.

You can find documentation on how to complete this here

CONTENTS