Skip to main content

Activation

Before proceeding with activation, users must obtain an activation code. For testing purposes this can be done via a REST API. Refer to the User Activities API documentation for step-by-step instructions on generating this activation code.

When a StartResultEvent with ACTIVATION_REQUIRED as sdkState is received in response to the StartEvent, users should initiate the Activation flow.

This involves calling IdpSdkNativeInterface.getAuthorizationCode with the user's username, activation code, and password provided through the IdpSdkInteractionInterface callback. Follow the three-step flow in the correct sequence for a successful activation.

Note: In Shift Lite, activation is already a login process — a StartLoginEvent will not be triggered after a completed activation. Once activation completes with StatusType.OK, the user is both activated and logged in with a valid token set. A login will be required again after an app restart, an MC-SDK restart, or when stored tokens have been cleared — however, a restart is not a full logout: the full token set received at activation enables the Stay Logged In feature (OfflineLoginEvent), which can re-authenticate the user as long as valid tokens are still present — either silently (no authentication required) or by prompting for biometrics, depending on the configured AuthenticationMode. See Login for post-restart flow options (see also Restart Event and Logout).


IdpSdk Activation Flow Diagram

The event flow diagram illustrates the sequence of events during the activation process when using the IdpSdk directly.


Implementation Examples

Android/Kotlin

Implement IdpSdkInteractionInterface to supply credentials when the SDK requests them. The SDK calls provideCredentials with the required input fields via interactionData.inputFieldIds — iterate over them and return a HashMap with the filled values.

Warning: provideCredentials is called from a separate thread. Your implementation must be thread-safe; any access to shared state in this scope must be synchronized. It may also be called multiple times in multi-step flows. See provideCredentials Behaviour for details on field IDs, multi-step flows, and error propagation.

IdpSdkInteractionInterface — provideCredentials (Kotlin)
class ActivationHandler {
companion object : IdpSdkInteractionInterface {

const val ACTIVATION_CLIENT = "KssIdpEnrollment"

// Called by the SDK from a background thread to collect user credentials.
// Must be thread-safe.
override fun provideCredentials(interactionData: IdpSdkInteractionData): IdpSdkProvideCredentialsResult {
val credentials = HashMap<String?, String?>()

for (fieldId in interactionData.inputFieldIds) {
when (fieldId) {
IdpSdkConstants.USERNAME -> credentials[fieldId] = "<username>"
IdpSdkConstants.PASSWORD -> credentials[fieldId] = "<password>"
IdpSdkConstants.ACTIVATION_CODE -> credentials[fieldId] = "<activation-code>"
}
}

// To cancel the flow and propagate an error, return:
// IdpSdkProvideCredentialsResult(IdpSdkError(subsystem, errorCode, errorDescription))

return IdpSdkProvideCredentialsResult(credentials)
}
}
}

The full three-step activation flow:

Activation Flow (Android/Kotlin)
fun activate() {
// Step 1 — get AST client data from the MC-SDK
val getAstClientDataEvent = GetAstClientDataEvent(IdpSdkApp.TENANT_ID)

MasterController.getInstance()?.postEvent(getAstClientDataEvent)?.then { resultEvent ->
when (resultEvent) {
is GetAstClientDataResultEvent -> {
if (resultEvent.status != StatusType.OK) {
Log.e(TAG, "GetAstClientData failed: ${resultEvent.errorDescription}")
return@then
}

// Step 2 — get authorization code from the IdpSdk
val astClientDataInfo = AstClientDataInfo(
resultEvent.clientData,
resultEvent.astClientId,
resultEvent.codeChallenge,
resultEvent.codeChallengeMethod
)

// userId is null for first activation (no user enrolled yet)
val userId: String? = null

IdpSdkNativeInterface.getAuthorizationCode(
astClientDataInfo,
ACTIVATION_CLIENT,
this, // IdpSdkInteractionInterface — provideCredentials called here
userId,
traceParent // optional W3C-compliant trace parent, or null
)?.thenApply { idpSdkResult ->
if (idpSdkResult.hasError()) {
Log.e(TAG, "getAuthorizationCode failed: ${idpSdkResult.idpSdkError}")
return@thenApply
}

// Step 3 — pass the authorization code to the MC-SDK
val authorizationCode = idpSdkResult.authorizationCode
val setEvent = SetAuthorisationCodeEvent(
IdpSdkApp.TENANT_ID,
AuthenticationMode.BIOMETRIC,
authorizationCode,
ACTIVATION_CLIENT
)

MasterController.getInstance()?.postEvent(setEvent)?.then { setResult ->
when (setResult) {
is SetAuthorisationCodeResultEvent -> {
if (setResult.status == StatusType.OK) {
Log.i(TAG, "Activation successful")
} else {
Log.e(TAG, "SetAuthorisationCode failed: ${setResult.errorDescription}")
}
}
else -> error("Unexpected result for SetAuthorisationCodeEvent")
}
}
}
}
else -> error("Unexpected result for GetAstClientDataEvent")
}
}
}

Request Parameters

The following credential fields are requested by the IdpSdk during activation via provideCredentials:

IdpSdkConstants.USERNAME        — the user's username
IdpSdkConstants.PASSWORD — the desired password
IdpSdkConstants.ACTIVATION_CODE — the one-time activation code

The clientId passed to getAuthorizationCode is provided by the KOBIL IDP services (e.g. KssIdpEnrollment).


Important Notes

For more information about MC-SDK event usage during IdpSdk flows, please refer to GetAstClientData and SetAuthorisationCode.

Response Handling

IdpSdkNativeInterface.getAuthorizationCode returns a CompletableFuture<IdpSdkResult>. Check idpSdkResult.hasError() before accessing idpSdkResult.authorizationCode.

In response to the SetAuthorisationCodeEvent, the MC-SDK sends a SetAuthorisationCodeResultEvent with the appropriate status.