Skip to main content
Version: v0.6

Holder Functions

This section guides you through the essential steps required to integrate with the Kiwa eLicense SDK. You’ll learn how to set up an application with the appropriate scopes, request a wallet certificate, and interact with the licensing system. Specifically, you'll cover:

  • Creating an application with the correct scopes
  • Requesting a wallet certificate
  • Assigning a license to a device
  • Issuing a license for a license holder
  • Confirming that license issuance was successful

By the end of this section, you will have a working setup capable of securely communicating with the Kiwa APIs and managing license lifecycles.

Prerequisites​

Before using the Kiwa eLicense SDK, please ensure the following setup is complete:

Dependencies​

Ensure your project includes the necessary Kiwa eLicense SDK modules. For Android this is com.sphereon.kiwa:kiwa-holder-sdk-impl:<version>. See getting started and installation for more information.

Setup Dependency Injection​

Generate your components or use predefined DI components for the scopes available in the Kiwa eLicense SDK. See dependency injection for more information.

Environment Variables​

Set the necessary environment variables to authenticate with Kiwa APIs:

  • KIWA_SUBSCRIPTION_KEY: Your unique subscription key provided by Kiwa.

Example: KIWA_SUBSCRIPTION_KEY=your_subscription_key_here

Obtaining a wallet certificate​

note

The below code uses service names that can be found in the dependency injection page.

Before performing any license operations, you need to authenticate and obtain a wallet certificate:

// Request a certificate, with the optional environment parameter. If omitted, the default environment will be used from the configuration service (Acc by default if nothing is configured)
val certificateResult = authService.getWalletCertificate(GetWalletCertificateRequestOpts(environment = ApiEnvironment.ACC))
certificateResult.onSuccess { result ->
// Certificate successfully obtained
println("Certificate obtained: ${result.success}")
}.onFailure { error ->
// Handle error println("Error obtaining certificate: ${error.message.defaultMessage}")
}

License Operations​

Assigning a License​

The following command can be executed once an e-license has been issued to a user's email address via the Kiwa IA API. This will also provide the activation code needed to assign the license.

To assign a license to a device/holder:

// Create a request with activation code and email
val assignRequest = AssignDeviceLicenseRequest(
code = "your_activation_code_here",
email = "user@example.com"
)

// Assign the license
val assignResult = holderService.assignLicense(assignRequest)
assignResult.onSuccess { result ->
// License successfully assigned
println("License assigned successfully: ${result.success}")
}.onFailure { error ->
// Handle error
println("Error assigning license: ${error.message.defaultMessage}")
}

Issuing a license​

The below command will retrieve all available licenses in Mdoc format. Internally, it will also validate the licenses for correctness, like signatures, dates, certificates, and CBOR document structure.

To retrieve licenses available for the authenticated holder:

// Issue the license
val issueResult = holderService.issueLicense()
issueResult.onSuccess { result ->
// Process the raw license data
val encodedCbor: ByteArray = result.raw

// Decode the CBOR-encoded license
val license = ElicenseIssueDocuments.decodeCbor(encodedCbor)

// Convert to JSON for display or processing
val licenseJson = license.toJson()
println(licenseJson.toJsonString())

// Convert to a simplified display format
val simpleDisplay = license.toSimpleDisplay()
println(CborJsonSupport.serializer.encodeToString(simpleDisplay))
}.onFailure { error ->
println("Error issuing license: ${error.message.defaultMessage}")
}

Confirming license issuance​

After successfully retrieving license(s), confirm the issuance:

// Confirm the license issuance
val confirmResult = holderService.confirmLicense()
confirmResult.onSuccess { result ->
println("License confirmation successful: ${result.success}")
}.onFailure { error ->
println("Error confirming license: ${error.message.defaultMessage}")
}

Complete example​

Here's a complete example that demonstrates the entire process of getting an mTLS certificate and then getting the licenses:

// Create your components
val appComponent = KiwaAppComponent.init(
application = yourApplication, // This can be your mobile app reference instance
appId = "your-app-id", // A string denoting your app
profile = "prod", // A profile so you could have different properties for different environments or profiles of the app
version = "1.0.0" // The version of your app.
)
val contextComponent = appComponent.contextManager.initAnonymous()
val sessionContextManager = contextComponent.sessionContextManager
val sessionComponent = sessionContextManager.initSession("unique-example-session") // A unique value for the session


// Get the main Kiwa service
val kiwa = sessionContextManager.getService<IKiwaServices>(
IKiwaServices.SERVICE_ID
)

// Get a device certificate
kiwa.auth.getWalletCertificate(GetWalletCertificateRequestOpts())
.onSuccess { result ->
println("Certificate obtained: ${result.success}")
}.onFailure { error ->
println("Error obtaining certificate: ${error.message.defaultMessage}")
return
}

// Step 2: Assign license
val activationCode = "your_mailed_activation_code_here"

val assignRequest = AssignDeviceLicenseRequest(
code = activationCode,
email = "user@example.com"
)

// kiwa.holderService.cmd.assign() <= This is the same call as below but then using the command pattern interface
kiwa.holder.assignLicense(assignRequest)
.onSuccess { result ->
println("License assigned successfully: ${result.success}")
}.onFailure { error ->
println("Error assigning license: ${error.message.defaultMessage}")
return
}

// Step 3: Issue license
kiwa.holder.issueLicense()
.onSuccess { result ->
println("License issued successfully")

// The default way to access the license documents. They have been validated already at this point
val documents: ElicenseIssueDocumentsCbor = issueLicensResult.documents

// If you really want access to the raw bytes of the mDoc documents
val encodedCbor: ByteArray = issueLicenseResult.raw
// Decode the CBOR-encoded licenses
val licenses = ElicenseIssueDocumentsCbor.decodeCbor(encodedCbor)
// Convert to JSON for display or processing
val licenseJson = licenses.toJson()
println("License JSON: ${licenseJson.toJsonString()}")
// Convert to a simplified display format
val simpleDisplay = license.toSimpleDisplay()
println("Simple display: ${CborJsonSupport.serializer.encodeToString(simpleDisplay)}")
}.onFailure { error ->
println("Error issuing license: ${error.message.defaultMessage}")
return
}

// Step 4: Confirm license issuance
kiwa.holder.confirmLicense()
.onSuccess { result ->
println("License confirmation successful: ${result.success}")
}.onFailure { error ->
println("Error confirming license: ${error.message.defaultMessage}")
}

eLicense Mdoc and verification​

More information about the eLicense Mdoc format, display formats and engagement/presentation to verifiers can be found in the Kiwa eLicense Mdoc and IDK Mdoc engagemnet documentation.