ASEE mToken
Solution concept
mToken is a comprehensive security solution powered by the ASEE Mobile Token SDK that provides comprehensive Two-Factor Authentication (2FA) and transaction signing capabilities. Designed to replace physical hardware tokens, it embeds directly into mobile applications to secure user identities and authorize financial transactions. The solution works alongside the ASEE Security Access Server (SxS) and Secure Mobile Applications Platform (SMAP) to ensure end-to-end security, managing the entire lifecycle of the software token from activation to recovery.
The following documentation is intended for security managers, project managers, business analysts, and developers and contains information about mToken functionalities, security features, and technical limitations.
How does mToken work?
mToken incorporates banking-grade security into a running application by utilizing an SDK that manages cryptographic operations and secure storage independently of the main business logic. The technology ensures that sensitive data, such as PINs, OTPs, and encryption keys, are never stored in plain text but are managed via secure classes and wiped immediately after use.
When a security event occurs, such as a login request or payment confirmation, mToken detects the requirement (via Push Notification or QR code) and calculates the necessary One Time Password (OTP) or Message Authentication Code (MAC) using the device's secure storage. By using the application to continuously monitor security parameters, such as PIN strength, biometric integrity, and inactivity time, transactions can be identified and authorized immediately without human intervention on the server side.
Supported platforms and languages
There are two versions of the Mobile Token SDK, built for Android and for iOS.
Android Mobile Token SDK is written in Java language but is fully compatible with other Java languages supported on Android, like Kotlin. This framework can be used for target devices from Android KitKat (API level 19) and higher.
iOS Mobile Token SDK is available in two builds, a build for Swift and a build for Objective-C. Both versions have all the capabilities in terms of runtime self-protection and utilize the iOS Keychain for secure storage. This framework can be used for target devices iOS 8.0 and higher.
Confirm identity for action execution with OTP
Actor: Customer, End User, SxS
Goal: Confirm that the end user is the one requesting the execution of the action
Preconditions:
- End user must have an enrolled token.
Steps:
- End user attempts to execute an action that can be considered risky
- Customer asks the user to confirm their identity using an OTP.
- End user opens an application that generates OTPs.
- End user types in their OTP and authorizes the execution of the action
- Customer validates the OTP with the SxS:
- If OTP validation succeeds, the action can be executed
- If OTP validation fails, the action is blocked
Result: The system ensures that only the authenticated end user can execute risky actions, enhancing security and accountability.
Confirm identity for action execution with dynamic linking
Actor: Customer, End User, SxS
Goal: Confirm that the end user is the one requesting the execution of the action.
Preconditions:
- End user must have an enrolled token.
Steps:
- End user attempts to execute an action that must be linked to the token.
- Customer asks the user to generate a MAC based on data that is shown to the user. The data has to be based upon a repeatable MAC input (Hash of a file, or a UUID linked to the file). This data is generated by the customer.
- End user opens an application that can calculate MACs. They enter the shown data.
- End user types in their MAC and authorizes the execution of the action
- Customer validates the MAC and MAC input data with the SxS:
- If MAC validation succeeds, the action can be executed
- If MAC validation fails, the action is blocked
Result: The system ensures that only the authenticated end user can execute risky actions, enhancing security and accountability. The action is now linked to the MAC generated. This means that with the same inputs, we can always get the same MAC.
Using SMS for confirming identity for action execution
Actor: Customer, End User, SxS
Goal: Confirm that the end user has control over the mobile phone number that is added to the Customer database.
Preconditions:
- End user must have an SMS token.
Steps:
- End user attempts to execute an action.
- Customer sends an SMS with OTP to the defined mobile phone number using SxS send SMS methods.
- End receives the SMS and sees the OTP.
- End user types in their OTP and authorizes the execution of the action
- Customer validates the OTP with the SxS:
- If OTP validation succeeds, the action can be executed
- If OTP validation fails, the action is blocked
Result: The system ensures that only the owner of the mobile phone number can execute the requested action.
Using PUSH notifications to give consent and dynamically link the action
Actor: Customer, End User, SxS
Goal: Confirm the identity of the user by leveraging application PUSH notifications.
Preconditions:
- End user must have an enrolled mToken
- End user application must be able to receive PUSH notifications.
- End user application must be connected to the internet.
- Customer backend must be able to handle callback methods.
Steps:
- End user attempts to execute an action.
- Customer requests from the SxS to send a PUSH notification to the end user with a given MAC input data, and a callback location.
- End receives the PUSH request and authorizes the action.
- SxS receives the MAC and MAC input data from the mobile application.
- SxS validates the MAC using the MAC input data.
- SxS calls the callback location with a result. If the result was successful, an OTP is given as well
- Customer validates the OTP with the SxS to confirm the validation process.
- If OTP validation succeeds, the action can be executed
- If OTP validation fails, the action is blocked
Result: The system ensures that only the owner of the application can execute the requested action.
Activation of mToken
Actor: Customer, End User, SxS
Goal: Enroll the mToken on the customer application.
Preconditions:
- Customer must either have a mToken SDK integrated into their mobile application or have a mToken standalone application.
Steps:
- End user requests the activation codes for mToken
- Customer backend calls the SxS to assign a token to the user and generate activation codes
- The codes are sent via SMS and email to the customer.
- The customer enters the codes and the mToken is activated
Result: The mToken is active and enrolled.
Technologies used
Docker – SxS is deployed as Docker container
Postman – All methods that are used as a part of this chapter are prepared in the attached postman collection
SxS healthCheck
URL: {{base-url-sxsadminws}}/api/healthCheck
Response:
Response Code: 200
Body:
{
"message": "Service is alive and well."
}
Create SxS user
Actor: Customer, SxS
Goal: Create a user on the SxS to which we will be able to add tokens.
Steps:
- User runs the Docker deploy CLI command. This command will download the preconfigured SxS.
- Run the healthCheck method to validate that the SxS is active and ready.
- Run the createUser method that was provided as part of the Postman collection.
Result: SxS is up and running, and a user was created
Summary
The purpose of this chapter is to explain the process of deploying SxS and the creation of the first end user on the SxS. SxS will come preloaded with mToken licenses, which will be used later in the process of activating mTokens. As a result of this chapter, you will have a fully deployed and operational SxS as well as a user that can be used later for authentication.
Methods
The following is a list of methods and CLI commands that will be used as part of this chapter.
Docker CLI
docker run –name sxs -p 442:442 -d sxs:latest
CreateSxSUser
URL: {{base-url-sxsadminws}}/UserAdministrationService
Body:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:impl="http://impl.user.webservice.sxsadmin.sxs.asseco.hr" xmlns:hsm="http://hsm.exposed.sxsadmin.sxs.asseco.hr/">
<soapenv:Header/>
<soapenv:Body>
<impl:createOrUpdateSxsUser>
<sxsUserWS>
<address>Address</address>
<email>test.user@gmail.com</email>
<firstName>Test</firstName>
<userId>test_user</userId>
<lastName>User</lastName>
<mobile>+385991234567</mobile>
</sxsUserWS>
</impl:createOrUpdateSxsUser>
</soapenv:Body>
</soapenv:Envelope>
Response: This method has no return value
Process
The following steps need to be executed to be able to run the SxS and create a user that will be later used:
- On a machine, run the docker run CLI command:
docker run –name sxs -p 442:442 -d sxs:latest
- Once the execution is done, run the following methods from the Postman collection. Make sure that the URL environment variable targets your Docker instance:
a. SxSAdminWS-healthCheck
b. SxSWS-healthCheck
- To create the user, run the following methods from the Postman collection
a. CreateSxSUser
mToken Biometrics
Actor: Customer, End User, Token SDK, Android OS, iOS
Goal: Enable biometric authentication (fingerprint, face) to allow the user to access the token without entering a PIN.
Preconditions:
- Token must be successfully activated (see previous chapter).
- Device must run Android 6.0 (Marshmallow) or higher.
- User must have biometrics enrolled on the device (e.g., at least one fingerprint registered).
- Biometric sensor must conform to Class 3 (formerly "Strong") classification for Face, or Class 2/3 for Fingerprint.
Steps:
- Application checks if the token supports biometrics and if the device has biometrics capability.
- User requests to enable biometrics (usually via a Switch in Settings).
- Application prompts the user for their current PIN (required to encrypt the biometric key).
- Application calls
secureTokenWithBiometrics(...)on a background thread. - User scans their biometric (fingerprint/face) when prompted by the system.
- SDK encrypts the PIN and stores it securely using the Android Keystore (TEE or StrongBox).
Result: The token is secured with biometrics. Future logins can be performed using loadTokenWithBiometrics, which decrypts the stored PIN upon successful biometric authentication.
Summary
The purpose of this chapter is to explain how to enhance user experience by implementing biometric login. Instead of typing a PIN for every transaction or login, the user can authenticate using the device's hardware sensors.
The Token SDK supports Android X Biometrics (recommended) and native Android Biometrics. When enabled, the SDK creates a secure cryptographic key protected by the hardware (Trusted Execution Environment or StrongBox). This key encrypts the user's PIN. When the user successfully authenticates via biometrics, the PIN is decrypted and used internally to load the token.
Methods
isBiometricsAvailable()- Checks if the device hardware supports biometrics and if the user has enrolled data (e.g., fingerprints).
getTokenBiometricState(String)- Returns the specific state of biometrics for a token (e.g., LOCKED, NOT_ENROLLED, SECURED).
secureTokenWithBiometrics(...)- Enables biometric security. Must be called on a background thread.
loadTokenWithBiometrics(...)- Unlocks/Loads the token using biometrics. Unlocks/Loads the token using biometrics. Must be called on a background thread.
removeTokenBiometricsSecurity(...)- Disables biometric login and reverts to PIN-only mode.
createBiometricsCancellationWrapper(...)- Creates a wrapper to handle the cancellation of the biometric prompt (e.g., if the user taps "Cancel").
Process
Integrating biometrics involves handling hardware availability, threading (as biometric operations are blocking), and callbacks for UI updates.
Check availability
Before showing a "Use Biometrics" switch in your UI, verify that the specific token and device are ready. Use getTokenBiometricState to handle specific edge cases (like the user having hardware but no fingerprints enrolled).
Configure Biometric Mechanism
The SDK supports multiple mechanisms. It is strongly recommended to use ANDROID_X_BIOMETRICS as it ensures backwards compatibility and consistent UI handling across Android versions.
Enable Biometrics
This operation requires the user's current PIN. Since this method blocks execution until the user scans their finger (or cancels), it must be run on a background thread. You must implement the IBiometricProgress interface to receive updates.
void secureTokenWithBiometrics(String tokenName, CharArrayExt pin, ServerInfo serverinfo) {
// Biometric authentication mechanism stored in this class's field
biometricAuthenticationMechanism = BiometricAuthenticationMechanism.BIOMETRIC_PROMPT_BIOMETRICS;
// Biometrics cancellation wrapper stored in this class's field.
biometricsCancellationWrapper = TokenFacade.createBiometricsCancellationWrapper(biometricAuthenticationMechanism);
// NOTE: handling of disposable purposely left out. Disposable must be handled in order not to get garbage collected.
Completable.fromAction(() -> {
TokenFacade.getToken(tokenName)
.secureTokenWithBiometrics(
pin,
serverinfo,
biometricsCancellationWrapper,
new IBiometricProgress() {
@Override
public void onFingerAuthenticated() {
// Dismiss UI element indicating that fingerprint scanning is in progress,
// and replace with loading indicator for example.
}
@Override
public void onAuthenticationFailed() {
// Display that an error has occurred during fingerprint scanning.
}
},
BiometricPromptText.createWithRequiredFieldsOnly("Title", "Cancel"),
false,
BiometricSecuritySpecification.DEFAULT,
biometricAuthenticationMechanism,
null
);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
this::processSecureTokenSuccess,
this::processSecureTokenFailure
);
}
private void processSecureTokenSuccess() {
// Continue with business logic which must be done when token action related to biometrics is done.
// This is the place do dismiss „Loading UI“ element which was shown in „onFingerprintAuthenticated“ callback.
}
Login with Biometrics
To use the token later, use loadTokenWithBiometrics. This replaces the standard loadToken method. Like the enabling process, this must be done on a background thread.
Handling Biometric invalidation
If you set invalidateOnFingerprintEnrollment = true during setup, and the user subsequently adds a new fingerprint to their Android settings, the token biometric link becomes invalid for security reasons.
- Detection:
getTokenBiometricState()returnsTOKEN_BIOMETRICS_INVALIDATED_DUE_TO_NEW_FINGERPRINT. - Resolution: You must call
removeTokenBiometricsSecurity(...)and then ask the user to re-enable biometrics (re-enter PIN) viasecureTokenWithBiometrics(...).
Token activation
Actor: Customer, End User, SxS
Goal: Activate the mobile token so it can be used for authentication operations.
Preconditions:
- Customer mobile application must have the Token SDK integrated.
- Activation codes (16-digit string) must be generated and distributed to the end user.
- Token name (unique identifier) must be defined by the developer.
Steps:
- End user receives the activation codes (first 8 digits =
clientID; second 8 digits =activationCode). - Customer backend calls SxS to generate and distribute activation codes to the user.
- The end user enters the activation codes and defines a PIN.
- The application invokes the SDK method
activateAndLoad(...)with:tokenName(unique identifier)clientID(first 8 digits)activationCode(second 8 digits)- optionally
userId, if SxS is configured to validate it
- The SDK validates the activation codes. If incorrect codes are entered three times (or the SxS-configured limit), the token cannot be activated anymore even with correct codes.
- If successful, the token is activated, securely stored on disk/KeyChain, and remains available for retrieval via
getToken(tokenName).
Result: The token is successfully activated, securely stored, and in the loaded state. A token with the same tokenName cannot be activated again unless the existing token is deleted using deleteTokenFromStorage().
Summary
The purpose of this chapter is to explain the integration steps required to activate a mobile token on the end user's device. While the previous chapter dealt with the server-side user creation, this chapter focuses on binding the mobile application instance to that user securely.
Token activation is the process where the application exchanges the activation codes (obtained from the SxS via the backend) and a user-defined PIN for a secure, encrypted token stored on the device. As a result of this chapter, the mobile application will hold an active token capable of generating OTPs, signatures, and performing authentication.
Methods
The following is a list of SDK methods and API endpoints that will be used as part of this chapter.
SDK
mtmRedistributeToken
URL: http://host:port/SxSAdminWS/services/MobileTokenManagementService
SxS
mtmRedistributeToken
URL: http://host:port/SxSAdminWS/services/MobileTokenManagementService
Body:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:impl="http://impl.mtm.webservice.sxsadmin.sxs.asseco.hr" xmlns:hsm="http://hsm.exposed.sxsadmin.sxs.asseco.hr/">
<soapenv:Header/>
<soapenv:Body>
<impl:mtmRedistributeTokenRequest>
<sxsUserWS>
<userId>new_user</userId>
</sxsUserWS>
<tokenProfileId>1393</tokenProfileId>
<serviceIds>6</serviceIds>
</impl:mtmRedistributeTokenRequest>
</soapenv:Body> </soapenv
Response: This method returns the tokenSN of the enrolled mobile token.
mtmRenewActivationCode
URL: http://host:port/SxSAdminWS/services/MobileTokenManagementService
Body:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:impl="http://impl.mtm.webservice.sxsadmin.sxs.asseco.hr">
<soapenv:Header/>
<soapenv:Body>
<impl:mtmRenewActivationCodeRequest>
<tokensn>2000038252</tokensn>
<generateNew>true</generateNew>
</impl:mtmRenewActivationCodeRequest>
</soapenv:Body>
</soapenv:Envelope>
mtmGetActivationCode
Body:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:impl="http://impl.mtm.webservice.sxsadmin.sxs.asseco.hr">
<soapenv:Header/>
<soapenv:Body>
<impl:mtmGetActivationCodeRequest>
<tokensn>2000038252</tokensn>
<formatId>1</formatId>
</impl:mtmGetActivationCodeRequest>
</soapenv:Body>
</soapenv:Envelope>
Response: This method has returned the Activation code.
Process:
SDK initialization
Before attempting the activation, the Token SDK must be initialized. This should ideally happen in the onCreate() method of your Application class to ensure it's ready before any UI is shown.
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//
// Handle initialization error
}
}
}
Obtain activation codes
Before the mobile application can activate a token, the Customer Backend must provision the token on the SxS and retrieve the credentials. This is a three-step process performed via the MobileTokenManagementService SOAP API:
- Enroll the Token (
mtmRedistributeToken): Call this method with the target userId and tokenProfileId. The response will contain the Token Serial Number (tokensn), which is required for the subsequent steps. - Generate Code (
mtmRenewActivationCode): Call this method using the tokensn obtained in step 1 with the flag generateNew set to true. This triggers the generation of a fresh code on the server. - Fetch Code (
mtmGetActivationCode): Call this method using the tokensn to retrieve the actual activation string. Set formatId to 1 to get the full 16-digit code.
Result: The backend receives a 16-digit string. This must be split and provided to the user:
- Digits 1–8:
ClientID - Digits 9–16:
ActivationCode
Check for existing token
Before calling the activation method, it is best practice to check if a token with the desired name already exists to avoid exceptions.
String tokenName = "MyMobileToken"; // Unique identifier defined by developer
try {
if (TokenFacade.hasToken(tokenName)) {
// Token already exists.
// Logic to delete the old token or skip activation.
}
} catch (TokenException e) {
// Handle check error
}
Activate the Token
Once the user inputs the codes and defines a PIN, call the activateAndLoad method. Note that sensitive data uses CharArrayExt instead of standard Strings for security reasons.
// Prepare input data
String tokenName = "MyMobileToken";
CharArrayExt clientId = new CharArrayExt("12345678"); // First 8 digits
CharArrayExt actCode = new CharArrayExt("87654321"); // Second 8 digits
CharArrayExt pin = new CharArrayExt("1234"); // User defined PIN
CharArrayExt licenseKey = new CharArrayExt("YOUR_LICENSE_KEY");
ServerInfo serverInfo = new ServerInfo(); // Configure server connection details
try {
// Perform Activation
TokenFacade token = TokenFacade.activateAndLoad(
tokenName,
clientId,
actCode,
licenseKey,
pin,
serverInfo
);
// Result: Token is now active, loaded, and ready for use
} catch (TokenException e) {
// Handle activation failure
// e.g., Invalid codes, network error, or activation limit reached
int errorCode = e.getErrorCode();
}
Note: If the activation fails 3 times (default SxS configuration) due to incorrect codes, the activation string becomes invalid and a new one must be generated via the backend.
OTP Validation
Actor: Customer, End User, SxS
Goal: Verify the validity of a generated OTP
Preconditions:
- Token must be in the loaded state (unlocked with PIN).
- Device must have network access to reach the SxS.
Steps:
- The end user triggers an action (e.g., Login) on the mobile app.
- The mobile SDK generates an OTP using the OTP_APP slot.
- The mobile app sends this OTP (and username/tokenSN) to the Customer Backend.
- The Customer Backend invokes the validateOtp SOAP method on the SxS.
- The SxS checks the OTP against its internal records.
- The SxS returns a success response (TokenSN/UserID) or an exception (Wrong OTP).
Result: The user is either authenticated (success) or rejected (failure/lockout).
Summary
The purpose of this chapter is to explain the server-side validation of the OTP. After the mobile application generates an OTP locally, it must be verified by the central authentication server (SxS) to ensure it matches the expected value. This process confirms the user's identity and that they are in possession of the specific mobile device.
Methods
validateOtp
URL: http://host:port/SxSWS/SxS5Authentication
Body:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut= "http://authentication.ws.sxs.logos.hr">
<soapenv:Header/>
<soapenv:Body>
<aut:validateOtpRequest>
<otp>740627</otp>
<TokenSN>2000038252</TokenSN>
<applicationProfileName>OTP_APP</applicationProfileName>
<!--<UserID>test</UserID>-->
</aut:validateOtpRequest>
</soapenv:Body>
</soapenv:Envelope>
Response: If OTP is correct, only tokenSN (and userID) are returned, otherwise, an error will be returned (with code and message).
Process
The validation process begins when the mobile application sends the locally calculated OTP and the user's identifier (Token Serial Number or UserID) to the Customer Backend. Upon receiving these details, the backend must construct a SOAP request to the SxS5Authentication web service, specifically invoking the validateOtp method. It is critical to include the Organization ID in the HTTP headers and ensure the applicationProfileName parameter is set to "OTP_APP".
Once the request is sent, the backend must parse the SOAP response from the SxS to determine the outcome. In a successful scenario, the SxS returns the tokenSN and userId without errors, indicating the OTP is valid. However, if the validation fails (e.g., due to an incorrect OTP or a locked token), the response will contain an exception object detailing the specific exceptionCode and exceptionMessage. The backend should use this information to approve the user's login or return an appropriate error message to the client.


