Orchestration SDK: Authenticator Activation on Android Studio
The Orchestration SDK is an integral part of OneSpan Mobile Security Suite (MSS). It orchestrate the commands between the different components to ensure a successful activation on the integrated mobile application, enabling the security features of the Mobile Security Suite on the end-user mobile application. Today, we will explore the activation mechanism of an authenticator instance using the Orchestration SDK on a sample application.
Prerequisites:
- Android 4.1 or later.
- A registered user on the sandbox environment of the OneSpan Intelligent Adaptive Authentication. Here’s a full reference on how to do so.
- The MSS Orchestration SDK’s sample application.
The Activation Process
Activity Creation
The activation process starts upon the creation of an instance of the ActivationActivity
class. The execution of the activity will lead to the startRegistration
method to be attached to the onClick
callback method as we see in the code snippet below. The method will then be waiting to be executed after the click event is triggered on the register button on the UI.
// Register button
Button registerBtn = (Button) findViewById(R.id.btn_register);
registerBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Make sure to hide keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
startRegistration();
}
});
Orchestrator builder and Client Device Data Collector (CDDC)
The orchestrationCallback
object will be created with the current instance of the ActivationActivity
. The instance will be passed to the orchestrationCallback
as an argument referenced with the this
keyword. Afterwards, an object of the inner Builder class of the Orchestrator
class will be created. The purpose of the Builder object is to create an Orchestrator
object following the concept of the Builder design pattern, as seen below.
private Orchestrator orchestrator;
orchestrationCallback = new SampleOrchestrationCallback(this);
Orchestrator.Builder builder = new Orchestrator.Builder();
orchestrator = builder
.setDigipassSalt(Constants.SALT_DIGIPASS)
.setStorageSalt(Constants.SALT_STORAGE)
.setContext(getApplicationContext())
.setDefaultDomain(Constants.DOMAIN)
.setCDDCParams(CDDCUtils.getCDDCParams())
.setErrorCallback(orchestrationCallback)
.setWarningCallback(orchestrationCallback)
.build();
// Set values for the CDDC when available
CDDCUtils.configure(orchestrator.getCDDCDataFeeder());
}
Before invoking the build method to complete the creation of the Orchestrator
object, the following arguments should be defined as shown in the code above:
- Hardcoded salts, which will be used for diversification with certain security features (e.g. device binding, secure storage). These salts will be derived by the Orchestration SDK Client to complicate reverse-engineering attacks.
- Default domain: required if the Customer Application Server integrates OneSpan Authentication Server. If the Customer Mobile Application must manage multiple domains, the default domain can be dynamically overwritten for each action (e.g. startActivation).
- A
CDDCParams
object, which will define the parameters for device data collection. These parameters are optional. - An
OrchestrationErrorCallback
object, in case of errors, it will be used to throw them from the Orchestration SDK Client to the Customer Mobile Application. - An
OrchestrationWarningCallback
object, in case of warnings, it will be used to throw them from the Orchestration SDK Client to the Customer Mobile Application.
After the Orchestrator
object is built successfully, the static configure
method of the CDDCUtils
class will be called to set up the values for the CDDC data from the orchestrator.getCDDCDataFeeder()
.
Activation Parameters
The activation parameters will be configured inside the startRegistration
method when it gets called. First, the current instance of the ActivationActivity
will be set for the activationParams
as an ActivationCallback
, since it already implements it.
Also, the OrchestrationUser
and the ActivationPassword
are provided as activation parameters. They will be obtained from the UI Views after the end-user is prompted to provide them upon the first execution.
Finally, The Orchestrator
object will set the UserAuthenticationCallback
passing all the necessary arguments including the orchestrationCallback
. Then it invokes the startActivation
method, passing the activation parameters that have been configured earlier as shown below.
private void startRegistration() {
// Get input strings
userId = userIdView.getText().toString();
String activationPassword = activationPasswordView.getText().toString();
// Create activation configuration
OnlineActivationParams activationParams = new OnlineActivationParams();
activationParams.setActivationCallback(this);
activationParams.setOrchestrationUser(new OrchestrationUser(userId));
activationParams.setActivationPassword(activationPassword);
// Used for custom password instead of default one
orchestrator.setUserAuthenticationCallback(orchestrationCallback,
new UserAuthenticationCallback.UserAuthentication[]
{UserAuthenticationCallback.UserAuthentication.PASSWORD});
// Show progress dialog & start activation
progressDialog = UIUtils.displayProgress(this, getString(R.string.dialog_progress_activating));
orchestrationCallback.setProgressDialog(progressDialog);
orchestrator.startActivation(activationParams);
}
Since the ActivationActivity
implements the OnlineActivationCallback
interface, it should override all the declared callback methods inside it. The OnlineActivationCallback
interface is used by the Orchestration SDK Client to interact with the Customer Mobile Application during the activation process. As seen in the sample code below, the following methods have been implemented for a successful activation and interaction with the integrated mobile app considering all the scenarios:
onActivationStepComplete
: the method will be called upon each successful activation step. ThecommandSender
will send the produced command each time to the server.onActivationSuccess
: The method will be called upon the success of the activation process.onActivationInputError
: The method will be called upon activation process error due to incorrect user input. The possible errors are listed in theOrchestrationErrorCodes
class.onActivationAborted
: The method will be called upon the cancellation of the activation process.
Below are the definitions of the methods as appear in the sample app.
@Override
public void onActivationStepComplete(String command) {
// Initialize custom async task for sending an orchestration command to the server
CommandSender commandSender = new CommandSender(getApplicationContext(), new CommandSenderCallback() {
@Override
public void onCommandSendingFailure() {
// Hide progress dialog and display error message
UIUtils.hideProgress(progressDialog);
UIUtils.displayAlert(ActivationActivity.this, getString(R.string.dialog_error_title),
getString(R.string.dialog_error_content_sending));
}
@Override
public void onCommandSendingSuccess(String serverCommand) {
// Handle server command
orchestrator.execute(serverCommand);
}
});
// Send command to server
commandSender.execute(command);
}
@Override
public void onActivationSuccess() {
// Hide progress
UIUtils.hideProgress(progressDialog);
// Store activated user identity in the local preferences
SharedPreferencesStorage userStorage = new SharedPreferencesStorage(this);
userStorage.setCurrentUser(userId);
// Back to calling activity
setResult(Activity.RESULT_OK);
finish();
}
@Override
public void onActivationAborted() {
// Hide progress
UIUtils.hideProgress(progressDialog);
// Display cancel message
Log.d(TAG, "Activation cancelled by user");
UIUtils.displayAlert(this, "Activation cancelled", "Activation cancelled by user");
}
@Override
public void onActivationInputError(OnlineActivationInputError error) {
// Hide progress
UIUtils.hideProgress(progressDialog);
// User got it wrong, display specific error
Log.e(TAG, "Exception in onActivationError", error.getActivationInputException());
switch (error.getErrorCode()) {
case OrchestrationErrorCodes.USER_ID_NULL_OR_EMPTY:
userIdView.setError("User ID is null or empty");
break;
case OrchestrationErrorCodes.USER_ID_WRONG_FORMAT:
userIdView.setError("User ID contains invalid characters");
break;
case OrchestrationErrorCodes.ACTIVATION_PASSWORD_NULL_OR_EMPTY:
activationPasswordView.setError("The activation password is null or empty");
break;
case OrchestrationErrorCodes.ACTIVATION_PASSWORD_WRONG_LENGTH:
activationPasswordView.setError("The activation password has a wrong length");
break;
case OrchestrationErrorCodes.ACTIVATION_PASSWORD_WRONG_CHECKSUM:
activationPasswordView.setError("The activation password is invalid");
break;
default:
UIUtils.displayAlert(this, "Error", "Unknown error");
break;
}
}
In the code block above, if the activation process encounters zero errors, the onActivationStepComplete
method will get called multiple times, communicating the required commands to the server. Then it will hand the control to onActivationSuccess
which in turn will finish the activation process and take the end-user the welcome page of the mobile application. Meanwhile, if an error occurred, the onActivationInputError
will handle it. However if the activation was aborted for any reason, the onActivationAborted
will take over and cancel the activation process in a proper way.
In this blog, we have highlighted the activation process of an authenticator through the integration of the Orchestration SDK. If you have any questions regarding this blog, feel free to reach us on the OneSpan Community Portal Forums.