Kimlik Bilgisi Yöneticisi'nin Kimlik Bilgisi Aktarımı API'leri, kimlik bilgisi sağlayıcılar arasında kullanıcı kimlik bilgilerinin aynı cihazda güvenli bir şekilde aktarılmasını sağlar. Bu kılavuzda, Android'deki kimlik bilgisi sağlayıcıların androidx.credentials:providerevents kitaplığı tarafından sağlanan API'lerle nasıl entegre olabileceği ayrıntılı olarak açıklanmaktadır. Bu özellik, standartlaştırılmış FIDO Credential Exchange Format (CXF) kullanılarak şifreleri, geçiş anahtarlarını, adres bilgilerini ve özel alanları destekler.
Temel kavramlar
Kimlik bilgisi aktarımı çerçevesi, aynı cihazda eşler arası kimlik bilgisi aktarımını kolaylaştırır. Bu aktarım sırasında, ham kimlik bilgileri Android işletim sistemine veya kimliği doğrulanmamış uygulamalara gösterilmez.
Çerçeve iki temel rol tanımlar:
- Dışa aktarıcı (kaynak sağlayıcı): Şu anda kullanıcı kimlik bilgilerini barındıran bir kimlik bilgisi sağlayıcı. Dışa aktarılabilir hesaplarla (
ExportEntry) ilgili meta verileri sistemde önceden kaydeder ve kullanıcı tarafından seçildiğinde aktarım isteklerine yanıt verir. - İçe aktarıcı (istemci sağlayıcı veya kurulum sihirbazı): Hangi tür kimlik bilgilerini ve uzantıları alabileceğini belirten bir içe aktarma isteği (
ImportCredentialsRequest) başlatan bir kimlik bilgisi sağlayıcı veya kurulum sihirbazı.
Android sürümü uyumluluğu
Kimlik Bilgileri Aktarımı API'si, Android 8 (API düzeyi 26) ve sonraki sürümlerin yüklü olduğu cihazlarda çalışır.
Bağımlılık ekleme
Modülünüzün build.gradle veya build.gradle.kts dosyasına androidx.credentials:providerevents bağımlılığını ekleyin:
dependencies {
implementation("androidx.credentials:providerevents:1.0.0-alpha06")
}
Gerekli sınıfı oluşturun
Gerekli ProviderEventsManager öğesinin bir örneğini oluşturun.
val providerEventsManager = ProviderEventsManager.create(context)
Dışa aktarma aracını uygulama
Kullanıcıların kimlik bilgilerini uygulamanızdan cihazdaki diğer kimlik bilgisi sağlayıcılara aktarmasına izin vermek için dışa aktarıcı rolünü uygulayın.
Dışa aktarma girişlerini kaydetme
Kimlik bilgisi sağlayıcınız değiştiğinde (ör. kullanıcı oturum açtığında, kimlik bilgisi eklediğinde veya hesapları değiştirdiğinde) ExportEntry öğelerinizi ProviderEventsManager.registerExport() kullanarak kaydedin veya güncelleyin.
Her ExportEntry için gerekenler:
id: Bu dışa aktarma girişini benzersiz şekilde temsil eden gizli, rastgele oluşturulmuş bir dize tanımlayıcı. Bu kimliği güvenli bir şekilde saklamanız gerekir. Gelen transfer isteklerini doğrulamak için bu kimliğe daha sonra ihtiyacınız olacaktır.accountDisplayName: İsteğe bağlı hesap etiketi (örneğin,"Personal Account").userDisplayName: Kullanıcının birincil tanımlayıcısı (örneğin,"alice@example.com").icon: Sağlayıcıyı veya hesabı temsil eden birBitmapsimgesi (kitaplık tarafından otomatik olarak 32x32 PNG'ye ölçeklendirilir).supportedCredentialTypes: Bu girişin hangi türleri içerdiğini gösteren,CredentialTypeskaynağından alınan bir dizi dize sabiti.
suspend fun registerMyProviderForExport( providerEventsManager: ProviderEventsManager, providerIcon: Bitmap, // Randomly generated and stored in encrypted storage secretEntryId: String ) { val entry = ExportEntry( id = secretEntryId, accountDisplayName = "MyProvider Personal", userDisplayName = "alice@example.com", icon = providerIcon, supportedCredentialTypes = setOf( CredentialTypes.CREDENTIAL_TYPE_BASIC_AUTH, // Passwords CredentialTypes.CREDENTIAL_TYPE_PUBLIC_KEY, // Passkeys CredentialTypes.CREDENTIAL_TYPE_ADDRESS, CredentialTypes.CREDENTIAL_TYPE_CREDIT_CARD ) ) // RegisterExportRequest.create() attaches the default WASM matcher from assets val request = RegisterExportRequest.create(context, listOf(entry)) try { val response = providerEventsManager.registerExport(request) // Registration successful } catch (e: Exception) { // Handle registration exceptions (e.g., RegisterExportProviderConfigurationException) } }
Dışa aktarma etkinliğini manifest dosyasında bildirin.
Kullanıcı, sistem seçici kullanıcı arayüzünde ExportEntry öğenizi seçtiğinde sistem, belirlenen işleme Activity öğenizi başlatır. Bu etkinliği zorunlu amaç işlemi ve içerik URI şemasıyla bildirin:
<activity
android:name="com.example.CredentialExportActivity"
android:exported="true"
android:label="@string/export_activity_label">
<intent-filter>
// This intent action is required for Credential Manager to invoke this activity
<action android:name="androidx.identitycredentials.action.IMPORT_CREDENTIALS" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
</intent-filter>
</activity>
Etkinliğinizdeki aktarım amacını işleme
CredentialExportActivity içinde, isteği ayrıştırmak, arayan uygulamayı ve credId'yi doğrulamak, gerekli biyometrik kimlik doğrulamayı gerçekleştirmek ve FIDO CXF yükünü sağlanan içerik URI'sine geri yazmak için IntentHandler.retrieveProviderImportCredentialsRequest(intent) kullanın:
class CredentialExportActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 1. Extract the transfer request from the incoming Intent val request: ProviderImportCredentialsRequest? = IntentHandler.retrieveProviderImportCredentialsRequest(intent) if (request == null) { finishWithError() return } // 2. Validate CallingAppInfo and secret `credId` val callingAppPackage = request.callingAppInfo.packageName val receivedCredId = request.credId if (!verifySecretEntryId(receivedCredId) || !isTrustedImporter(callingAppPackage)) { // Secret ID mismatch or untrusted caller -> abort sendExceptionAndFinish(ImportCredentialsNoExportOptionException("Unauthorized request")) return } // 3. Optional: Prompt user for Biometric / PIN authentication before exporting authenticateUserThenExport(request) } private fun authenticateUserThenExport(request: ProviderImportCredentialsRequest) { // ... Biometric prompt logic ... // Once authenticated, generate the FIDO CXF JSON string matching the requested types val cxfJsonPayload = buildFidoCxfJsonPayload( requestedTypes = request.request.credentialTypes, requestedExtensions = request.request.knownExtensions ) val response = ImportCredentialsResponse(cxfJsonPayload) // 4. Write the JSON payload to the Content URI and set Activity result IntentHandler.setImportCredentialsResponse( context = this, uri = request.uri, intent = intent, response = response ) setResult(Activity.RESULT_OK, intent) finish() } private fun sendExceptionAndFinish(exception: androidx.credentials.providerevents.exception.ImportCredentialsException) { IntentHandler.setImportCredentialsException(intent, exception) setResult(Activity.RESULT_OK, intent) finish() } private fun verifySecretEntryId(credentialId: String): Boolean { // Check if credentialId matches what you stored when calling RegisterExportRequest return credentialId == getStoredSecretEntryId() } private fun isTrustedImporter(packageName: String): Boolean { // Implement any specific allowlisting / caller checks if required return true } private fun finishWithError() { setResult(Activity.RESULT_CANCELED) finish() } }
İhracat kaydı ve gümrükleme istisnaları
Bu modüldeki tüm istisnalar ImportCredentialsException, RegisterExportException veya ClearExportException alt sınıflarıdır.
RegisterExportProviderConfigurationExceptionveyaClearExportProviderConfigurationException: Kayıt veya temizleme işlemi, sağlayıcı kurulumuyla ilgili sorunlar (ör.ExportEntryiçinde boşsupportedCredentialTypesveya desteklenmeyen bir işletim sistemi katmanında arama yapılması) nedeniyle başarısız olduğunda oluşturulur.RegisterExportUnknownErrorExceptionveyaClearExportUnknownErrorException: Dışa aktarma kaydı güncellenirken sınıflandırılmamış bir sistem veya depolama hatası oluştu.
İçe aktarma aracını uygulama
Kimlik bilgilerini uygulamanıza aktarmak için (örneğin, ilk katılım veya sağlayıcı içe aktarma sırasında) içe aktarıcı rolünü uygulayın ve ProviderEventsManager.importCredentials() işlevini çağırarak akışı başlatın.
İçe aktarma isteğini ve başlatma akışını oluşturma
İçe aktarıcınızın hangi CredentialTypes ve KnownExtensions biçimlerini desteklediğini belirtin:
suspend fun startCredentialImport( activityContext: Context, providerEventsManager: ProviderEventsManager ) { val importRequest = ImportCredentialsRequest( credentialTypes = setOf( CredentialTypes.CREDENTIAL_TYPE_BASIC_AUTH, CredentialTypes.CREDENTIAL_TYPE_PUBLIC_KEY, CredentialTypes.CREDENTIAL_TYPE_ADDRESS, CredentialTypes.CREDENTIAL_TYPE_NOTE ), knownExtensions = setOf( KnownExtensions.KNOWN_EXTENSION_SHARED ) ) try { // Launches the system Selector UI; suspends until user selects a provider and completes transfer val response = providerEventsManager.importCredentials(activityContext, importRequest) // 1. Inspect the source exporter's package info val exporterPackageName = response.callingAppInfo.packageName // 2. Parse the FIDO CXF JSON string val cxfJsonString = response.response.responseJson parseAndSaveImportedCredentials(cxfJsonString) } catch (e: ImportCredentialsException) { // Handle specific import exceptions (e.g., ImportCredentialsCancellationException) handleImportFailure(e) } } private fun parseAndSaveImportedCredentials(cxfJsonString: String) { val rootJson = JSONObject(cxfJsonString) // Parse according to FIDO Credential Exchange Format (CXF v1.0) specification: // https://fidoalliance.org/specs/cx/cxf-v1.0-ps-20250814.html } // Helper function to make it compile private fun handleImportFailure(e: ImportCredentialsException) {}
İçe aktarma akışı istisnaları
Bu modüldeki tüm istisnalar ImportCredentialsException, RegisterExportException veya ClearExportException alt sınıflarıdır.
ImportCredentialsCancellationException: Kullanıcı, seçici kullanıcı arayüzünü kapattı veya dışa aktarma etkinliğini iptal etti (Activity.RESULT_CANCELED).ImportCredentialsNoExportOptionException: Kayıtlı dışa aktarma girişlerinden hiçbiri istenen kimlik bilgisi türleriyle eşleşmedi veya seçilen dışa aktarıcı bir ret istisnası oluşturdu.ImportCredentialsProviderConfigurationException: Yapılandırma hatası (örneğin,ImportCredentialsRequestiçinde boşcredentialTypesayarlanmış veya izinler eksik).ImportCredentialsInvalidJsonException: Dışa aktarıcı, istek doğrulamasında başarısız olan hatalı biçimlendirilmiş veya boş bir JSON yükü döndürdü.ImportCredentialsSystemErrorException: İçe aktarma sırasında dahili Android sistemi veya Binder aktarım hatası oluştu.ImportCredentialsUnknownCallerException: Arama uygulaması çerçeve tarafından doğrulanamadı.ImportCredentialsUnknownErrorException: Sınıflandırılmamış veya beklenmedik bir hata oluştu.
Desteklenen kimlik bilgisi türleri ve uzantıları
androidx.credentials.providerevents.transfer.CredentialTypes nesnesi, FIDO CXF öğe türlerine karşılık gelen standartlaştırılmış dize sabitlerini tanımlar:
| Sabit | Değer (cxf türü) |
Açıklama |
|---|---|---|
CREDENTIAL_TYPE_BASIC_AUTH |
"basic-auth" |
Kullanıcı adı ve şifre giriş bilgileri. |
CREDENTIAL_TYPE_PUBLIC_KEY |
"passkey" |
FIDO2 veya WebAuthn geçiş anahtarı ortak anahtar kimlik bilgileri. |
CREDENTIAL_TYPE_ADDRESS |
"address" |
Formları otomatik doldurmak için posta veya kargo adresi bilgileri. |
CREDENTIAL_TYPE_API_KEY |
"api-key" |
API erişim anahtarları ve jetonları. |
CREDENTIAL_TYPE_CREDIT_CARD |
"credit-card" |
Kredi ve banka kartı ödeme bilgileri |
CREDENTIAL_TYPE_CUSTOM_FIELDS |
"custom-fields" |
Özel gruplandırmalar veya kullanıcı tanımlı alanlar. |
CREDENTIAL_TYPE_DRIVERS_LICENSE |
"drivers-license" |
Sürücü belgesi ayrıntıları |
CREDENTIAL_TYPE_FILE |
"file" |
İkili dosyalar için meta veriler ve yer tutucu referansları. |
CREDENTIAL_TYPE_GENERATED_PASSWORD |
"generated-password" |
Makine tarafından oluşturulan güvenli şifreler. |
CREDENTIAL_TYPE_IDENTITY_DOCUMENT |
"identity-document" |
Resmi kimlik kartları, SSN, TIN veya pasaport referansları |
CREDENTIAL_TYPE_ITEM_REFERENCE |
"item-reference" |
Yükteki başka bir öğeyi işaret eden mantıksal bağlantılar. |
CREDENTIAL_TYPE_NOTE |
"note" |
Kullanıcı tanımlı güvenli notlar (UTF-8 dizesi). |
CREDENTIAL_TYPE_PASSPORT |
"passport" |
Pasaport seyahat belgesi ayrıntıları. |
CREDENTIAL_TYPE_PERSON_NAME |
"person-name" |
Kişi kimliği ve adlandırma ayrıntıları. |
CREDENTIAL_TYPE_SSH_KEY |
"ssh-key" |
SSH ortak ve özel anahtar çiftleri. |
CREDENTIAL_TYPE_TOTP |
"totp" |
Zamana dayalı tek kullanımlık şifre (2FA) sırları. |
CREDENTIAL_TYPE_WIFI |
"wifi" |
Kablosuz ağ SSID'si ve geçiş ifadeleri. |
Özel WASM (WebAssembly) eşleştiriciler (Gelişmiş)
Varsayılan olarak, RegisterExportRequest.create(context, entries) çağrısı, kitaplık öğelerinden sistem varsayılanı olan credential_transfer_matcher.wasm öğesini paketler. Bu öğe, girişleri yalnızca supportedCredentialTypes kesişimine göre filtreler.
Kimlik bilgisi sağlayıcınız karmaşık eşleştirme mantığı (ör. dinamik özellik kontrolleri veya özel alanlara göre koşullu filtreleme) gerektiriyorsa WASM kimlik bilgisi aktarımı API'siyle eşleşen kendi WebAssembly modülünüzü derleyebilir ve ham bayt dizisini doğrudan iletebilirsiniz:
// Loading a custom WASM matcher val customMatcherBytes = context.assets.open("my_custom_matcher.wasm").use { it.readBytes() } val customRequest = RegisterExportRequest( entries = myEntries, exportMatcher = customMatcherBytes ) providerEventsManager.registerExport(customRequest)