Foreword
The provisioning is the step that consists in feeding the Secure Client with all the necessary information it needs to connect to the Secure Backend.
Howto
Provisioning can be achieved via the singleton instance of the AOneAppSecurity
class.
// Get the class instance and start provisioning AOneAppSecurity.getInstance(this.context, AOneAppSecurityCbk(this.activity)) .provision(settings)
Now there are a few things to consider in this example: the callbacks class AOneAppSecurityCbk
and the provisioning settings.
Callbacks
Some of the AOneAppSecurity
class methods are asynchronous. The AOneAppSecurityCbk
class purpose is to provide callback functions for when the asynchronous tasks are complete or terminated for some reason.
The AOneAppSecurityCbk
class must derive the IAOneAppSecurityCbk
interface. The rest of its content is implementation dependent. Find below an basic implementation example:
class AOneAppSecurityCbk() : IAOneAppSecurityCbk { override fun getApplicationInfo(): String { Log.v("${this::class.java.simpleName}", "getApplicationInfo") return "{}" } override fun notifyError(error: Int) { Log.v("${this::class.java.simpleName}", "notifyError - error: " + error) } override fun notifyException(e: Exception) { Log.v("${this::class.java.simpleName}", "notifyException - exception: " + e) } override fun notifyExit() { Log.v("${this::class.java.simpleName}", "notifyExit") } override fun notifyRemediation(data: String?) { Log.v("${this::class.java.simpleName}", "notifyRemediation") } override fun pinEnterResult(params: Any?, status: IAOneAppSecurityCbk.PinStatus, pin: ByteArray?, error: Int) { Log.v("${this::class.java.simpleName}", "pinEnterResult - params: ${params}, status: ${status}, error: ${error}") } override fun syncExecuteResult(params: Any?, error: Int) { Log.v("${this::class.java.simpleName}", "syncExecuteResult - error: ${error}, params: ${params}") } }
Provisioning settings
The provisioning settings are the information the Secure Client will need to connect to the Backend Server. There are to be provided as a JSON string with the following parameter:
domain: Secure Backend IP address or hostname
port
osType (should be set to “Anroid”)
hardwareDescription
terminalId: terminal ID received when registering the device in the database
clientId: client ID received when registering the user in the database
secret: client secret received when registering the user in the database
Which gives us the following code as example:
// Provisioning parameters val settings = """ |{ |"domain":"my.domain.name", |"port":8090, |"osType":"Android", |"hardwareDescription":"AmadisOneClient", |"terminalId":"1234567891" |"clientId":2 |"secret":"DbIHpPvGbfnj6j8gh6mG7FtB8eAgO1yM8V0DnDPT" |}""".trimMargin()
Flow
The provisioning step is supposed to happen only once in the application lifetime (unless some parameters need to be changed - for example, a change of user ID or a change of domain name, etc…).
Calling the provisioning method on an already provisioned device will not only fail but also clean the provisioning settings from the system.
In case you need to change the provisioning data it is cleaner to programmatically remove the existing data (called stores) and then start provisioning again.
To delete the existing store, the following code can be used:
// Store name pattern private val regex = Regex("""R\w+\.bin$""") // Delete store private fun deleteStores() { val fileList = context.filesDir.listFiles() if (null != fileList) { for (fileObj in fileList) { if (regex.matches(fileObj.name)) { fileObj.delete() } } } }