Obsługa wydawania danych logowania za pomocą aplikacji portfela

Aby otrzymywać i przechowywać dane uwierzytelniające od wydawców, aplikacja posiadacza musi obsługiwać procesy wydawania. Wystawianie danych uwierzytelniających można aktywować na 2 sposoby:

  • Proces inicjowany przez wydawcę: użytkownik wysyła prośbę o wydanie wirtualnej karty debetowej z aplikacji lub witryny wydawcy. Na przykład witryna może oferować użytkownikom opcję „Dodaj paszport do portfela”. Wydawca wywołuje interfejs API wydawania Menedżera danych logowania, aby wysłać żądanie oferty danych logowania OpenID4VCI. Aby obsługiwać takie żądania, posiadacz musi najpierw zintegrować się z Credential Manager, aby zarejestrować swoje metadane. Credential Manager wyświetli odpowiednie opcje do wyboru przez użytkownika. Gdy użytkownik wybierze opcję posiadacza, zostanie wywołana aplikacja posiadacza i będzie można wykonać czynności niezbędne do zakończenia wydawania.
  • Proces inicjowany przez posiadacza: użytkownik prosi o dodanie VDC z aplikacji posiadacza. Na przykład posiadacz może udostępnić przycisk „Dodaj paszport”. W takim przypadku posiadacz przechowuje listę obsługiwanych wydawców i metadane. Nie musi integrować się z Menedżerem danych logowania na Androidzie, aby realizować tę funkcję.

Więcej informacji o tym, jak dokumenty tożsamości współpracują z interfejsem Holder API, znajdziesz w artykule Przechowywanie cyfrowych dokumentów tożsamości.

Zgodność z wersją Androida

Interfejs Holder API jest obsługiwany na Androidzie 6 (poziom interfejsu API 23) i nowszych wersjach.

Implementacja

Aby używać interfejsu Credential Manager Holder API, dodaj do skryptu kompilacji modułu aplikacji te zależności:

Groovy

dependencies {
    // Use to implement credentials registrys

    implementation "androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-provider:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha04"

}

Kotlin

dependencies {
    // Use to implement credentials registrys

    implementation("androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-provider:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha04")

}

Tworzenie obiektu RegistryManager

Utwórz instancję RegistryManager i zarejestruj w niej żądanie RegisterCreationOptionsRequest.

val registryManager = RegistryManager.create(context)

try {
    registryManager.registerCreationOptions(object :
        RegisterCreationOptionsRequest(
            creationOptions = buildIssuanceData(),
            matcher = loadIssuanceMatcher(),
            type = DigitalCredential.TYPE_DIGITAL_CREDENTIAL,
            id = "openid4vci",
        ) {}
    )
} catch (e: Exception) {
    Log.e(TAG, "Issuance registration failed.", e)
}

Dopasowujący to plik binarny WebAssembly (Wasm), który otrzymuje zestaw creationOptions podczas rejestracji i ofertę danych logowania wysłaną przez wystawcę, aby określić wpisy wyświetlane w interfejsie Credential Manager. Przykładowy dopasowujący znajdziesz w przykładowej aplikacji portfela open source.

Obsługa żądania wystawienia

Następnie portfel musi obsłużyć sytuację, gdy użytkownik wybierze opcję utworzenia dokumentu tożsamości. Zdefiniuj aktywność, która nasłuchuje filtra intencji androidx.credentials.registry.provider.action.CREATE_CREDENTIAL, jak pokazano w przykładowym portfelu.

Intencja, która uruchamia aktywność, zawiera żądanie utworzenia i źródło wywołania, które można wyodrębnić za pomocą funkcji PendingIntentHandler.retrieveProviderCreateCredentialRequest. Interfejs API zwraca obiekt ProviderCreateCredentialRequest zawierający wszystkie informacje powiązane z żądaniem utworzenia. Składa się on z 2 głównych elementów:

  • Aplikacja, która wysłała żądanie. Możesz je pobrać za pomocą getCallingAppInfo.
  • Żądanie z aplikacji do dzwonienia. Możesz je pobrać za pomocą getCallingRequest, która zwraca CreateCredentialRequest. Jeśli żądanie dotyczy cyfrowych danych uwierzytelniających, jest to instancja CreateDigitalCredentialRequest, która zawiera żądanie wydania w formacie JSON we właściwości requestJson. Możesz to zrobić za pomocą tego przykładowego kodu:
val pendingIntentRequest =
    PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)
val request = pendingIntentRequest!!.callingRequest
if (request is CreateDigitalCredentialRequest) {
    Log.i(TAG, "Got DC creation request: ${request.requestJson}")
    processCreationRequest(request.requestJson)
}

Atestacja klucza

Pamiętaj o tych kwestiach dotyczących atestacji kluczy:

  • Podczas generowania atestacji kluczy możesz używać BigInteger.toByteArray do konwertowania materiałów klucza na przykład na klucz internetowy JSON. Ta metoda może czasami dodać bajt znaku i spowodować błąd weryfikacji. Jeśli tak się stanie, usuń te bajty przed wysłaniem atestacji kluczy do wydawcy.
  • Zalecamy używanie android_key_attestation jako typu dowodu klucza.

Zwracanie odpowiedzi dotyczącej tworzenia

Gdy portfel wykona czynności niezbędne do zapisania dokumentu tożsamości, zakończ aktywność z odpowiedzią dotyczącą dokumentu tożsamości:

val resultData = Intent()
PendingIntentHandler.setCreateCredentialResponse(
    resultData,
    CreateDigitalCredentialResponse(response.responseJson)
)
setResult(RESULT_OK, resultData)
finish()

Jeśli wystąpi wyjątek, możesz wysłać wyjątek dotyczący danych logowania:

val resultData = Intent()
PendingIntentHandler.setCreateCredentialException(
    resultData,
    CreateCredentialUnknownException() // Configure the proper exception
)
setResult(RESULT_OK, resultData)
finish()

Pełny przykład zwracania odpowiedzi z danymi logowania w kontekście znajdziesz w przykładowej aplikacji.