Dijital kimlik bilgisi isteme

Android uygulamalarında dijital kimlik bilgisi doğrulama, bir kullanıcının kimliğini (ör. resmi kimlik) ve bu kullanıcıyla ilgili özellikleri (ör. sürücü belgesi, akademik derece veya yaş ya da adres gibi özellikler) doğrulamak ve yetkilendirmek için kullanılabilir. Ayrıca, bir varlığın gerçekliğini doğrulamak için kimlik bilgisinin verilmesi ve doğrulanması gereken diğer senaryolarda da kullanılabilir.

Verifier API, Android 9 (API düzeyi 28) ve sonraki sürümlerde desteklenir.

Uygulama

Android projenizde dijital kimlik bilgilerini doğrulamak için aşağıdakileri yapın:

  1. Uygulamanızın derleme komut dosyasına bağımlılıklar ekleyin ve bir CredentialManager sınıfı başlatın.
  2. Dijital kimlik bilgisi isteği oluşturun ve bunu kullanarak DigitalCredentialOption ilk kullanıma hazırlayın, ardından GetCredentialRequest oluşturun.
  3. Başarılı bir GetCredentialResponse almak için oluşturulan istekle getCredential akışını başlatın veya oluşabilecek istisnaları ele alın. Başarıyla alındıktan sonra yanıtı doğrulayın.

Bağımlılıkları ekleme ve başlatma

Gradle derleme komut dosyanıza aşağıdaki bağımlılıkları ekleyin:

dependencies {
    implementation("androidx.credentials:credentials:1.6.0-beta01")
    implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta01")
}

Ardından, CredentialManager sınıfının bir örneğini başlatın.

val credentialManager = CredentialManager.create(context)

Dijital kimlik bilgisi isteği oluşturma

Dijital kimlik bilgisi isteği oluşturun ve bunu kullanarak bir DigitalCredentialOption başlatın.

// The request in the JSON format to conform with
// the JSON-ified Credential Manager - Verifier API request definition.
val requestJson = generateRequestFromServer()
val digitalCredentialOption =
    GetDigitalCredentialOption(requestJson = requestJson)

// Use the option from the previous step to build the `GetCredentialRequest`.
val getCredRequest = GetCredentialRequest(
    listOf(digitalCredentialOption)
)

Aşağıdaki örnekte bir OpenId4Vp1 isteği gösterilmektedir. Bu istekteki alanlarla ilgili ayrıntılar için OpenID belgelerine bakın.

{
  "requests": [
    {
      "protocol": "openid4vp-v1-unsigned",
      "data": {
        "response_type": "vp_token",
        "response_mode": "dc_api",
        "nonce": "OD8eP8BYfr0zyhgq4QCVEGN3m7C1Ht_No9H5fG5KJFk",
        "dcql_query": {
          "credentials": [
            {
              "id": "cred1",
              "format": "mso_mdoc",
              "meta": {
                "doctype_value": "org.iso.18013.5.1.mDL"
              },
              "claims": [
                {
                  "path": [
                    "org.iso.18013.5.1",
                    "family_name"
                  ]
                },
                {
                  "path": [
                    "org.iso.18013.5.1",
                    "given_name"
                  ]
                },
                {
                  "path": [
                    "org.iso.18013.5.1",
                    "age_over_21"
                  ]
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

Kimlik bilgisini alma

Oluşturulan istekle getCredential akışını başlatın. İstek başarılı olursa GetCredentialResponse, başarısız olursa GetCredentialException yanıtını alırsınız.

getCredential akışı, kullanıcının mevcut kimlik bilgisi seçeneklerini sunmak ve seçimini toplamak için Android sistem iletişim kutularını tetikler. Ardından, seçilen kimlik bilgisi seçeneğini içeren cüzdan uygulaması, kullanıcı rızasını almak ve dijital kimlik bilgisi yanıtı oluşturmak için gereken İşlem Gerekiyor'u gerçekleştirmek üzere kullanıcı arayüzlerini gösterir.

coroutineScope.launch {
    try {
        val result = credentialManager.getCredential(
            context = activityContext,
            request = getCredRequest
        )
        verifyResult(result)
    } catch (e : GetCredentialException) {
        handleFailure(e)
    }
}

// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
    val credential = result.credential
    when (credential) {
        is DigitalCredential -> {
            val responseJson = credential.credentialJson
            validateResponseOnServer(responseJson)
        }
        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential ${credential.type}")
        }
    }
}

// Handle failure.
fun handleFailure(e: GetCredentialException) {
  when (e) {
        is GetCredentialCancellationException -> {
            // The user intentionally canceled the operation and chose not
            // to share the credential.
        }
        is GetCredentialInterruptedException -> {
            // Retry-able error. Consider retrying the call.
        }
        is NoCredentialException -> {
            // No credential was available.
        }
        else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
    }
}
getCredential çağrılırken görüntülenen dijital kimlik bilgisi seçiciyi gösteren resim.
Şekil 1. getCredential çağrılırken gösterilen dijital kimlik bilgisi seçici

Esnek çoklu kimlik bilgisi istekleri

Digital Credentials API, OpenID4VP kullanarak aynı anda birden fazla kimlik bilgisi türü istemeyi de destekler:

  • Eş zamanlı istekler: Tek bir kullanıcı işleminde birden fazla kimlik bilgisi isteyin. Örneğin, bir seyahat uygulaması aynı anda biniş kartı ve resmi kimlik isteyebilir. Böylece kullanıcı, tek bir dokunuşla her ikisini de inceleyip onaylayabilir.
  • Esnek karşılama: Çeşitli kimlik bilgisi türlerinden veya verenlerden herhangi birini kabul edin. Örneğin, yaş doğrulama akışı sürücü belgesi veya pasaport kabul edebilir. Böylece kullanıcılar, cüzdanlarında sakladıkları kimlik bilgilerini kullanarak isteği yerine getirebilir.

Tek bir istekte birden fazla kimlik bilgisi isteme örneğini aşağıda bulabilirsiniz:

{
  "credentials": [
    {
      "id": "gov_id1",
      "format": "mso_mdoc",
      "meta": {
        "doctype_value": "org.iso.18013.5.1.mDL"
      },
      "claims": [
        {
          "path": [
            "org.iso.18013.5.1",
            "age_over_21"
          ]
        }
      ]
    },
    {
      "id": "boarding_pass1",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": [
          "https://credentials.example.airline/boarding-pass"
        ]
      },
      "claims": [
        {
          "path": [
            "flight_number"
          ]
        },
        {
          "path": [
            "seat"
          ]
        }
      ]
    }
  ]
}
Birden fazla kimlik bilgisi türü çağrılırken gösterilen dijital kimlik bilgisi seçiciyi gösteren resim.
Şekil 1. Birden fazla kimlik bilgisi türü çağrılırken gösterilen dijital kimlik bilgisi seçici.

Yanıtı işleme

Kimlik bilgisi isteğinde bulunduktan sonra CredentialManager tarafından döndürülen GetCredentialResponse değerini işleyin.

// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
    val credential = result.credential
    when (credential) {
        is DigitalCredential -> {
            val responseJson = credential.credentialJson
            validateResponseOnServer(responseJson)
        }
        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential ${credential.type}")
        }
    }
}

İstisnaları işleme

Uygulamanız, cihazda kimlik bilgisi olmaması veya kullanıcının işlemi iptal etmesi gibi ortaya çıkabilecek hataları işlemelidir:

// Handle failure.
fun handleFailure(e: GetCredentialException) {
    when (e) {
        is GetCredentialCancellationException -> {
            // The user intentionally canceled the operation and chose not
            // to share the credential.
        }
        is GetCredentialInterruptedException -> {
            // Retry-able error. Consider retrying the call.
        }
        is NoCredentialException -> {
            // No credential was available.
        }
        is CreateCredentialUnknownException -> {
            // An unknown, usually unexpected, error has occurred. Check the
            // message error for any additional debugging information.
        }
        is CreateCredentialCustomException -> {
            // You have encountered a custom error thrown by the wallet.
            // If you made 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}")
    }
}