Skip to content

Comments

Identity update holder snippets#804

Closed
cy245 wants to merge 6 commits intomainfrom
identity-update-holder-snippets
Closed

Identity update holder snippets#804
cy245 wants to merge 6 commits intomainfrom
identity-update-holder-snippets

Conversation

@cy245
Copy link
Contributor

@cy245 cy245 commented Feb 20, 2026

No description provided.

@cy245 cy245 closed this Feb 20, 2026
@cy245 cy245 deleted the identity-update-holder-snippets branch February 20, 2026 19:57
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @cy245, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates new digital credential management capabilities by updating project dependencies and introducing a dedicated Kotlin file for handling digital credential operations. The changes enable the application to register, process, and respond to digital credential requests, laying the groundwork for enhanced identity features.

Highlights

  • Dependency Updates: Updated xrGlimmer and xrProjected library versions to 1.0.0-alpha03 and introduced registryDigitalCredentials version 1.0.0-alpha02 in gradle/libs.versions.toml.
  • New Digital Credential Libraries: Added new androidx.credentials.registry dependencies, including registry-digitalcredentials-openid, registry-provider, and registry-provider-play-services, to support digital credential management.
  • Digital Credential Holder Implementation: Introduced a new Kotlin file, DigitalCredentialHolder.kt, which provides a foundational implementation for managing digital credentials. This includes functions for registering credentials, handling credential requests, verifying identity, and returning responses.
  • Credential Mapping Utilities: Added utility functions to map stored SD-JWT and mDOC entries to their respective SdJwtEntry and MdocEntry formats for registration with the RegistryManager.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • gradle/libs.versions.toml
    • Updated xrGlimmer and xrProjected versions to 1.0.0-alpha03.
    • Added registryDigitalCredentials version 1.0.0-alpha02.
    • Declared new androidx-registry-digitalcredentials, androidx-registry-provider, and androidx-registry-provider-play-services libraries.
  • identity/credentialmanager/build.gradle.kts
    • Added implementation dependencies for androidx.registry.digitalcredentials, androidx.registry.provider, and androidx.registry.provider.play.services.
  • identity/credentialmanager/src/main/java/com/example/identity/credentialmanager/DigitalCredentialHolder.kt
    • Added a new Kotlin file DigitalCredentialHolder.kt.
    • Implemented DigitalCredentialHolderActivity with functions for creating and registering credential registries.
    • Included utility functions mapToSdJwtEntries and mapToMdocEntries for converting stored credential data.
    • Provided methods for handling selected digital credentials, processing requests, checking verifier identity, and returning credential responses.
    • Defined sealed classes StoredSdJwtEntry, StoredMdocEntry, and HolderCredentialResponse as data structures.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces new dependencies for digital credentials and adds a new activity DigitalCredentialHolderActivity containing several code snippets for handling these credentials. I've identified several issues in the new file, including missing variable definitions (TAG), potential nullability and index-out-of-bounds errors in certificate hashing, and opportunities to use more idiomatic Kotlin features like map instead of manual loops. Additionally, there are some unused variables and empty catch blocks that should be addressed to improve code quality and maintainability.

// [START android_identity_process_selected_credential]
request.credentialOptions.forEach { option ->
if (option is GetDigitalCredentialOption) {
Log.i(TAG, "Got DC request: ${option.requestJson}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The variable TAG is not defined in this class, which will cause a compilation error. Please define a TAG constant, typically in a companion object.

Comment on lines +143 to +146
val appSigningInfo = request?.callingAppInfo?.signingInfoCompat?.signingCertificateHistory[0]?.toByteArray()
val md = MessageDigest.getInstance("SHA-256")
val certHash = Base64.encodeToString(md.digest(appSigningInfo), Base64.NO_WRAP or Base64.NO_PADDING)
return "android:apk-key-hash:$certHash"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This block has several issues that will prevent compilation or cause crashes:

  1. signingCertificateHistory is accessed via a nullable chain, so [0] cannot be called directly without a null-safe operator (e.g., ?.get(0)).
  2. appSigningInfo is nullable, but md.digest() requires a non-null ByteArray. Passing a null value will result in a NullPointerException.
  3. Accessing index [0] without checking if the array is empty can cause an IndexOutOfBoundsException.
        val appSigningInfo = request?.callingAppInfo?.signingInfoCompat?.signingCertificateHistory?.firstOrNull()?.toByteArray()
        if (appSigningInfo == null) return ""
        val md = MessageDigest.getInstance("SHA-256")
        val certHash = Base64.encodeToString(md.digest(appSigningInfo), Base64.NO_WRAP or Base64.NO_PADDING)
        return "android:apk-key-hash:$certHash"

Comment on lines +55 to +57
} catch (e: Exception) {
// Handle exceptions
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Swallowing exceptions without any logging or handling is generally discouraged as it makes debugging difficult. Consider logging the error at a minimum.

Comment on lines +63 to +75
val list = mutableListOf<SdJwtEntry>()

for (sdJwt in sdJwtsFromStorage) {
list.add(
SdJwtEntry(
verifiableCredentialType = sdJwt.getVCT(),
claims = sdJwt.getClaimsList(),
entryDisplayPropertySet = sdJwt.toDisplayProperties(),
id = sdJwt.getId() // Make sure this cannot be readily guessed
)
)
}
return list
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This loop can be simplified using the map function for better readability and idiomatic Kotlin.

        return sdJwtsFromStorage.map { sdJwt ->
            SdJwtEntry(
                verifiableCredentialType = sdJwt.getVCT(),
                claims = sdJwt.getClaimsList(),
                entryDisplayPropertySet = sdJwt.toDisplayProperties(),
                id = sdJwt.getId() // Make sure this cannot be readily guessed
            )
        }

Comment on lines +81 to +93
val list = mutableListOf<MdocEntry>()

for (mdoc in mdocsFromStorage) {
list.add(
MdocEntry(
docType = mdoc.retrieveDocType(),
fields = mdoc.getFields(),
entryDisplayPropertySet = mdoc.toDisplayProperties(),
id = mdoc.getId() // Make sure this cannot be readily guessed
)
)
}
return list
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This loop can be simplified using the map function for better readability and idiomatic Kotlin.

        return mdocsFromStorage.map { mdoc ->
            MdocEntry(
                docType = mdoc.retrieveDocType(),
                fields = mdoc.getFields(),
                entryDisplayPropertySet = mdoc.toDisplayProperties(),
                id = mdoc.getId() // Make sure this cannot be readily guessed
            )
        }


// [START android_identity_register_credentials_registrymanager]
try {
val response = registryManager.registerCredentials(openidRegistryRequest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The variable response is assigned but never used. If the response is not needed, you can remove the assignment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant