Credential Manager Holder API, Android cüzdan uygulamanızın dijital kimlik bilgilerini yönetmesini ve doğrulayıcılara sunmasını sağlar. Bu kılavuzda, cüzdan uygulamanızın kimlik bilgilerini Kimlik Bilgisi Yöneticisi'ne nasıl kaydedeceğiniz ve kullanıcı bir kimlik bilgisi seçtiğinde sunu isteğini nasıl işleyeceğiniz açıklanmaktadır. Holder API, Android 6 (API düzeyi 23) ve sonraki sürümlerde desteklenir.
Bağımlılık ekleme
Kimlik Bilgisi Yöneticisi Holder API'yi kullanmak için uygulama modülünüzün build.gradle komut dosyasına aşağıdaki bağımlılıkları ekleyin:
dependencies {
// Used to implement credential registries
implementation "androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha05"
implementation "androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha05"
implementation "androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha05"
implementation "androidx.credentials.registry:registry-provider:1.0.0-alpha05"
implementation "androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha05"
}
Kimlik bilgilerinizi kaydetme
Öncelikle, OpenId4VpRegistry isteğini kaydetmek için kullanacağınız bir RegistryManager örneği oluşturun.
// Create the registry manager
val registryManager = RegistryManager.create(context)
OpenId4VpRegistry isteği oluşturma
Doğrulayıcılardan gelen OpenID4VP isteklerini işlemek için bir OpenId4VpRegistry kaydetmeniz gerekir. Cüzdan kimlik bilgilerinizle (ör. sdJwtsFromStorage ve mdocsFromStorage) yüklenmiş yerel veri türleriniz varsa bunları Jetpack DigitalCredentialEntry eşdeğerlerine (SdJwtEntry ve MdocEntry) dönüştürmeniz gerekir.
SD-JWT'leri kayıt defterine ekleme
Her yerel SD-JWT kimlik bilgisini kayıt defteri için bir SdJwtEntry ile eşleyin:
fun mapToSdJwtEntries(sdJwtsFromStorage: List<StoredSdJwtEntry>): List<SdJwtEntry> {
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
}
Kayıt Defteri'ne mdoc ekleme
Yerel mdoc kimlik bilgilerinizi Jetpack türü MdocEntry ile eşleyin:
fun mapToMdocEntries(mdocsFromStorage: List<StoredMdocEntry>): List<MdocEntry> {
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
}
Kodla ilgili önemli noktalar
- Şifrelenmiş kimlikler:
IDalanını yapılandırmanın bir yöntemi, şifrelenmiş bir kimlik bilgisi tanımlayıcısı kaydetmektir. Böylece, değeri yalnızca siz çözebilirsiniz. - Yerelleştirme: Her iki biçim için de kullanıcı arayüzü görüntüleme alanları yerelleştirilmelidir.
İsteğinizi birleştirme ve kaydetme
Dönüştürülen girişlerinizi birleştirin ve isteği RegistryManager ile kaydedin:
val credentialEntries =
mapToSdJwtEntries(sdJwtsFromStorage) + mapToMdocEntries(mdocsFromStorage)
val openidRegistryRequest = OpenId4VpRegistry(
credentialEntries = credentialEntries,
id = "my-wallet-openid-registry-v1" // A stable, unique ID to identify your registry record.
)
İsteğe bağlı: Satır içi kart verme
Kullanıcı için istenen türde mevcut kimlik bilgisi yoksa cüzdanınıza kimlik bilgisi ekleme seçeneği gösterebilirsiniz. Bunu yapmak için OpenId4VpRegistry öğenize, desteklenen kimlik bilgilerini içeren bir inlineIssuanceEntries listesi ekleyin:
val openidRegistryRequest = OpenId4VpRegistry(
credentialEntries = credentialEntries,
inlineIssuanceEntries = emptyList(),
listOf(
MdocInlineIssuanceEntry(
id = "Issuance",
display = InlineIssuanceEntry.InlineIssuanceDisplayProperties(
subtitle = "Mobile Drivers License, State Id, and Others",
),
supportedMdocs = setOf(
MdocInlineIssuanceEntry.SupportedMdoc(
"eu.europa.ec.eudi.pid.1"
),
MdocInlineIssuanceEntry.SupportedMdoc(
"org.iso.18013.5.1.mDL1"
),
)
),
SdJwtInlineIssuanceEntry(
id = "sd-jwt-issuance",
display = InlineIssuanceEntry.InlineIssuanceDisplayProperties(
subtitle = "Mobile Drivers License, State Id, and Others",
),
supportedSdJwts = setOf(
SdJwtInlineIssuanceEntry.SupportedSdJwt("urn:openid:interop:id:1")
)
)
),
id = "my-wallet-openid-registry-v1"
)
Kimlik bilgilerinizi CredentialManager'a kaydetme
try {
val response = registryManager.registerCredentials(openidRegistryRequest)
} catch (e: Exception) {
// Handle failure
}
Uygulama meta verilerini yönetme
Cüzdan uygulamanızın CredentialManager ile kaydettiği meta veriler aşağıdaki özelliklere sahiptir:
- Kalıcılık: Bilgiler yerel olarak kaydedilir ve yeniden başlatma işlemlerinden sonra da korunur.
- Yalıtılmış depolama alanı: Her uygulamanın kayıt defteri kayıtları ayrı ayrı depolanır. Bu, bir uygulamanın başka bir uygulamanın kayıt defteri kayıtlarını değiştiremeyeceği anlamına gelir.
- Anahtarlı Güncellemeler: Her uygulamanın kayıt defteri kayıtları, kayıtların yeniden tanımlanmasına, güncellenmesine veya silinmesine olanak tanıyan bir
idile anahtarlanır. - Meta verileri güncelleme: Uygulamanız her değiştiğinde veya ilk yüklendiğinde kalıcı meta verileri güncellemek iyi bir uygulamadır. Bir kayıt defteri aynı
idaltında birden çok kez çağrılırsa en son çağrı, önceki tüm kayıtların üzerine yazılır. Güncellemek için eski kaydı temizlemenize gerek kalmadan yeniden kaydolun.
İsteğe bağlı: Eşleştirici oluşturma
Eşleştirici, kayıtlı kimlik bilgilerinizi gelen bir doğrulayıcı isteğine göre filtrelemek için Kimlik Bilgisi Yöneticisi'nin korumalı alanda çalıştırdığı bir Wasm ikili programıdır.
- Varsayılan eşleştirici:
OpenId4VpRegistrysınıfı, örneklendirdiğinizde varsayılanOpenId4VPeşleştiriciyi (OpenId4VpDefaults.DEFAULT_MATCHER) otomatik olarak içerir. Tüm standart OpenID4VP kullanım alanlarında kitaplık, eşleştirmeyi sizin için yapar. - Özel eşleştirici: Özel eşleştiriciyi yalnızca kendi eşleştirme mantığını gerektiren standart dışı bir protokolü destekliyorsanız kullanırsınız.
Seçili kimlik bilgilerini işleme
Kullanıcı bir kimlik bilgisi seçtiğinde cüzdan uygulamanızın isteği işlemesi gerekir.
androidx.credentials.registry.provider.action.GET_CREDENTIAL intent filtresini dinleyen bir Activity tanımlamanız gerekir.
Örnek cüzdanımız bu prosedürü göstermektedir.
Intent, etkinliğinizi Verifier isteği ve çağrı kaynağıyla başlatır. Bu bilgileri PendingIntentHandler.retrieveProviderGetCredentialRequest işleviyle ayıklarsınız. Bu işlem, doğrulayıcı isteğiyle ilişkili tüm bilgileri içeren bir ProviderGetCredentialRequest döndürür. Üç temel bileşen vardır:
- Arama uygulaması: İsteği gönderen uygulama.
getCallingAppInfoile alınabilir. Bu bilgiyi doğrulayıcının kimliğini kontrol etmek için kullanabilirsiniz. - Seçilen kimlik bilgisi: Kullanıcının seçtiği aday hakkındaki bilgiler,
selectedCredentialSet extension methodaracılığıyla alınır. Bu, kaydettiğiniz kimlik bilgisi kimliğiyle eşleşir. - Özel istekler: Doğrulayıcı tarafından yapılan ve
getCredentialOptionsyönteminden alınan özel istek. Dijital Kimlik Bilgileri istek akışında bu listede tek birGetDigitalCredentialOptionbulabilirsiniz.
Sunu isteğini aşağıdaki kodla işleyebilirsiniz:
request.credentialOptions.forEach { option ->
if (option is GetDigitalCredentialOption) {
Log.i(TAG, "Got DC request: ${option.requestJson}")
processRequest(option.requestJson)
}
}
Bunun bir örneğini örnek cüzdanda görebilirsiniz.
Doğrulayıcı kimliğini kontrol etme
Öncelikle intent'ten ProviderGetCredentialRequest değerini çıkarın:
val request = PendingIntentHandler.retrieveProviderGetCredentialRequest(intent)
Ayrıcalıklı uygulamaları kontrol edin: Ayrıcalıklı uygulamalar (ör. web tarayıcıları), kaynak parametresini ayarlayarak diğer doğrulayıcılar adına çağrı yapabilir. Bu kaynağı almak için CallingAppInfo getOrigin API'ye ayrıcalıklı ve güvenilir arayanların listesini (JSON biçiminde bir izin verilenler listesi) iletin.
val origin = request?.callingAppInfo?.getOrigin(
privilegedAppsJson // Your allow list JSON
)
origin boş değilse: packageName ve sertifika parmak izleri, izin verilenler listenizdeki bir uygulamayla eşleşirse kaynak döndürülür. Bu çağrıyı ayrıcalıklı bir çağrı olarak kabul edin ve çağrı uygulamasının imzasını kullanarak kaynağı hesaplamak yerine OpenID4VP yanıtında bu kaynağı ayarlayın.
origin boşsa: Doğrulayıcı isteği bir Android uygulamasından geliyordur. OpenID4VP yanıtıyla eşlenen kaynak, android:apk-key-hash:<encoded SHA 256 fingerprint> olarak hesaplanmalıdır.
val appSigningInfo =
request?.callingAppInfo?.signingInfoCompat?.signingCertificateHistory?.get(0)?.toByteArray()
val md = MessageDigest.getInstance("SHA-256")
val certHash =
Base64.encodeToString(md.digest(appSigningInfo), Base64.NO_WRAP or Base64.NO_PADDING)
val computedOrigin = "android:apk-key-hash:$certHash"
Kart Sahibi Kullanıcı Arayüzü'nü oluşturma
Bir kimlik bilgisi seçildiğinde, cüzdan uygulaması çağrılır ve kullanıcıyı uygulamanın kullanıcı arayüzü üzerinden yönlendirir. Bu iş akışını yönetmenin iki standart yolu vardır:
- Kimlik bilgisini yayınlamak için ek kullanıcı kimlik doğrulaması gerekiyorsa BiometricPrompt API'yi kullanın. Bu durum, örnekte gösterilmektedir.
- Aksi takdirde, birçok cüzdan, verileri hemen arayan uygulamaya geri ileten boş bir etkinlik oluşturarak sessiz bir dönüşü tercih eder. Bu, kullanıcı tıklamalarını en aza indirir ve daha sorunsuz bir deneyim sağlar.
Kimlik bilgisi yanıtını döndürme
Cüzdan uygulamanız sonucu geri göndermeye hazır olduğunda etkinliği kimlik bilgisi yanıtıyla tamamlayın:
PendingIntentHandler.setGetCredentialResponse(
resultData,
GetCredentialResponse(DigitalCredential(response.responseJson))
)
setResult(RESULT_OK, resultData)
finish()
Bir istisna varsa kimlik bilgisi istisnasını da benzer şekilde gönderebilirsiniz:
PendingIntentHandler.setGetCredentialException(
resultData,
GetCredentialUnknownException() // Configure the proper exception
)
setResult(RESULT_OK, resultData)
finish()
Kimlik bilgisi yanıtını bağlam içinde döndürmenin tam bir örneği için örnek uygulamaya bakın.