Account recovery
This documentation only describes how to configure the SDK for our account recovery feature. If you want to learn about the feature and the full set of implementation requirements, see the main feature documentation:
How does account recovery work?
Recovery methods
For Android, recovery is currently supported with the following recovery methods:
| Name | Recovery method |
|---|---|
| Recovery code | CLOUD_BACKUP_RECOVERY_CODE |
| Face scan | CLOUD_BACKUP_SERVER_SIDE_FACE |
Recovery code
A recovery code is code that is chosen and remembered by the end-user.
- Backup-based recovery uses a secret code (
recoveryCode). - It is associated with the recovery method
CLOUD_BACKUP_RECOVERY_CODE. - This type of recovery is deleted after the recovery is performed.
- Kotlin
- Java
RecoveryCodeRecoveryParameter(recoveryCode)
new RecoveryCodeRecoveryParameter(recoveryCode);
The parameter RecoveryCodeRecoveryParameter replaces the former parameter EncapRecoveryCodeParameter(CLOUD_BACKUP), providing an easier constructor.
Face scan
Face scan data is obtained from a face scan of the end-user. This data contains the face scan and optionally, audit trail images.
- Recovery with face scan uses face scan data (
faceScanData). - It is associated with the recovery method
CLOUD_BACKUP_SERVER_SIDE_FACE. - This type of recovery is kept after the recovery is performed, to avoid the need for another face scan.
- Kotlin
- Java
ServerSideFaceRecoveryParameter(faceScanData)
new ServerSideFaceRecoveryParameter(faceScanData);
The parameter ServerSideFaceRecoveryParameter requires that the end-user has set up face scan for the registration, before adding recovery.
To do this, you must use addOrUpdate(AuthenticationParameter, DeviceServerSideFaceActivationParameter).
Supported backup types
Recovery for Android is fully compliant with the Android Auto Backup feature.
Prerequisites
Account recovery generates secrets that are tied to a specific device. The secrets are stored inside the app files, which the end-user needs to back up.
To enable this, you need to ensure that:
- Your application declares
allowBackupin its manifest files.android:allowBackup="true" - The file
2c5f882341aa8372a6166769bd469903.xmlis not excluded from the backup in the application manifest section.NoteYou can skip this step if the manifest does not include the attributes
fullBackupContentordataExtractionRules. For more information, see Back up and restore attributes in our Encap SDK developer documentation. - The end-user enables backup in their mobile device's settings. To do this, they can either:
- Set up a Google account and enable auto backup to Google Drive.
- Set up a cloud backup specific to the their mobile device's manufacturer, such as Samsung Cloud.
- Transfer data from another mobile device.
- Perform a manual backup to the external storage.
Google's auto backup is the most convenient way of backing up and restoring data. However, it runs on its own and in some cases files can be backed up with a delay reaching up to 24 hours. This makes recovery on another device impossible until that time.
Token authorisation
When you are using our SDKs for account recovery, you need to provide a token to authorise the operation.
- Authorisation tokens are issued by our server when performing certain SDK operations.
- In these operations, you need to set what purpose you will use the token for.
- The token is returned back to the app as a response.
- This token is used to authorise the next account recovery operation after a successful activation or authentication.
For example, this makes it possible to implement a flow that both registers the end-user and sets up recovery for the registration, without an additional authentication.
Operations that require a token
An authorisation token is required for the following recovery-related operations:
addOrUpdateRecoverydeleteRecovery
Operations that can yield a token
The server will issue an authorisation token for the following operations:
finishActivationfinishAuthenticationfinishAddOrUpdateRecoveryfinishRecoveryfinishDeleteRecovery
Token purpose
To request the authorisation token, you must provide one of the following purposes in the finish call:
TokenPurpose.ADD_OR_UPDATE_RECOVERYTokenPurpose.DELETE_RECOVERY
The default value is TokenPurpose.UNSET_PURPOSE.
Configure the SDK
How to get a token
The operations addOrUpdateRecovery and deleteRecovery require an EncapToken.
- To request a token, you must set the token purpose together with the activation or authentication parameter, using the
setTokenPurposemethod.- If adding or updating recovery, you should use
TokenPurpose.ADD_OR_UPDATE_RECOVERY. - If deleting recovery, you should use
TokenPurpose.DELETE_RECOVERY.
- If adding or updating recovery, you should use
- Kotlin
- Java
val activationParameter = DevicePinActivationParameter(userPinCode).apply {
tokenPurpose = TokenPurpose.ADD_OR_UPDATE_RECOVERY
}
ActivationParameter activationParameter = new DevicePinActivationParameter(userPinCode);
activationParameter.setTokenPurpose(TokenPurpose.ADD_OR_UPDATE_RECOVERY);
- The token is returned with the usual operation response. To learn how to access it, see example below:
- Kotlin
- Java
override fun onSuccess(result: FinishActivationResult) {
val token = result.encapToken
}
public void onSuccess(FinishActivationResult result) {
EncapToken token = result.getEncapToken();
}
Recovery Code
The following describes how to add, perform and delete recovery using a recovery code.
Add account recovery
To add account recovery and connect it to the end-user's registration, you can perform the addOrUpdateRecovery operation.
- Call
startAddOrUpdateRecoveryand pass in theEncapTokenyou acquired from the previous step. - If this is successful, then you can call
finishAddOrUpdateRecoverywith anRecoveryCodeRecoveryParameter.
- The
RecoveryCodeRecoveryParametertakes arecoveryCodethat the end-user creates. - The end-user needs to use this code when they perform a recovery later on.
- Kotlin
- Java
controller.startAddOrUpdateRecovery(
encapToken = <ENCAP_TOKEN>,
appCallback = object : AsyncCallback<StartAddOrUpdateRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartAddOrUpdateRecoveryResult) { ... }
}
)
controller.finishAddOrUpdateRecovery(
recoveryParameter = RecoveryCodeRecoveryParameter(<RECOVERY_CODE>),
appCallback = object : AsyncCallback<FinishAddOrUpdateRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishAddOrUpdateRecoveryResult) { ... }
}
)
controller.startAddOrUpdateRecovery(
<ENCAP_TOKEN>,
new AsyncCallback<StartAddOrUpdateRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartAddOrUpdateRecoveryResult result) { ... }
}
);
controller.finishAddOrUpdateRecovery(
new RecoveryCodeRecoveryParameter(<RECOVERY_CODE>),
new AsyncCallback<FinishAddOrUpdateRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishAddOrUpdateRecoveryResult result) { ... }
}
);
Perform an account recovery
To recover an end-user's registration, you can perform the startRecovery and finishRecovery operations.
This works similarly in concept to the activation process, where you must select and enable a new authentication method.
- You can only enable one authentication method for a single recovery.
- To add more authentication methods, you can perform the
addOrUpdateoperation.
- Kotlin
- Java
controller.startRecovery(
object : AsyncCallback<StartRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartRecoveryResult) { ... }
}
)
controller.finishRecovery(
recoveryParameter = RecoveryCodeRecoveryParameter(<RECOVERY_CODE>),
activationParameter = DevicePinActivationParameter(<PIN_CODE>),
appCallback = object : AsyncStateChangedCallback<FinishRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishRecoveryResult) { ... }
override fun onStateChanged(state: EncapController.State) { ... }
}
)
controller.startRecovery(
new AsyncCallback<StartRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartRecoveryResult result) { ... }
}
);
controller.finishRecovery(
new RecoveryCodeRecoveryParameter(<RECOVERY_CODE>),
new DevicePinActivationParameter(<PIN_CODE>),
new AsyncStateChangedCallback<FinishRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishRecoveryResult result) { ... }
public void onStateChanged(EncapController.State state) { ... }
}
);
The <RECOVERY_CODE> is a secret code that is provided by the end-user, and is only known by them.
- The end-user chooses the recovery code, which is a parameter to the
finishAddOrUpdateRecovery()operation. - The end-user must then provide the same recovery code as a parameter to the
finishRecovery()operation. - The end-user's choice of authentication method to activate is also a parameter to the
finishRecovery()operation.
Delete a recovery
To remove an active recovery, you can perform the startDeleteRecovery and finishDeleteRecovery operations.
The <ENCAP_TOKEN> has to be requested with an authentication, and must have the token purpose set to DELETE_RECOVERY.
- Kotlin
- Java
controller.startDeleteRecovery(
encapToken = <ENCAP_TOKEN>,
appCallback = object : AsyncCallback<StartDeleteRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartDeleteRecoveryResult) { ... }
}
)
controller.finishDeleteRecovery(
recoveryParameter = RecoveryCodeRecoveryParameter(),
appCallback = object : AsyncCallback<FinishDeleteRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishDeleteRecoveryResult) { ... }
}
)
controller.startDeleteRecovery(
<ENCAP_TOKEN>,
new AsyncCallback<StartDeleteRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartDeleteRecoveryResult result) { ... }
}
);
controller.finishDeleteRecovery(
new RecoveryCodeRecoveryParameter(),
new AsyncCallback<FinishDeleteRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishDeleteRecoveryResult result) { ... }
}
);
Face scan
The following describes how to add, perform and delete recovery using face scan.
Add account recovery
To add account recovery and connect it to the end-user's registration, you can perform the addOrUpdateRecovery operation.
- If the registration does not have server-side face, then you add it. To do this:
- Call
startAddOrUpdatewithStartAddOrUpdateParameter(authMethod = DEVICE_SERVER_SIDE_FACE). - Call
finishAddOrUpdatewith a validAuthenticationParameter(typically for PIN or biometrics), and aDeviceServerSideFaceActivationParametercontaining the face scan data of the end-user. - Request a token with
TokenPurpose.ADD_OR_UPDATE_RECOVERY.
- Call
- Call
startAddOrUpdateRecoveryand pass in theEncapTokenthat you acquired from the previous step. - If this is successful, then you can call
finishAddOrUpdateRecoverywith an emptyServerSideFaceRecoveryParameter.
- The
DeviceServerSideFaceActivationParametertakes afaceScanDatacontaining the face scan data of the end-user. - No face scan data is needed when adding recovery using the
ServerSideFaceRecoveryParameter, as the existing face scan fromaddOrUpdateis used. - The end-user needs to perform a new face scan when they perform a recovery later on.
- Kotlin
- Java
controller.startAddOrUpdate(
startParameter = StartAddOrUpdateParameter(authMethod = DEVICE_SERVER_SIDE_FACE),
appCallback = object : AsyncCallback<StartAddOrUpdateResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartAddOrUpdateResult) { ... }
}
)
controller.finishAddOrUpdate(
authParameter = DevicePinAuthParameter(<PIN_CODE>),
activationParameter = DeviceServerSideFaceActivationParameter(FaceScanData(<FACE_SCAN_DATA>)),
appCallback = object : AsyncCallback<FinishAuthenticationResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishAuthenticationResult) { ... }
}
)
controller.startAddOrUpdateRecovery(
encapToken = <ENCAP_TOKEN>,
appCallback = object : AsyncCallback<StartAddOrUpdateRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartAddOrUpdateRecoveryResult) { ... }
}
)
controller.finishAddOrUpdateRecovery(
recoveryParameter = ServerSideFaceRecoveryParameter(),
appCallback = object : AsyncCallback<FinishAddOrUpdateRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishAddOrUpdateRecoveryResult) { ... }
}
)
controller.startAddOrUpdate(
new StartAddOrUpdateParameter(DEVICE_SERVER_SIDE_FACE),
new AsyncCallback<StartAddOrUpdateResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartAddOrUpdateResult result) { ... }
}
);
controller.finishAddOrUpdate(
new DevicePinAuthParameter(<PIN_CODE>),
new DeviceServerSideFaceActivationParameter(new FaceScanData(<FACE_SCAN_DATA>)),
new AsyncCallback<FinishAuthenticationResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishAuthenticationResult result) { ... }
}
);
controller.startAddOrUpdateRecovery(
<ENCAP_TOKEN>,
new AsyncCallback<StartAddOrUpdateRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartAddOrUpdateRecoveryResult result) { ... }
}
);
controller.finishAddOrUpdateRecovery(
new ServerSideFaceRecoveryParameter(),
new AsyncCallback<FinishAddOrUpdateRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishAddOrUpdateRecoveryResult result) { ... }
}
);
Perform an account recovery
To recover an end-user's registration, you can perform the startRecovery and finishRecovery operations.
This works similarly in concept to the activation process, where you must select and enable a new authentication method.
- You can only enable one authentication method for a single recovery.
- To add more authentication methods, you can perform the
addOrUpdateoperation.
- Kotlin
- Java
controller.startRecovery(
appCallback = object : AsyncCallback<StartRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartRecoveryResult) { ... }
}
)
controller.finishRecovery(
recoveryParameter = ServerSideFaceRecoveryParameter(FaceScanData(<FACE_SCAN_DATA>)),
activationParameter = DevicePinActivationParameter(<PIN_CODE>),
appCallback = object : AsyncStateChangedCallback<FinishRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishRecoveryResult) { ... }
override fun onStateChanged(state: EncapController.State) { ... }
}
)
controller.startRecovery(
new AsyncCallback<StartRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartRecoveryResult result) { ... }
}
);
controller.finishRecovery(
new ServerSideFaceRecoveryParameter(new FaceScanData(<FACE_SCAN_DATA>)),
new DevicePinActivationParameter(<PIN_CODE>),
new AsyncStateChangedCallback<FinishRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishRecoveryResult result) { ... }
public void onStateChanged(EncapController.State state) { ... }
}
);
- The
<FACE_SCAN_DATA>contains a face scan of the end-user, optionally with audit trail images. - The end-user's choice of authentication method to activate is a parameter to the
finishRecovery()operation.
Delete a recovery
To remove an active recovery, you can perform the startDeleteRecovery and finishDeleteRecovery operations.
The <ENCAP_TOKEN> has to be requested with an authentication, and must have the token purpose set to DELETE_RECOVERY.
- Kotlin
- Java
controller.startDeleteRecovery(
encapToken = <ENCAP_TOKEN>,
appCallback = object : AsyncCallback<StartDeleteRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: StartDeleteRecoveryResult) { ... }
}
)
controller.finishDeleteRecovery(
recoveryParameter = ServerSideFaceRecoveryParameter(),
appCallback = object : AsyncCallback<FinishDeleteRecoveryResult> {
override fun onFailure(errorCodeException: ErrorCodeException) { ... }
override fun onSuccess(result: FinishDeleteRecoveryResult) { ... }
}
)
controller.startDeleteRecovery(
<ENCAP_TOKEN>,
new AsyncCallback<StartDeleteRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(StartDeleteRecoveryResult result) { ... }
}
);
controller.finishDeleteRecovery(
new ServerSideFaceRecoveryParameter(),
new AsyncCallback<FinishDeleteRecoveryResult>() {
public void onFailure(ErrorCodeException errorCodeException) { ... }
public void onSuccess(FinishDeleteRecoveryResult result) { ... }
}
);
Additional operations
These additional operations can help you to create app logic in scenarios where a backup or restore has occurred, so that you can show recovery instead of a normal registration.
Check if account recovery is added
To check whether account recovery is added on a device, you can use the following method:
- Kotlin
- Java
controller.isRecoveryActivated
controller.isRecoveryActivated();
In order for the method to detect account recovery, backup has to be restored on the new device first.
Check if device has been restored from backup
To check whether the end-user's device has been restored from backup and your app is ready to perform account recovery, you can use the following app flow:
- Check that
isActivated()is returningfalse. - Check that
isRecoveryActivatedis returningtruebefore performing an account recovery.
- Kotlin
- Java
if(!controller.isActivated() && controller.isRecoveryActivated) {
// recovery has been activated and can be used to recover registration
}
if(!controller.isActivated() && controller.isRecoveryActivated()) {
// recovery has been activated and can be used to recover registration
}