Skip to main content

Add User

Adding a user is not a distinct flow — it is the Activation flow performed when at least one user is already enrolled on the device. You can identify this situation by the sdkState in the StartResultEvent: when another user is already activated, the state will be LOGIN_REQUIRED rather than ACTIVATION_REQUIRED. Performing an activation in this state enrolls an additional user.

Before proceeding, you must obtain an activation code for the new user. Refer to the User Activities API documentation for step-by-step instructions on generating this activation code for testing purposes.


IdpSdk Add User Flow Diagram

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


Implementation Examples

Android/Kotlin

Adding a user reuses the same IdpSdkInteractionInterface pattern as activation. 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 for Add User (Kotlin)
class AddUserHandler {
companion object : IdpSdkInteractionInterface {

const val ENROLLMENT_CLIENT = "KssIdpEnrollment"

// Called by the SDK from a background thread to collect new user's 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] = "<new-username>"
IdpSdkConstants.PASSWORD -> credentials[fieldId] = "<new-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 add user flow:

Add User Flow (Android/Kotlin)
fun addUser() {
// 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
)

// Pass the existing enrolled user's userId so the SDK can associate
// the new enrollment with the existing device binding.
// Pass null if this is the very first user on the device.
val userId: String? = StartRestartHandler.getFirstUserId()

IdpSdkNativeInterface.getAuthorizationCode(
astClientDataInfo,
ENROLLMENT_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,
ENROLLMENT_CLIENT
)

MasterController.getInstance()?.postEvent(setEvent)?.then { setResult ->
when (setResult) {
is SetAuthorisationCodeResultEvent -> {
if (setResult.status == StatusType.OK) {
Log.i(TAG, "Add user 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 add user via provideCredentials:

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

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.