Kimlik Yöneticisi ile kullanıcınızda oturum açın

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 Yöneticisi, kullanıcılar için kimlik doğrulama yöntemlerinde oturum açma arayüzünü birleştirerek, tercih ettikleri yöntemden bağımsız olarak kullanıcıların uygulamalarda oturum açmasını daha net ve kolay hale getirir.

Bu sayfada geçiş anahtarı kavramı ve Authentication Manager API'yi kullanarak geçiş anahtarları da 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 sorulara cevaplar sağlayan ayrı bir SSS sayfası da vardır.

Geri bildiriminiz, Credential Manager API'sini geliştirmemizde önemli bir rol oynar. API'nin iyileştirilmesiyle ilgili bulduğunuz sorunları veya fikirlerinizi aşağıdaki bağlantıyı kullanarak paylaşabilirsiniz:

Geri bildirim gönderin

Geçiş anahtarları hakkında

Geçiş anahtarları, şifrelerin daha güvenli ve kolay bir şekilde değiştirilmesini sağlar. Geçiş anahtarları ile 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 şekilde sorunsuz bir oturum açma deneyimi sunarak kullanıcılarınızın kullanıcı adlarını veya şifrelerini hatırlamalarına gerek kalmaz.

Geçiş anahtarları, FIDO Alliance ve World Wide Web Consortium (W3C) tarafından ortak 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. Ayrıca, anahtar hem benzersiz hem de web sitesine veya uygulamaya bağlı olduğundan geçiş anahtarları kimlik avına karşı korunmaz ve daha fazla güvenlik sağlar.

Kimlik Bilgisi Yöneticisi, kullanıcıların geçiş anahtarı oluşturmasına ve bunları Google Şifre Yöneticisi'nde saklamasına olanak tanır.

Ön koşullar

Kimlik Bilgisi Yöneticisi'ni kullanmak için bu bölümdeki adımları tamamlayın.

En son platform sürümlerinden birini 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.3.0-alpha02")

    // optional - needed for credentials support from play services, for devices running
    // Android 13 and below.
    implementation("androidx.credentials:credentials-play-services-auth:1.3.0-alpha02")
}

Modern

dependencies {
    implementation "androidx.credentials:credentials:1.3.0-alpha02"

    // optional - needed for credentials support from play services, for devices running
    // Android 13 and below.
    implementation "androidx.credentials:credentials-play-services-auth:1.3.0-alpha02"
}

ProGuard dosyasında sınıfları koruma

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 ekleme

Android uygulamanız için geçiş anahtarı desteğini etkinleştirmek üzere uygulamanızı, uygulamanıza ait bir web sitesiyle ilişkilendirin. Aşağıdaki adımları tamamlayarak bu ilişkilendirmeyi beyan edebilirsiniz:

  1. Digital Asset Links JSON dosyası oluşturun. Örneğin, https://signin.example.com web sitesinin ve com.example paket adına sahip bir Android uygulamasının oturum açma kimlik bilgilerini paylaşabileceğini bildirmek için aşağıdaki içeriğe sahip assetlinks.json adında 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ı, bildirilen 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ı bildirmek için ilişkileri delegate_permission/handle_all_urls ve delegate_permission/common.get_login_creds olarak 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 belirtilmemelidir.

    site hedefi yalnızca bir kök alan olabilir: Uygulama ilişkilendirmesini belirli bir alt dizinle sınırlayamazsınız. URL'nin sonuna eğik çizgi gibi bir yol eklemeyin.

    Alt alan adlarının eşleştiği kabul edilmez. Yani domain alanını www.example.com olarak belirtirseniz www.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.
  2. 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.

  3. 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 bu dosya, 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 herhangi bir otomatik aracının /.well-known/ yolundaki dosyaları almasına izin verebilir:

    User-agent: *
    Allow: /.well-known/
    
  4. <application> altındaki manifest dosyasına aşağıdaki satırı ekleyin:

    <meta-data android:name="asset_statements" android:resource="@string/asset_statements" />
    
  5. Kimlik Bilgisi Yöneticisi üzerinden şifreyle oturum açma özelliğini kullanıyorsanız manifest dosyasında 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. Örnek:

    <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, otomatik doldurma hizmetlerinin daha iyi otomatik doldurma önerileri sunmasına yardımcı olurken aynı zamanda bu görünümün Kimlik Bilgisi Yöneticisi ve üçüncü taraf kimlik bilgisi sağlayıcılarıyla birlikte kullanılması için tasarlanmış bir kimlik bilgisi alanı olduğunu belirtir. Uygulama, Credential Manager API'sini kullandığında, kullanılabilir kimlik bilgilerini içeren Kimlik Bilgisi Yöneticisi alt sayfası gösterilir ve kullanıcı adı veya şifre için otomatik 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:

  1. Şifre ve geçiş anahtarı kimlik doğrulama seçeneklerini başlatı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);
  2. 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();
  3. 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 onResult(GetCredentialResponse result) {
                handleSignIn(result);
            }
    
            @Override
            public void onError(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 kimlik bilgileri bulunmayabilir veya 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, kodunuzun NoCredentialException örneklerini işlemesi gerekir.

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. Yalnızca hazırlık çalışmasını gerçekleştirmenize yardımcı olur. Böylece daha sonra kalan get-credential işlemini (kullanıcı arayüzlerini içerir) getCredential() API aracılığıyla 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 getirmek için kalan getCredential() API'yi başlatabilirsiniz.

Kayıt akışları

Kullanıcıları 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 üzere bir CreatePublicKeyCredentialRequest nesnesi kullanarak kullanıcı kimlik bilgisi 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 genel anahtarını sunucunuzda saklamanız gerekir. Aşağıdaki kod örneğinde, geçiş anahtarı oluşturduğunuzda JSON isteğinin nasıl biçimlendirileceği gösterilmektedir.

Uygulamalarınıza sorunsuz kimlik doğrulama olanağı sunmayla ilgili bu blog yayınında, geçiş anahtarı oluşturduğunuzda ve geçiş anahtarları kullanarak kimlik doğrulama yaparken 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 bir web sitesiyle nasıl ilişkilendireceğiniz, geçiş anahtarı oluşturma ve geçiş anahtarlarını kullanarak nasıl kimlik doğrulama yapacağınız da açıklanmaktadır.

{
  "challenge": "abc123",
  "rp": {
    "name": "Credential Manager example",
    "id": "credential-manager-test.example.com"
  },
  "user": {
    "id": "def456",
    "name": "helloandroid@gmail.com",
    "displayName": "helloandroid@gmail.com"
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    }
  ],
  "timeout": 1800000,
  "attestation": "none",
  "excludeCredentials": [
    {"id": "ghi789", "type": "public-key"},
    {"id": "jkl012", "type": "public-key"}
  ],
  "authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}

AuthenticatorEk için değerler ayarla

authenticatorAttachment parametresi yalnızca kimlik bilgisi oluşturma zamanında ayarlanabilir. platform veya cross-platform değerlerini belirtebilir ya da hiç değer belirtmeyebilirsiniz. Çoğu durumda, hiçbir değer önerilmez.

  • platform: Kullanıcının geçerli cihazını kaydettirmek veya oturum açtıktan sonra şifre kullanan bir kullanıcıdan geçiş anahtarına geçmesini istemek için authenticatorAttachment değerini platform olarak ayarlayın.
  • cross-platform: Bu değer, çok öğeli kimlik bilgileri kaydedilirken yaygın olarak 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.

Yinelenen geçiş anahtarlarının oluşturulmasını engelle

Aynı geçiş anahtarı sağlayıcısına sahip bir geçiş anahtarı varsa yeni bir geçiş anahtarı oluşturulmasını önlemek için isteğe bağlı excludeCredentials dizisinde kimlik bilgisi kimliklerini listeleyin.

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"
  }
}

Kaynağı istemci verileri JSON dosyasından 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 sunucusu, istemci veri kaynağını onaylı uygulamalar ve web sitelerinden oluşan bir izin verilenler listesiyle karşılaştırarak kontrol etmelidir. Sunucu tanınmayan bir kaynaktan bir uygulama veya web sitesinden istek alırsa isteğin reddedilmesi gerekir.

Web durumunda origin, kimlik bilgisinin oturum açıldığı aynı site kaynağını gösterir. Örneğin, https://www.example.com:8443/store?category=shoes#athletic URL'si verildiğinde origin değeri https://www.example.com:8443 olur.

Android uygulamalarında kullanıcı aracısı, origin öğesini çağıran uygulamanın imzasına otomatik olarak ayarlar. Geçiş API'sini arayanı 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'dır. Ö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ı biçimde (91:F7:CB:F9:D6:81…) ve Android origin değerleri base64url olarak kodlanmıştır. Bu Python örneğinde, karma biçiminin iki nokta üst üste işaretiyle ayrılmış uyumlu bir onaltılık biçime nasıl dönüştürüleceği gösterilmektedir:

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ı veya birden fazla uygulamanız gibi birden fazla imzalama sertifikanız varsa işlemi tekrarlayın ve sunucuda geçerli olan tüm kaynakları kabul edin.

Kullanıcı şifresini kaydetme

Kullanıcı, uygulamanızdaki kimlik doğrulama akışı için kullanıcı adı ve şifre sağlarsa kullanıcının kimliğini doğrulamak amacıyla kullanılabilecek bir kullanıcı kimlik bilgisi kaydedebilirsiniz. Bunun 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);
            }
        }
    );
}

Kimlik bilgileri kurtarma desteği

Bir kullanıcının kimlik bilgilerini depoladığı bir cihaza artık erişimi yoksa güvenli bir online 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'lere sahip şifre yönetimi araçları için destek eklendi

Sorunsuz entegrasyon ve gelecekte şifre ve kimlik bilgisi yönetim araçlarıyla uyumluluk sağlamak amacıyla, iyi bilinen geçiş anahtarı uç noktaları için destek eklemenizi öneririz. Bu, uyumlu tarafların geçiş anahtarına yönelik desteğinin resmi olarak reklamını yapması ve geçiş anahtarı kaydı ve yönetimi için doğrudan bağlantılar sağlaması için açık bir protokoldür.

  1. Web sitesi ile Android ve iOS uygulamaları bulunan https://example.com şirketindeki bir bağlı taraf için bilinen URL https://example.com/.well-known/passkey-endpoints olur.
  2. URL sorgulandığında yanıt aşağıdaki şemayı kullanmalıdır.

    {
      "enroll": "https://example.com/account/manage/passkeys/create"
      "manage": "https://example.com/account/manage/passkeys"
    }
    
  3. 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.

  4. GitHub'daki geçiş anahtarı uç noktaları iyi bilinen URL açıklayıcısında daha fazla ayrıntı bulabilirsiniz.

Sık karşılaşılan hataları giderme

Aşağıdaki tabloda yaygın olarak kullanılan bazı hata kodları ve açıklamaları gösterilmiş olup nedenleri hakkında bazı bilgiler verilmektedir:

Hata kodu ve açıklaması Neden
Başlangıçta Oturum Açma Hatası: 16: İptal edilen çok fazla oturum açma istemi nedeniyle arayan 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 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: *#*#66382723#*#*. Çevirici uygulaması tüm girişleri temizler ve kapanabilir, ancak onay mesajı görünmez.

Başlangıçta Oturum Açma Hatası: 8: Bilinmeyen dahili hata.
  1. Cihaz, Google Hesabı ile doğru bir şekilde ayarlanmamıştır.
  2. Geçiş anahtarı JSON'ı yanlış oluşturuluyor.
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ıyla ilgili yanıt bulundu 16: Kullanıcı muhtemelen Android Otomatik Doldurma istemini göreceği için şifre kaydetme işlemi atlanıyor Bu hata yalnızca Android 13 ve önceki sürümlerde ve yalnızca otomatik doldurma sağlayıcısı Google olduğunda görülür. Bu durumda, kullanıcılara Otomatik Doldurma'dan bir 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ı 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: