Skip to content

Commit 4fe2def

Browse files
cy245yrezgui
andauthored
Identity add holder issuance snippets (#872)
* Add password-only snippet * Add holder issuance handling snippets * Apply Spotless * Updated formatting --------- Co-authored-by: cy245 <2625507+cy245@users.noreply.github.com> Co-authored-by: Yacine Rezgui <rezgui.y@gmail.com>
1 parent b99814d commit 4fe2def

3 files changed

Lines changed: 92 additions & 6 deletions

File tree

gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ androidx-protolayout-expression = { module = "androidx.wear.protolayout:protolay
203203
androidx-protolayout-material = { module = "androidx.wear.protolayout:protolayout-material", version.ref = "protolayout" }
204204
androidx-protolayout-material3 = { module = "androidx.wear.protolayout:protolayout-material3", version.ref = "protolayout" }
205205
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
206-
androidx-registry-digitalcredentials = { module = "androidx.credentials.registry:registry-digitalcredentials-openid", version.ref = "registryDigitalCredentials" }
206+
androidx-registry-digitalcredentials-openid = { module = "androidx.credentials.registry:registry-digitalcredentials-openid", version.ref = "registryDigitalCredentials" }
207+
androidx-registry-digitalcredentials-mdoc = { module = "androidx.credentials.registry:registry-digitalcredentials-mdoc", version.ref = "registryDigitalCredentials" }
208+
androidx-registry-digitalcredentials-sdjwtvc = { module = "androidx.credentials.registry:registry-digitalcredentials-sdjwtvc", version.ref = "registryDigitalCredentials" }
207209
androidx-registry-provider = { module = "androidx.credentials.registry:registry-provider", version.ref = "registryDigitalCredentials" }
208210
androidx-registry-provider-play-services = { module = "androidx.credentials.registry:registry-provider-play-services", version.ref = "registryDigitalCredentials" }
209211
androidx-startup-runtime = { module = "androidx.startup:startup-runtime", version.ref = "androidx-startup-runtime" }

identity/credentialmanager/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ dependencies {
6666
// [END android_identity_gradle_dependencies]
6767

6868
// In your app module's build.gradle:
69-
implementation(libs.androidx.registry.digitalcredentials)
69+
implementation(libs.androidx.registry.digitalcredentials.openid)
70+
implementation(libs.androidx.registry.digitalcredentials.mdoc)
71+
implementation(libs.androidx.registry.digitalcredentials.sdjwtvc)
7072
implementation(libs.androidx.registry.provider)
7173
implementation(libs.androidx.registry.provider.play.services)
7274

identity/credentialmanager/src/main/java/com/example/identity/credentialmanager/DigitalCredentialHolder.kt

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ import android.content.Context
2121
import android.content.Intent
2222
import android.util.Base64
2323
import android.util.Log
24+
import androidx.credentials.CreateDigitalCredentialRequest
25+
import androidx.credentials.CreateDigitalCredentialResponse
2426
import androidx.credentials.DigitalCredential
2527
import androidx.credentials.ExperimentalDigitalCredentialApi
2628
import androidx.credentials.GetCredentialResponse
2729
import androidx.credentials.GetDigitalCredentialOption
30+
import androidx.credentials.exceptions.CreateCredentialUnknownException
2831
import androidx.credentials.exceptions.GetCredentialUnknownException
2932
import androidx.credentials.provider.PendingIntentHandler
3033
import androidx.credentials.provider.ProviderGetCredentialRequest
@@ -33,6 +36,7 @@ import androidx.credentials.registry.digitalcredentials.mdoc.MdocField
3336
import androidx.credentials.registry.digitalcredentials.openid4vp.OpenId4VpRegistry
3437
import androidx.credentials.registry.digitalcredentials.sdjwt.SdJwtClaim
3538
import androidx.credentials.registry.digitalcredentials.sdjwt.SdJwtEntry
39+
import androidx.credentials.registry.provider.RegisterCreationOptionsRequest
3640
import androidx.credentials.registry.provider.RegistryManager
3741
import androidx.credentials.registry.provider.digitalcredentials.DigitalCredentialEntry
3842
import androidx.credentials.registry.provider.digitalcredentials.EntryDisplayProperties
@@ -94,9 +98,14 @@ class DigitalCredentialHolderActivity : Activity() {
9498
}
9599
// [END android_identity_mapto_mdoc_entries]
96100

97-
suspend fun registerCredentials(sdJwtsFromStorage: List<StoredSdJwtEntry>, mdocsFromStorage: List<StoredMdocEntry>, registryManager: RegistryManager) {
101+
suspend fun registerCredentials(
102+
sdJwtsFromStorage: List<StoredSdJwtEntry>,
103+
mdocsFromStorage: List<StoredMdocEntry>,
104+
registryManager: RegistryManager
105+
) {
98106
// [START android_identity_register_credential_entries]
99-
val credentialEntries = mapToSdJwtEntries(sdJwtsFromStorage) + mapToMdocEntries(mdocsFromStorage)
107+
val credentialEntries =
108+
mapToSdJwtEntries(sdJwtsFromStorage) + mapToMdocEntries(mdocsFromStorage)
100109

101110
val openidRegistryRequest = OpenId4VpRegistry(
102111
credentialEntries = credentialEntries,
@@ -140,9 +149,11 @@ class DigitalCredentialHolderActivity : Activity() {
140149
// [END android_identity_get_credential_origin]
141150

142151
// [START android_identity_get_signing_cert_hash]
143-
val appSigningInfo = request?.callingAppInfo?.signingInfoCompat?.signingCertificateHistory[0]?.toByteArray()
152+
val appSigningInfo =
153+
request?.callingAppInfo?.signingInfoCompat?.signingCertificateHistory[0]?.toByteArray()
144154
val md = MessageDigest.getInstance("SHA-256")
145-
val certHash = Base64.encodeToString(md.digest(appSigningInfo), Base64.NO_WRAP or Base64.NO_PADDING)
155+
val certHash =
156+
Base64.encodeToString(md.digest(appSigningInfo), Base64.NO_WRAP or Base64.NO_PADDING)
146157
return "android:apk-key-hash:$certHash"
147158
// [END android_identity_get_signing_cert_hash]
148159
}
@@ -169,18 +180,86 @@ class DigitalCredentialHolderActivity : Activity() {
169180
// [END android_identity_get_credential_response_exception]
170181
}
171182
}
183+
184+
@OptIn(ExperimentalDigitalCredentialApi::class)
185+
suspend fun registerIssuance(context: Context) {
186+
// [START android_identity_register_issuance_create_options]
187+
val registryManager = RegistryManager.create(context)
188+
189+
try {
190+
registryManager.registerCreationOptions(object :
191+
RegisterCreationOptionsRequest(
192+
creationOptions = buildIssuanceData(),
193+
matcher = loadIssuanceMatcher(),
194+
type = DigitalCredential.TYPE_DIGITAL_CREDENTIAL,
195+
id = "openid4vci",
196+
) {}
197+
)
198+
} catch (e: Exception) {
199+
Log.e(TAG, "Issuance registration failed.", e)
200+
}
201+
// [END android_identity_register_issuance_create_options]
202+
203+
// [START android_identity_handle_issuance_create_option_selected]
204+
val pendingIntentRequest =
205+
PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)
206+
val request = pendingIntentRequest!!.callingRequest
207+
if (request is CreateDigitalCredentialRequest) {
208+
Log.i(TAG, "Got DC creation request: ${request.requestJson}")
209+
processCreationRequest(request.requestJson)
210+
}
211+
// [END android_identity_handle_issuance_create_option_selected]
212+
}
213+
214+
fun buildIssuanceData(): ByteArray {
215+
return byteArrayOf()
216+
}
217+
218+
fun loadIssuanceMatcher(): ByteArray {
219+
return byteArrayOf()
220+
}
221+
222+
fun processCreationRequest(requestJson: String) {}
223+
224+
@OptIn(ExperimentalDigitalCredentialApi::class)
225+
fun processIssuanceCreationResponse(response: CreateDigitalCredentialResponse) {
226+
// [START android_identity_issuance_return_credential_response]
227+
val resultData = Intent()
228+
PendingIntentHandler.setCreateCredentialResponse(
229+
resultData,
230+
CreateDigitalCredentialResponse(response.responseJson)
231+
)
232+
setResult(RESULT_OK, resultData)
233+
finish()
234+
// [END android_identity_issuance_return_credential_response]
235+
}
236+
237+
fun processIssuanceCreationResponseException() {
238+
// [START android_identity_issuance_handle_credential_exception]
239+
val resultData = Intent()
240+
PendingIntentHandler.setCreateCredentialException(
241+
resultData,
242+
CreateCredentialUnknownException() // Configure the proper exception
243+
)
244+
setResult(RESULT_OK, resultData)
245+
finish()
246+
// [END android_identity_issuance_handle_credential_exception]
247+
}
172248
}
173249

174250
sealed class StoredSdJwtEntry {
175251
fun getVCT(): String {
176252
return ""
177253
}
254+
178255
fun getClaimsList(): List<SdJwtClaim> {
179256
return emptyList()
180257
}
258+
181259
fun toDisplayProperties(): Set<EntryDisplayProperties> {
182260
return emptySet()
183261
}
262+
184263
fun getId(): String {
185264
return ""
186265
}
@@ -190,12 +269,15 @@ sealed class StoredMdocEntry {
190269
fun retrieveDocType(): String {
191270
return ""
192271
}
272+
193273
fun getFields(): List<MdocField> {
194274
return emptyList()
195275
}
276+
196277
fun toDisplayProperties(): Set<EntryDisplayProperties> {
197278
return emptySet()
198279
}
280+
199281
fun getId(): String {
200282
return ""
201283
}

0 commit comments

Comments
 (0)