Kimlik Bilgisi Yöneticisi, tek bir API'de kullanıcı adı ve şifre, geçiş anahtarları ve birleşik oturum açma çözümleri (ör. Google ile oturum açma) gibi çoklu oturum açma yöntemlerini destekleyen bir Jetpack API'dir. Böylece geliştiriciler için entegrasyonu basitleştirir.
Dahası, Kimlik Bilgisi Yöneticisi kullanıcılar için kimlik doğrulama yöntemlerinde oturum açma arayüzünü birleştirerek kullanıcıların seçtikleri yöntemden bağımsız olarak uygulamalarda oturum açmalarını daha net ve kolay hale getirir.
Bu sayfada, geçiş anahtarı kavramı ve Authentication Manager API'yi kullanarak geçiş anahtarları dahil olmak üzere kimlik doğrulama çözümleri için istemci tarafı desteği uygulama adımları açıklanmaktadır. Daha ayrıntılı ve özel soruların yanıtlarının yer aldığı ayrı bir SSS sayfası da vardır.
Geri bildiriminiz, Credential Manager API'sinin geliştirilmesinde çok önemli bir rol oynar. API'yi iyileştirmek için bulduğunuz sorunları veya fikirlerinizi aşağıdaki bağlantıyı kullanarak paylaşabilirsiniz:
Geçiş anahtarları hakkında
Geçiş anahtarları, şifrelerin daha güvenli ve kolay bir şekilde değiştirilmesini sağlar. Geçiş anahtarları sayesinde kullanıcılar biyometrik sensör (parmak izi veya yüz tanıma gibi), PIN veya desen kullanarak uygulamalarda ve web sitelerinde oturum açabilir. Bu, sorunsuz bir oturum açma deneyimi sunarak kullanıcılarınızın kullanıcı adlarını veya şifrelerini hatırlama zorunluluğunu ortadan kaldırır.
Geçiş anahtarları, FIDO Alliance ve World Wide Web Consortium (W3C) tarafından ortaklaşa geliştirilen WebAuthn (Web Authentication) standardına dayanır. WebAuthn, kullanıcının kimliğini doğrulamak için ortak anahtar kriptografisini kullanır. Kullanıcının oturum açtığı web sitesi veya uygulama, ortak anahtarı görüp depolayabilir, ancak gizli anahtarı hiçbir zaman göremez. Özel anahtar gizli ve güvende tutulur. Hem benzersiz olan hem de web sitesine veya uygulamaya bağlı olan geçiş anahtarları, kimlik avına karşı korunur ve güvenliği daha da artırır.
Kimlik Bilgisi Yöneticisi, kullanıcıların geçiş anahtarları oluşturmasına ve bunları Google Şifre Yöneticisi'nde depolamasına olanak tanır.
Ön koşullar
Kimlik Bilgisi Yöneticisi'ni kullanmak için bu bölümdeki adımları tamamlayın.
Güncel bir platform sürümü kullanın
Kimlik Bilgisi Yöneticisi, Android 4.4 (API düzeyi 19) ve sonraki sürümlerde desteklenir.
Uygulamanıza bağımlılık ekleyin
Uygulama modülünüzün derleme komut dosyasına aşağıdaki bağımlılıkları ekleyin:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.2.0") // optional - needed for credentials support from play services, for devices running // Android 13 and below. implementation("androidx.credentials:credentials-play-services-auth:1.2.0") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.2.0" // optional - needed for credentials support from play services, for devices running // Android 13 and below. implementation "androidx.credentials:credentials-play-services-auth:1.2.0" }
ProGuard dosyasındaki sınıfları koru
Modülünüzün proguard-rules.pro
dosyasına aşağıdaki yönergeleri ekleyin:
-if class androidx.credentials.CredentialManager
-keep class androidx.credentials.playservices.** {
*;
}
Uygulamanızı küçültme, gizleme ve optimize etme hakkında daha fazla bilgi edinin.
Digital Asset Links için destek ekleyin
Android uygulamanızda geçiş anahtarı desteğini etkinleştirmek için uygulamanızı, ait olduğu bir web sitesiyle ilişkilendirin. Aşağıdaki adımları tamamlayarak bu ilişkilendirmeyi beyan edebilirsiniz:
Bir Digital Asset Links JSON dosyası oluşturun. Örneğin,
https://signin.example.com
web sitesinin vecom.example
paket adlı bir Android uygulamasının oturum açma kimlik bilgilerini paylaşabileceğini beyan etmek için aşağıdaki içeriğe sahipassetlinks.json
adlı bir dosya oluşturun:[ { "relation" : [ "delegate_permission/common.handle_all_urls", "delegate_permission/common.get_login_creds" ], "target" : { "namespace" : "android_app", "package_name" : "com.example.android", "sha256_cert_fingerprints" : [ SHA_HEX_VALUE ] } } ]
relation
alanı, bildirilmekte olan ilişkiyi açıklayan bir veya daha fazla dizeden oluşan bir dizidir. Uygulamaların ve sitelerin oturum açma kimlik bilgilerini paylaştığını beyan etmek içindelegate_permission/handle_all_urls
vedelegate_permission/common.get_login_creds
ilişkilerini belirtin.target
alanı, bildirimin geçerli olduğu öğeyi belirten bir nesnedir. Aşağıdaki alanlar bir web sitesini tanımlar:namespace
web
site
Web sitesinin
https://domain[:optional_port]
biçimindeki URL'si; örneğin,https://www.example.com
.domain tam nitelikli olmalı ve HTTPS için 443 numaralı bağlantı noktası kullanılırken optional_port atlanmalıdır.
site
hedefi yalnızca bir kök alan olabilir: Uygulama ilişkilendirmesini belirli bir alt dizinle sınırlayamazsınız. URL'ye eğik çizgi gibi bir yol eklemeyin.Alt alan adları eşleşmiş olarak kabul edilmez. Yani domain alanını
www.example.com
olarak belirtirsenizwww.counter.example.com
alanı, uygulamanızla ilişkilendirilmez.Aşağıdaki alanlar bir Android uygulamasını tanımlar:
namespace
android_app
package_name
Uygulamanın manifest dosyasında belirtilen paket adı. Örneğin, com.example.android
sha256_cert_fingerprints
Uygulamanızın imza sertifikasının SHA256 parmak izleridir. Digital Assets Link JSON dosyasını, oturum açma alanında aşağıdaki konumda barındırın:
https://domain[:optional_port]/.well-known/assetlinks.json
Örneğin, oturum açma alanınız
signin.example.com
ise JSON dosyasınıhttps://signin.example.com/.well-known/assetlinks.json
adresinde barındırın.Digital Assets Link dosyasının MIME türü JSON olmalıdır. Sunucunun yanıtta bir
Content-Type: application/json
üst bilgisi gönderdiğinden emin olun.Barındırıcınızın, Google'ın Dijital Öğe Bağlantısı dosyanızı almasına izin verdiğinden emin olun.
robots.txt
dosyanız varsa Googlebot aracısının/.well-known/assetlinks.json
dosyasını almasına izin vermelidir. Çoğu site, diğer hizmetlerin bu dosyalardaki meta verilere erişebilmesi için otomatik aracıların/.well-known/
yolundaki dosyaları almasına izin verebilir:User-agent: * Allow: /.well-known/
Kimlik Bilgisi Yöneticisi üzerinden şifreyle oturum açmayı kullanıyorsanız manifest'te dijital varlık bağlantısını yapılandırmak için bu adımı uygulayın. Yalnızca geçiş anahtarı kullanıyorsanız bu adım gerekli değildir.
İlişkilendirmeyi Android uygulamasında bildirin. Yüklenecek
assetlinks.json
dosyalarını belirten bir nesne ekleyin. Dizede kullandığınız kesme işareti ve tırnak işaretlerini kullanmaktan kaçınmalısınız. Örneğin:<string name="asset_statements" translatable="false"> [{ \"include\": \"https://signin.example.com/.well-known/assetlinks.json\" }] </string>
> GET /.well-known/assetlinks.json HTTP/1.1 > User-Agent: curl/7.35.0 > Host: signin.example.com < HTTP/1.1 200 OK < Content-Type: application/json
Kimlik Bilgisi Yöneticisi'ni yapılandırma
Bir CredentialManager
nesnesini yapılandırıp başlatmak için aşağıdakine benzer bir mantık ekleyin:
Kotlin
// Use your app or activity context to instantiate a client instance of // CredentialManager. val credentialManager = CredentialManager.create(context)
Java
// Use your app or activity context to instantiate a client instance of // CredentialManager. CredentialManager credentialManager = CredentialManager.create(context)
Kimlik bilgisi alanlarını belirtin
Android 14 ve sonraki sürümlerde isCredential
özelliği, kullanıcı adı veya şifre alanları gibi kimlik bilgisi alanlarını belirtmek için kullanılabilir. Bu özellik, bu görünümün Kimlik Bilgisi Yöneticisi ve üçüncü taraf kimlik bilgisi sağlayıcıları ile çalışmak üzere tasarlanmış bir kimlik bilgisi alanı olduğunu belirtir ve otomatik doldurma hizmetlerinin daha iyi otomatik doldurma önerileri sağlamasına yardımcı olur. Uygulama, Credential Manager API'sini kullandığında, kullanılabilir kimlik bilgilerini içeren Kimlik Bilgisi Yöneticisi alt sayfası görüntülenir ve kullanıcı adı veya şifre için otomatik doldurmanın doldurma iletişim kutusunun gösterilmesine gerek yoktur.
isCredential
özelliğini kullanmak için ilgili Görünümler'e ekleyin:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isCredential="true"
...
/>
Kullanıcınızın oturumunu açma
Kullanıcının hesabıyla ilişkili tüm geçiş anahtarı ve şifre seçeneklerini almak için şu adımları tamamlayın:
Şifreyi ve geçiş anahtarı kimlik doğrulama seçeneklerini ilk kullanıma hazırlayın:
Kotlin
// Retrieves the user's saved password for your app from their // password provider. val getPasswordOption = GetPasswordOption() // Get passkey from the user's public key credential provider. val getPublicKeyCredentialOption = GetPublicKeyCredentialOption( requestJson = requestJson )
Java
// Retrieves the user's saved password for your app from their // password provider. GetPasswordOption getPasswordOption = new GetPasswordOption(); // Get passkey from the user's public key credential provider. GetPublicKeyCredentialOption getPublicKeyCredentialOption = new GetPublicKeyCredentialOption(requestJson);
Oturum açma isteğini oluşturmak için önceki adımda alınan seçenekleri kullanın.
Kotlin
val getCredRequest = GetCredentialRequest( listOf(getPasswordOption, getPublicKeyCredentialOption) )
Java
GetCredentialRequest getCredRequest = new GetCredentialRequest.Builder() .addCredentialOption(getPasswordOption) .addCredentialOption(getPublicKeyCredentialOption) .build();
Oturum açma akışını başlatın:
Kotlin
coroutineScope.launch { try { val result = credentialManager.getCredential( // Use an activity-based context to avoid undefined system UI // launching behavior. context = activityContext, request = getCredRequest ) handleSignIn(result) } catch (e : GetCredentialException) { handleFailure(e) } } fun handleSignIn(result: GetCredentialResponse) { // Handle the successfully returned credential. val credential = result.credential when (credential) { is PublicKeyCredential -> { val responseJson = credential.authenticationResponseJson // Share responseJson i.e. a GetCredentialResponse on your server to // validate and authenticate } is PasswordCredential -> { val username = credential.id val password = credential.password // Use id and password to send to your server to validate // and authenticate } is CustomCredential -> { // If you are also using any external sign-in libraries, parse them // here with the utility functions provided. if (credential.type == ExampleCustomCredential.TYPE) { try { val ExampleCustomCredential = ExampleCustomCredential.createFrom(credential.data) // Extract the required credentials and complete the authentication as per // the federated sign in or any external sign in library flow } catch (e: ExampleCustomCredential.ExampleCustomCredentialParsingException) { // Unlikely to happen. If it does, you likely need to update the dependency // version of your external sign-in library. Log.e(TAG, "Failed to parse an ExampleCustomCredential", e) } } else { // Catch any unrecognized custom credential type here. Log.e(TAG, "Unexpected type of credential") } } else -> { // Catch any unrecognized credential type here. Log.e(TAG, "Unexpected type of credential") } } }
Java
credentialManager.getCredentialAsync( // Use activity based context to avoid undefined // system UI launching behavior activity, getCredRequest, cancellationSignal, <executor>, new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() { @Override public void onSuccess(GetCredentialResponse result) { handleSignIn(result); } @Override public void onFailure(GetCredentialException e) { handleFailure(e); } } ); public void handleSignIn(GetCredentialResponse result) { // Handle the successfully returned credential. Credential credential = result.getCredential(); if (credential instanceof PublicKeyCredential) { String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson(); // Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate } else if (credential instanceof PasswordCredential) { String username = ((PasswordCredential) credential).getId(); String password = ((PasswordCredential) credential).getPassword(); // Use id and password to send to your server to validate and authenticate } else if (credential instanceof CustomCredential) { if (ExampleCustomCredential.TYPE.equals(credential.getType())) { try { ExampleCustomCredential customCred = ExampleCustomCredential.createFrom(customCredential.getData()); // Extract the required credentials and complete the // authentication as per the federated sign in or any external // sign in library flow } catch (ExampleCustomCredential.ExampleCustomCredentialParsingException e) { // Unlikely to happen. If it does, you likely need to update the // dependency version of your external sign-in library. Log.e(TAG, "Failed to parse an ExampleCustomCredential", e); } } else { // Catch any unrecognized custom credential type here. Log.e(TAG, "Unexpected type of credential"); } } else { // Catch any unrecognized credential type here. Log.e(TAG, "Unexpected type of credential"); } }
Aşağıdaki örnekte, geçiş anahtarı aldığınızda JSON isteğinin nasıl biçimlendirileceği gösterilmektedir:
{
"challenge": "T1xCsnxM2DNL2KdK5CLa6fMhD7OBqho6syzInk_n-Uo",
"allowCredentials": [],
"timeout": 1800000,
"userVerification": "required",
"rpId": "credential-manager-app-test.glitch.me"
}
Aşağıdaki örnekte, ortak anahtar kimlik bilgisini aldıktan sonra bir JSON yanıtının nasıl görünebileceği gösterilmektedir:
{
"id": "KEDetxZcUfinhVi6Za5nZQ",
"type": "public-key",
"rawId": "KEDetxZcUfinhVi6Za5nZQ",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiVDF4Q3NueE0yRE5MMktkSzVDTGE2Zk1oRDdPQnFobzZzeXpJbmtfbi1VbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
"authenticatorData": "j5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGQdAAAAAA",
"signature": "MEUCIQCO1Cm4SA2xiG5FdKDHCJorueiS04wCsqHhiRDbbgITYAIgMKMFirgC2SSFmxrh7z9PzUqr0bK1HZ6Zn8vZVhETnyQ",
"userHandle": "2HzoHm_hY0CjuEESY9tY6-3SdjmNHOoNqaPDcZGzsr0"
}
}
Kimlik bilgisi olmadığında istisnaları işleme
Bazı durumlarda, kullanıcıya ait herhangi bir kimlik bilgisi olmayabilir veya kullanıcı mevcut kimlik bilgilerinin kullanılmasına izin vermeyebilir. getCredential()
çağrılırsa ve kimlik bilgileri bulunamazsa bir NoCredentialException
döndürülür. Bu durumda, kodunuz NoCredentialException
örneklerini işleyecektir.
Kotlin
try {
val credential = credentialManager.getCredential(credentialRequest)
} catch (e: NoCredentialException) {
Log.e("CredentialManager", "No credential available", e)
}
Java
try {
Credential credential = credentialManager.getCredential(credentialRequest);
} catch (NoCredentialException e) {
Log.e("CredentialManager", "No credential available", e);
}
Android 14 veya sonraki sürümlerde, getCredential()
çağrısı yapmadan önce prepareGetCredential()
yöntemini kullanarak hesap seçiciyi gösterirken gecikmeyi azaltabilirsiniz.
Kotlin
val response = credentialManager.prepareGetCredential(
GetCredentialRequest(
listOf(
<getPublicKeyCredentialOption>,
<getPasswordOption>
)
)
}
Java
GetCredentialResponse response = credentialManager.prepareGetCredential(
new GetCredentialRequest(
Arrays.asList(
new PublicKeyCredentialOption(),
new PasswordOption()
)
)
);
prepareGetCredential()
yöntemi, kullanıcı arayüzü öğelerini çağırmaz. Bu yalnızca hazırlık işini gerçekleştirmenize yardımcı olur. Böylece daha sonra getCredential()
API aracılığıyla kalan kimlik bilgisi işlemini (kullanıcı arayüzleri dahil) başlatabilirsiniz.
Önbelleğe alınan veriler bir PrepareGetCredentialResponse
nesnesinde döndürülür. Mevcut kimlik bilgileri varsa sonuçlar önbelleğe alınır. Daha sonra, hesap seçiciyi önbelleğe alınan verilerle birlikte açmak için kalan getCredential()
API'yi başlatabilirsiniz.
Kayıt akışları
Bir kullanıcıyı kimlik doğrulama için geçiş anahtarı veya şifre kullanarak kaydedebilirsiniz.
Geçiş anahtarı oluşturma
Kullanıcılara geçiş anahtarı kaydetme ve yeniden kimlik doğrulama için kullanma seçeneği sunmak için kullanıcı kimlik bilgilerini CreatePublicKeyCredentialRequest
nesnesi kullanarak kaydedin.
Kotlin
fun createPasskey(requestJson: String, preferImmediatelyAvailableCredentials: Boolean) { val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest( // Contains the request in JSON format. Uses the standard WebAuthn // web JSON spec. requestJson = requestJson, // Defines whether you prefer to use only immediately available // credentials, not hybrid credentials, to fulfill this request. // This value is false by default. preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials, ) // Execute CreateCredentialRequest asynchronously to register credentials // for a user account. Handle success and failure cases with the result and // exceptions, respectively. coroutineScope.launch { try { val result = credentialManager.createCredential( // Use an activity-based context to avoid undefined system // UI launching behavior context = activityContext, request = createPublicKeyCredentialRequest, ) handlePasskeyRegistrationResult(result) } catch (e : CreateCredentialException){ handleFailure(e) } } } fun handleFailure(e: CreateCredentialException) { when (e) { is CreatePublicKeyCredentialDomException -> { // Handle the passkey DOM errors thrown according to the // WebAuthn spec. handlePasskeyError(e.domError) } is CreateCredentialCancellationException -> { // The user intentionally canceled the operation and chose not // to register the credential. } is CreateCredentialInterruptedException -> { // Retry-able error. Consider retrying the call. } is CreateCredentialProviderConfigurationException -> { // Your app is missing the provider configuration dependency. // Most likely, you're missing the // "credentials-play-services-auth" module. } is CreateCredentialUnknownException -> ... is CreateCredentialCustomException -> { // You have encountered an error from a 3rd-party SDK. If you // make the API call with a request object that's a subclass of // CreateCustomCredentialRequest using a 3rd-party SDK, then you // should check for any custom exception type constants within // that SDK to match with e.type. Otherwise, drop or log the // exception. } else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}") } }
Java
public void createPasskey(String requestJson, boolean preferImmediatelyAvailableCredentials) { CreatePublicKeyCredentialRequest createPublicKeyCredentialRequest = // `requestJson` contains the request in JSON format. Uses the standard // WebAuthn web JSON spec. // `preferImmediatelyAvailableCredentials` defines whether you prefer // to only use immediately available credentials, not hybrid credentials, // to fulfill this request. This value is false by default. new CreatePublicKeyCredentialRequest( requestJson, preferImmediatelyAvailableCredentials); // Execute CreateCredentialRequest asynchronously to register credentials // for a user account. Handle success and failure cases with the result and // exceptions, respectively. credentialManager.createCredentialAsync( // Use an activity-based context to avoid undefined system // UI launching behavior requireActivity(), createPublicKeyCredentialRequest, cancellationSignal, executor, new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() { @Override public void onResult(CreateCredentialResponse result) { handleSuccessfulCreatePasskeyResult(result); } @Override public void onError(CreateCredentialException e) { if (e instanceof CreatePublicKeyCredentialDomException) { // Handle the passkey DOM errors thrown according to the // WebAuthn spec. handlePasskeyError(((CreatePublicKeyCredentialDomException)e).getDomError()); } else if (e instanceof CreateCredentialCancellationException) { // The user intentionally canceled the operation and chose not // to register the credential. } else if (e instanceof CreateCredentialInterruptedException) { // Retry-able error. Consider retrying the call. } else if (e instanceof CreateCredentialProviderConfigurationException) { // Your app is missing the provider configuration dependency. // Most likely, you're missing the // "credentials-play-services-auth" module. } else if (e instanceof CreateCredentialUnknownException) { } else if (e instanceof CreateCredentialCustomException) { // You have encountered an error from a 3rd-party SDK. If // you make the API call with a request object that's a // subclass of // CreateCustomCredentialRequest using a 3rd-party SDK, // then you should check for any custom exception type // constants within that SDK to match with e.type. // Otherwise, drop or log the exception. } else { Log.w(TAG, "Unexpected exception type " + e.getClass().getName()); } } } ); }
JSON isteğini biçimlendirme
Oluşturduğunuz geçiş anahtarını bir kullanıcı hesabıyla ilişkilendirmeniz ve geçiş anahtarının ortak anahtarını sunucunuzda saklamanız gerekir. Aşağıdaki snippet'te, geçiş anahtarı oluşturduğunuzda JSON isteğinin nasıl biçimlendirileceğine dair bir örnek gösterilmektedir.
Uygulamalarınızda sorunsuz kimlik doğrulama olanağı sunmayla ilgili bu blog yayınında, geçiş anahtarı oluşturduğunuzda ve geçiş anahtarı kullanarak kimlik doğrularken JSON isteğinizi nasıl biçimlendireceğiniz gösterilmektedir. Ayrıca şifrelerin neden etkili bir kimlik doğrulama çözümü olmadığı, mevcut biyometrik kimlik bilgilerinden nasıl yararlanılacağı, uygulamanızı sahip olduğunuz web sitesiyle nasıl ilişkilendireceğiniz, geçiş anahtarları nasıl oluşturacağınız ve geçiş anahtarları kullanarak nasıl kimlik doğrulama yapacağınız açıklanmaktadır.
{
"challenge": "nhkQXfE59Jb97VyyNJkvDiXucMEvltduvcrDmGrODHY",
"rp": {
"name": "CredMan App Test",
"id": "credential-manager-app-test.glitch.me"
},
"user": {
"id": "2HzoHm_hY0CjuEESY9tY6-3SdjmNHOoNqaPDcZGzsr0",
"name": "helloandroid@gmail.com",
"displayName": "helloandroid@gmail.com"
},
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
},
{
"type": "public-key",
"alg": -257
}
],
"timeout": 1800000,
"attestation": "none",
"excludeCredentials": [],
"authenticatorSelection": {
"authenticatorAttachment": "platform",
"requireResidentKey": true,
"residentKey": "required",
"userVerification": "required"
}
}
AuthenticatorEk için değerleri ayarlama
authenticatorAttachment
parametresi yalnızca kimlik bilgisi oluşturma zamanında ayarlanabilir. platform
ve cross-platform
seçeneklerini belirtebilir veya hiç değer belirtmeyebilirsiniz. Çoğu durumda, herhangi bir
değer önerilmez.
platform
: Kullanıcının geçerli cihazını kaydetmek veya şifreli kullanıcıdan oturum açtıktan sonra şifre anahtarına yükseltmesini istemek içinauthenticatorAttachment
politikasınıplatform
olarak ayarlayın.cross-platform
: Bu değer, genellikle çok öğeli kimlik bilgilerini kaydederken kullanılır ve geçiş anahtarı bağlamında kullanılmaz.- Değer yok: Kullanıcılara tercih ettikleri cihazlarda (ör. hesap ayarlarında) geçiş anahtarı oluşturma esnekliği sunmak için geçiş anahtarı eklemeyi seçtiğinde
authenticatorAttachment
parametresi belirtilmemelidir. Çoğu durumda, parametreyi belirtmeden bırakmak en iyi seçenektir.
JSON yanıtını işleme
Aşağıdaki kod snippet'i, ortak anahtar kimlik bilgisi oluşturmak için örnek bir JSON yanıtı göstermektedir. Döndürülen ortak anahtar kimlik bilgilerinin nasıl işleneceği hakkında daha fazla bilgi edinin.
{
"id": "KEDetxZcUfinhVi6Za5nZQ",
"type": "public-key",
"rawId": "KEDetxZcUfinhVi6Za5nZQ",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoibmhrUVhmRTU5SmI5N1Z5eU5Ka3ZEaVh1Y01Fdmx0ZHV2Y3JEbUdyT0RIWSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUj5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGRdAAAAAAAAAAAAAAAAAAAAAAAAAAAAEChA3rcWXFH4p4VYumWuZ2WlAQIDJiABIVgg4RqZaJyaC24Pf4tT-8ONIZ5_Elddf3dNotGOx81jj3siWCAWXS6Lz70hvC2g8hwoLllOwlsbYatNkO2uYFO-eJID6A"
}
}
JSON'un istemci verilerinden kaynağı doğrulayın
origin
, isteğin geldiği uygulama veya web sitesini temsil eder ve geçiş anahtarları tarafından kimlik avı saldırılarına karşı koruma sağlamak için kullanılır.
Uygulamanızın sunucusunun, istemci veri kaynağını onaylı uygulamalar ve web sitelerinden oluşan bir izin verilenler listesiyle karşılaştırarak kontrol etmesi gerekir. Sunucu, tanınmayan bir kaynaktan bir uygulama veya web sitesinden istek alırsa isteğin reddedilmesi gerekir.
Web örneğinde origin
, kimlik bilgilerinin oturum açtığı aynı site kaynağını yansıtır. Örneğin, https://www.example.com:8443/store?category=shoes#athletic
URL'si verildiğinde origin
https://www.example.com:8443
'dir.
Android uygulamalarında, kullanıcı aracısı otomatik olarak origin
yönergesini çağıran uygulamanın imzasına ayarlar. Geçiş API'sini çağıranı doğrulamak için bu imzanın sunucunuzda bir eşleşme olarak doğrulanması gerekir. Android origin
, APK imzalama sertifikasının SHA-256 karmasından türetilen bir URI'dir. Örneğin:
android:apk-key-hash:<sha256_hash-of-apk-signing-cert>
Bir anahtar deposundaki imzalama sertifikalarının SHA-256 karmaları, aşağıdaki terminal komutu çalıştırılarak bulunabilir:
keytool -list -keystore <path-to-apk-signing-keystore>
SHA-256 karmaları, iki nokta üst üste işaretiyle ayrılmış onaltılık biçimde (91:F7:CB:F9:D6:81…
) ve Android origin
değerleri base64url olarak kodlanmıştır.
Bu Python örneği, karma biçiminin uyumlu, iki nokta üst üste işaretiyle ayrılmış onaltılık biçime nasıl dönüştürüleceğini gösterir:
import binascii
import base64
fingerprint = '91:F7:CB:F9:D6:81:53:1B:C7:A5:8F:B8:33:CC:A1:4D:AB:ED:E5:09:C5'
print("android:apk-key-hash:" + base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))
fingerprint
değerini kendi değerinizle değiştirin. Örnek bir sonuç şöyle:
android:apk-key-hash:kffL-daBUxvHpY-4M8yhTavt5QnFEI2LsexohxrGPYU
Ardından bu dizeyi sunucunuzda izin verilen bir kaynak olarak eşleştirebilirsiniz. Hata ayıklama ve yayınlama sertifikaları gibi birden fazla imzalama sertifikanız veya birden fazla uygulamanız varsa işlemi tekrarlayın ve bu kaynakların tümünü sunucuda geçerli olarak kabul edin.
Kullanıcı şifrelerini kaydetme
Kullanıcı, uygulamanızdaki kimlik doğrulama akışı için bir kullanıcı adı ve şifre sağlarsa kullanıcının kimliğini doğrulamak için kullanılabilecek bir kullanıcı kimlik bilgisi kaydedebilirsiniz. Bunu yapmak için bir CreatePasswordRequest
nesnesi oluşturun:
Kotlin
fun registerPassword(username: String, password: String) { // Initialize a CreatePasswordRequest object. val createPasswordRequest = CreatePasswordRequest(id = username, password = password) // Create credential and handle result. coroutineScope.launch { try { val result = credentialManager.createCredential( // Use an activity based context to avoid undefined // system UI launching behavior. activityContext, createPasswordRequest ) handleRegisterPasswordResult(result) } catch (e: CreateCredentialException) { handleFailure(e) } } }
Java
void registerPassword(String username, String password) { // Initialize a CreatePasswordRequest object. CreatePasswordRequest createPasswordRequest = new CreatePasswordRequest(username, password); // Register the username and password. credentialManager.createCredentialAsync( // Use an activity-based context to avoid undefined // system UI launching behavior requireActivity(), createPasswordRequest, cancellationSignal, executor, new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() { @Override public void onResult(CreateCredentialResponse result) { handleResult(result); } @Override public void onError(CreateCredentialException e) { handleFailure(e); } } ); }
Destek kimlik bilgisi kurtarma
Bir kullanıcının kimlik bilgilerini depoladığı bir cihaza artık erişimi yoksa güvenli bir çevrimiçi yedekten kurtarması gerekebilir. Bu kimlik bilgisi kurtarma işlemini nasıl destekleyeceğiniz hakkında daha fazla bilgi edinmek için şu blog yayınındaki "Erişimi kurtarma veya yeni cihaz ekleme" başlıklı bölümü okuyun: Google Şifre Yöneticisi'ndeki geçiş anahtarlarının güvenliği.
Geçiş anahtarı uç noktaları iyi bilinen URL'leri ile şifre yönetimi araçları için destek ekleyin
Şifre ve kimlik bilgisi yönetim araçlarıyla sorunsuz entegrasyon ve gelecekte uyumluluk için iyi bilinen geçiş anahtarı uç noktaları için destek eklemenizi öneririz. Bu, uyumlu tarafların geçiş anahtarı desteklerini resmi olarak tanıtması ve geçiş anahtarı kaydı ve yönetimi için doğrudan bağlantılar sağlaması için açık bir protokoldür.
- Bir web sitesi ile Android ve iOS uygulamaları bulunan
https://example.com
kuruluşunda bağlı bir taraf için iyi bilinen URLhttps://example.com/.well-known/passkey-endpoints
olur. URL sorgulandığında yanıtta aşağıdaki şema kullanılmalıdır.
{ "enroll": "https://example.com/account/manage/passkeys/create" "manage": "https://example.com/account/manage/passkeys" }
Bu bağlantının web yerine doğrudan uygulamanızda açılmasını sağlamak için Android uygulama bağlantılarını kullanın.
GitHub'daki geçiş anahtarı uç noktaları iyi bilinen URL'si açıklayıcısında daha ayrıntılı bilgi bulabilirsiniz.
Sık karşılaşılan hataları giderme
Aşağıdaki tabloda, yaygın olarak karşılaşılan birkaç hata kodu ve açıklama gösterilmiş, ayrıca nedenleri hakkında bazı bilgiler verilmektedir:
Hata kodu ve açıklaması | Neden |
---|---|
Oturum Açma Başlangıcında Hata: 16: Arayan, çok sayıda iptal edilen oturum açma istemi nedeniyle geçici olarak engellendi. | Geliştirme sırasında bu 24 saatlik bekleme süresiyle karşılaşırsanız Google Play hizmetlerinin uygulama depolama alanını temizleyerek bu süreyi sıfırlayabilirsiniz. Alternatif olarak, bu bekleme süresini bir test cihazında veya emülatörde değiştirmek için Çevirici uygulamasına gidip şu kodu girin:
|
Başlangıçta Oturum Açma Hatası: 8: Bilinmeyen dahili hata. |
|
CreatePublicKeyCredentialDomException: Gelen istek doğrulanamıyor | Uygulamanın paket kimliği sunucunuza kayıtlı değil. Bunu sunucu tarafı entegrasyonunuzda doğrulayın. |
CreateCredentialUnknownException: Şifre kaydetme sırasında, tek dokunuşla şifre hatası yanıtı bulundu 16: Kullanıcı büyük olasılıkla Android Autofill ile sorulacağı için şifre kaydetme adımı atlanıyor. | Bu hata yalnızca Android 13 ve önceki sürümlerde ve yalnızca otomatik doldurma sağlayıcısı Google ise ortaya çıkar. Bu durumda, kullanıcılara Otomatik Doldurma'dan kaydetme istemi gösterilir ve şifre Google Şifre Yöneticisi'ne kaydedilir. Google ile otomatik doldurma özelliği kullanılarak kaydedilen kimlik bilgilerinin, Credential Manager API ile iki yönlü olarak paylaşıldığını unutmayın. Sonuç olarak, bu hatayı güvenle yoksayabilirsiniz. |
Ek kaynaklar
Credential Manager API ve geçiş anahtarları hakkında daha fazla bilgi edinmek için aşağıdaki kaynakları görüntüleyin:
- Geçiş anahtarları Kullanıcı Deneyimi Rehberi
- Video: Geçiş anahtarı desteğiyle Android uygulamalarında şifrelere bağımlılığı azaltma
- Codelab: Android uygulamanızda Credential Manager API'yi kullanarak kimlik doğrulama süreçlerini nasıl basitleştireceğinizi öğrenin
- Örnek uygulama: CredentialManager