Giter VIP home page Giter VIP logo

mdoc-credential's Introduction

mdoc-credential

This repository contains a library that offers support for ISO 18013-5 mdoc via CredentialManager present in Android 14 (U). An example app is also included.

Usage

The library contains support for both providing and requesting credentials, and the example app does both.

Releases are distributed through Google Maven.

Relying Party

In order for an app to request a mdoc credential, it needs to create a GetCredentialRequest for use with CredentialManager (via the Jetpack library) which includes the appropriate options for mdoc. This is fairly straightforward:

val option = GetMdocCredentialOption(
    handover = MdocHandover.ANDROID,
    nonce = nonce,
    publicKey = publicKey,
    documentType = MdocCredential.DOCUMENT_TYPE_MDL,
    requestedElements = elements,
    criticalElements = elements,
    retentionInDays = GetMdocCredentialOption.RETENTION_NONE
)

val request = GetCredentialRequest(listOf(option))
val credman = CredentialManager.create(context)
val cred = credman.getCredential(context, request).credential

handover identifies whether this request is coming from an app or a Web Browser. This affects how the SessionTranscript (18013-5#9.1.5.1) is formed.
nonce is any non-empty ByteArray
publicKey is an ECPublicKey using secp256r1
requestedElements is a Set of MdocElement containing the elements you want to be included in the resulting credential. criticalElements is a similar Set of MdocElement, but these are only used to narrow the selections in the CredentialManager picker UI. It may be useful to include a more minimal set of elements here to ensure that a credential request is successful. Of course, it's also fine to use the same set of elements for both.

A successful request returns a MdocCredential, which itself contains the HPKE-encrypted DeviceResponse CBOR and the encapsulated sender key. The example app contains some code to do HPKE via Tink and uses cbor-java to parse the DeviceResponse. This code or variants of it may find their way into the identity-credential project eventually.

An unsuccessful request will throw GetCredentialException.

Provider

For mdoc, we want to use the registry feature of CredentialManager. This allows us to provide credentials without the user needing to enable the service in the Android Settings, and also avoids some potential privacy-related badness that can occur with other providers seeing unrelated requests. This library has a helper, MdocRegistry, to make it easy to register credentials:

val SUPPORTED_ELEMENTS = setOf(
    MdocCredentialElement("family_name", MdocCredentialElement.NAMESPACE_MDL),
    MdocCredentialElement("issue_date", MdocCredentialElement.NAMESPACE_MDL),
    MdocCredentialElement("expiry_date", MdocCredentialElement.NAMESPACE_MDL),
    MdocCredentialElement("document_number", MdocCredentialElement.NAMESPACE_MDL),
    MdocCredentialElement("driving_privileges", MdocCredentialElement.NAMESPACE_MDL),
)

val registry = MdocRegistry(context)

val pendingIntent = PendingIntent.getActivity(
    context,
    0,
    Intent(context, GetCredentialActivity::class.java),
    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
)
        
registry.registerCredential(
    title = "Jane Doe's Driver's License",
    icon = Icon.createWithResource(context, android.R.drawable.ic_secure),
    documentType = MdocCredential.DOCUMENT_TYPE_MDL,
    supportedElements = SUPPORTED_ELEMENTS,
    pendingIntent = pendingIntent
)

The pendingIntent is used to launch the consent UI for your provider, so in the above example you would replace GetCredentialActivity with your own.

The supportedElements argument is the list of elements your provider is capable of returning for a given credential. If all supported elements are not present here, a request may fail to match and will not be presented to the user for selection.

As mentioned above, the PendingIntent references your own Activity that will be launched to service incoming requests. This Activity will typically show the user what is being requested and may also allow some modification of the response. Once it's determined that the user does want to allow this credential to fulfill the request, the provider needs to encrypt the mdoc with the public key present in the request, set this as the result of the Activity, and finally finish() the Activity. Some example code to form a response is below:

val request = PendingIntentHandler.retrieveProviderGetCredentialRequest(intent)!!
val option =
    GetMdocCredentialOption.createFrom(request.credentialOptions[0] as GetCustomCredentialOption)
val hpke = MdocHpke(option.publicKey)
val handoverBytes = when (option.handover) {
    MdocHandover.ANDROID -> hpke.generateAndroidSessionTranscript(
        nonce = option.nonce,
        publicKey = option.publicKey,
        packageName = request.callingAppInfo.packageName
    )
    MdocHandover.BROWSER -> hpke.generateBrowserSessionTranscript(
        nonce = option.nonce,
        publicKey = option.publicKey,
        origin = request.callingAppInfo.origin!!
    )
}

val credential =
    MdocCredential(hpke.encrypt(cborResponseBytes, handoverBytes))
val response = GetCredentialResponse(credential)

val result = Intent()
PendingIntentHandler.setGetCredentialResponse(result, response)
setResult(Activity.RESULT_OK, result)
finish()

If the provider wants to abort the request, because the user has declined to consent to sharing the credential or any other reason, it can return an error via PendingIntentHandler.setGetCredentialException() and finish() the Activity.

mdoc-credential's People

Contributors

snorp avatar

Stargazers

Yuri Schimke avatar Rizmy Abdulla avatar Keel_im avatar  avatar bo.bellkheir avatar Ramon Benitez-Pagan avatar Preet Patel avatar Akash Shah avatar

Watchers

James Cloos avatar Brad Lassey avatar  avatar  avatar  avatar

mdoc-credential's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.