Geçiş anahtarları, birleşik oturum açma ve üçüncü taraf kimlik doğrulama sağlayıcıları için destek sunan Kimlik Bilgisi Yöneticisi, Android'de kimlik doğrulama için önerilen API'dir. Kullanıcıların kimlik bilgilerini senkronize edip yönetebileceği güvenli ve kullanışlı bir ortam sağlar. Yerel FIDO2 kimlik bilgilerini kullanan geliştiriciler, uygulamalarını Credential Manager API ile entegre ederek geçiş anahtarı kimlik doğrulamasını destekleyecek şekilde güncellemelidir. Bu belgede, projenizi FIDO2'den Kimlik Bilgisi Yöneticisi'ne nasıl taşıyacağınız açıklanmaktadır.
FIDO2'den Kimlik Bilgisi Yöneticisi'ne geçiş yapma nedenleri
Çoğu durumda, Android uygulamanızın kimlik doğrulama sağlayıcısını Kimlik Bilgisi Yöneticisi'ne taşımanız gerekir. Kimlik Bilgisi Yöneticisi'ne geçiş yapmanın nedenleri şunlardır:
- Geçiş anahtarı desteği: Kimlik Bilgisi Yöneticisi, şifrelerden daha güvenli ve kullanımı daha kolay olan yeni, şifresiz bir kimlik doğrulama mekanizması olan geçiş anahtarlarını destekler.
- Çoklu oturum açma yöntemleri: Kimlik Bilgisi Yöneticisi; şifreler, geçiş anahtarları ve birleşik oturum açma yöntemleri dahil olmak üzere çoklu oturum açma yöntemlerini destekler. Bu sayede kullanıcılar, tercih ettikleri kimlik doğrulama yönteminden bağımsız olarak uygulamanızda daha kolay kimlik doğrulaması yapabilir.
- Üçüncü taraf kimlik bilgisi sağlayıcı desteği: Android 14 ve sonraki sürümlerde Kimlik Bilgisi Yöneticisi, birden fazla üçüncü taraf kimlik bilgisi sağlayıcıyı destekler. Bu, kullanıcılarınızın uygulamanızda oturum açmak için diğer sağlayıcılardaki mevcut kimlik bilgilerini kullanabileceği anlamına gelir.
- Tutarlı kullanıcı deneyimi: Kimlik Bilgisi Yöneticisi, uygulamalar ve oturum açma mekanizmaları genelinde kimlik doğrulama için daha tutarlı bir kullanıcı deneyimi sunar. Bu sayede kullanıcılar, uygulamanızın kimlik doğrulama akışını daha kolay anlayıp kullanabilir.
FIDO2'den Kimlik Bilgisi Yöneticisi'ne geçişe başlamak için aşağıdaki adımları uygulayın.
Bağımlılıkları güncelleme
Projenizin build.gradle dosyasındaki Kotlin eklentisini 1.8.10 veya sonraki bir sürüme güncelleyin.
plugins { //… id 'org.jetbrains.kotlin.android' version '1.8.10' apply false //… }Projenizin
build.gradledosyasında, bağımlılıklarınızı Kimlik Bilgisi Yöneticisi ve Google Play Hizmetleri Kimlik Doğrulama kitaplıklarının en yeni sürümlerini kullanacak şekilde güncelleyin.dependencies { // ... // Credential Manager: implementation 'androidx.credentials:credentials:<latest-version>' // Play Services Authentication: // Optional - needed for credentials support from play services, for devices running // Android 13 and lower: implementation 'androidx.credentials:credentials-play-services-auth:<latest-version>' // ... }FIDO başlatma işlemini, Kimlik Bilgisi Yöneticisi başlatma işlemiyle değiştirin. Geçiş anahtarı oluşturma ve oturum açma yöntemleri için kullandığınız sınıfa bu bildirimi ekleyin:
val credMan = CredentialManager.create(context)
Geçiş anahtarı oluşturma
Kullanıcının geçiş anahtarıyla oturum açabilmesi için yeni bir geçiş anahtarı oluşturmanız, bunu kullanıcının hesabıyla ilişkilendirmeniz ve geçiş anahtarının ortak anahtarını sunucunuzda depolamanız gerekir. Kayıt işlevi çağrılarını güncelleyerek uygulamanızı bu özellikten yararlanacak şekilde ayarlayın.
Geçiş anahtarı oluşturma sırasında
createCredential()yöntemine gönderilen gerekli parametreleri almak içinregisterRequest()sunucu çağrınızaname("residentKey").value("required")(WebAuthn spesifikasyonunda açıklandığı şekilde) ekleyin.suspend fun registerRequest() { // ... val call = client.newCall( Builder() .method( "POST", jsonRequestBody { name("attestation").value("none") name("authenticatorSelection").objectValue { name("residentKey").value("required") } } ).build() ) // ... }registerRequest()ve tüm alt işlevler içinreturntürünüJSONObjectolarak ayarlayın.suspend fun registerRequest(sessionId: String): ApiResult<JSONObject> { val call = client.newCall( Builder() .url("$BASE_URL/<your api url>") .addHeader("Cookie", formatCookie(sessionId)) .method( "POST", jsonRequestBody { name("attestation").value("none") name("authenticatorSelection").objectValue { name("authenticatorAttachment").value("platform") name("userVerification").value("required") name("residentKey").value("required") } } ).build() ) val response = call.await() return response.result("Error calling the api") { parsePublicKeyCredentialCreationOptions( body ?: throw ApiException("Empty response from the api call") ) } }Intent başlatıcı ve etkinlik sonucu çağrılarını işleyen tüm yöntemleri görünümünüzden güvenli bir şekilde kaldırın.
registerRequest()artık birJSONObjectdöndürdüğü içinPendingIntentoluşturmanız gerekmez. Döndürülen niyetiJSONObjectile değiştirin. Intent başlatıcı çağrılarınızı, Credential Manager API'dencreateCredential()çağrısı yapacak şekilde güncelleyin.createCredential()API yöntemini çağırın.suspend fun createPasskey( activity: Activity, requestResult: JSONObject ): CreatePublicKeyCredentialResponse? { val request = CreatePublicKeyCredentialRequest(requestResult.toString()) var response: CreatePublicKeyCredentialResponse? = null try { response = credMan.createCredential( request = request as CreateCredentialRequest, context = activity ) as CreatePublicKeyCredentialResponse } catch (e: CreateCredentialException) { showErrorAlert(activity, e) return null } return response }Çağrı başarılı olduktan sonra yanıtı sunucuya geri gönderin. Bu çağrının isteği ve yanıtı, FIDO2 uygulamasına benzer olduğundan herhangi bir değişiklik yapılması gerekmez.
Geçiş anahtarlarıyla kimlik doğrulama
Geçiş anahtarı oluşturma işlemini ayarladıktan sonra uygulamanızı, kullanıcıların geçiş anahtarlarını kullanarak oturum açmasına ve kimlik doğrulamasına izin verecek şekilde ayarlayabilirsiniz. Bunu yapmak için kimlik doğrulama kodunuzu, Kimlik Bilgisi Yöneticisi sonuçlarını işleyecek şekilde güncelleyecek ve geçiş anahtarlarıyla kimlik doğrulaması yapacak bir işlev uygulayacaksınız.
- Oturum açma isteğinizin,
getCredential()isteğine gönderilecek gerekli bilgileri almak için sunucuya yaptığı çağrı, FIDO2 uygulamasıyla aynıdır. Herhangi bir değişiklik yapılması gerekmez. Kayıt isteği çağrısına benzer şekilde, döndürülen yanıt JSONObject biçimindedir.
/** * @param sessionId The session ID to be used for the sign-in. * @param credentialId The credential ID of this device. * @return a JSON object. */ suspend fun signinRequest(): ApiResult<JSONObject> { val call = client.newCall( Builder().url( buildString { append("$BASE_URL/signinRequest") } ).method("POST", jsonRequestBody {}) .build() ) val response = call.await() return response.result("Error calling /signinRequest") { parsePublicKeyCredentialRequestOptions( body ?: throw ApiException("Empty response from /signinRequest") ) } } /** * @param sessionId The session ID to be used for the sign-in. * @param response The JSONObject for signInResponse. * @param credentialId id/rawId. * @return A list of all the credentials registered on the server, * including the newly-registered one. */ suspend fun signinResponse( sessionId: String, response: JSONObject, credentialId: String ): ApiResult<Unit> { val call = client.newCall( Builder().url("$BASE_URL/signinResponse") .addHeader("Cookie", formatCookie(sessionId)) .method( "POST", jsonRequestBody { name("id").value(credentialId) name("type").value(PUBLIC_KEY.toString()) name("rawId").value(credentialId) name("response").objectValue { name("clientDataJSON").value( response.getString("clientDataJSON") ) name("authenticatorData").value( response.getString("authenticatorData") ) name("signature").value( response.getString("signature") ) name("userHandle").value( response.getString("userHandle") ) } } ).build() ) val apiResponse = call.await() return apiResponse.result("Error calling /signingResponse") { } }Intent başlatıcı ve etkinlik sonucu çağrılarını işleyen tüm yöntemleri görünümünüzden güvenli bir şekilde kaldırın.
signInRequest()artık birJSONObjectdöndürdüğündenPendingIntentoluşturmanız gerekmez. Döndürülen intent'iJSONObjectile değiştirin ve API yöntemlerinizdengetCredential()yöntemini çağırın.suspend fun getPasskey( activity: Activity, creationResult: JSONObject ): GetCredentialResponse? { Toast.makeText( activity, "Fetching previously stored credentials", Toast.LENGTH_SHORT ) .show() var result: GetCredentialResponse? = null try { val request = GetCredentialRequest( listOf( GetPublicKeyCredentialOption( creationResult.toString(), null ), GetPasswordOption() ) ) result = credMan.getCredential(activity, request) if (result.credential is PublicKeyCredential) { val publicKeycredential = result.credential as PublicKeyCredential Log.i("TAG", "Passkey ${publicKeycredential.authenticationResponseJson}") return result } } catch (e: Exception) { showErrorAlert(activity, e) } return result }Çağrı başarılı olduktan sonra, kullanıcının kimliğini doğrulamak için yanıtı sunucuya geri gönderin. Bu API çağrısının istek ve yanıt parametreleri FIDO2 uygulamasına benzer olduğundan herhangi bir değişiklik yapılması gerekmez.
Ek kaynaklar
- Kimlik Bilgisi Yöneticisi örnek referansı
- Kimlik Bilgisi Yöneticisi Codelab'i
- Credential Manager API'yi kullanarak geçiş anahtarlarıyla uygulamalarınızda sorunsuz kimlik doğrulama sağlama
- FIDO2 codelab