Telefon numarası doğrulamayı uygulama

Bu kılavuzda, kullanıcılarınızın doğrulanmış telefon numaralarını almak için DigitalCredential API'nin nasıl kullanılacağı ayrıntılı olarak açıklanmaktadır. Bu işlem iki adımdan oluşur:

  1. Ön kontrol: Android Telephony API'yi sorgulayarak kullanıcının operatörünün bu API'yi destekleyip desteklemediğini kontrol edin. Operatör desteklenmiyorsa normal SMS akışınıza geri dönün.
  2. TS.43 token isteğinde bulunma: İstemci uygulamanız ("doğrulayıcı"), kullanıcının cihazından geçici bir TS.43 jetonu ister. TS.43 token, operatör tarafından verilen ve kullanıcının kimliğini temsil eden bir kimlik bilgisidir.
  3. Jetonu telefon numarasıyla değiştirme: Uygulamanızın arka ucu, kullanıcının doğrulanmış telefon numarası için TS.43 token değerini bir toplayıcı veya operatörle değiştirir.

Android sürümü uyumluluğu

Telefon Numarası Doğrulama API'si, Android 10 (API düzeyi 29) ve sonraki sürümlerde desteklenir.

Ön koşullar

DigitalCredential API ile telefon numarası doğrulamasını uygulamak için bir toplayıcıda veya mobil operatörde hesabınızın olması gerekir. Toplayıcı, operatörlerle etkileşim kurar ve uygulamanız için gerekli API yüzeyini (genellikle faturalandırılabilir bir bulut API uç noktası olarak) sağlar. Bu kılavuzda, hem toplayıcılar hem de operatörler toplu olarak toplayıcılar şeklinde adlandırılır.

Ayrıca Gradle derleme komut dosyanıza aşağıdaki bağımlılıkları eklemeniz gerekir:

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha02")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02")
}

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha02"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02"
}

Uygulama

Digital Credentials API'yi çağırmadan önce Android Telephony API'yi kullanarak kullanıcının operatörünün bu özelliği destekleyip desteklemediğini kontrol edin.

AndroidManifest.xml dosyanıza READ_PHONE_STATE iznini ekleyin.

val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val carrierId = telephonyManager.getSimCarrierId()

Bu kimlikle, toplayıcı arka ucunuzda TS.43 desteğini doğrulayın. Bu kullanıcının operatörü desteklenmiyorsa Digital Credentials API'yi çağırmak boş bir sonuç döndürür. Bu durumda SMS gibi alternatif bir yönteme başvurabilirsiniz. Aksi takdirde Dijital Kimlik Bilgileri akışına devam edin.

Uçtan uca süreç genellikle şu adımları izler:

  1. Bir toplayıcıdan DCQL (Dijital Kimlik Bilgisi Sorgu Dili) parametreleri isteme: Bir veya daha fazla toplayıcıyı çağırın ve bir dizi DCQL parametresi isteyin. DCQL, her toplayıcıdan ihtiyacınız olan dijital kimlik bilgilerini tam olarak belirtmenize olanak tanır.
  2. OpenID4VP isteğini oluşturun: Uygulamanızın arka ucundan OpenID4VP isteğini oluşturun ve toplayıcıdan gelen DCQL parametrelerini ekleyin. Ardından, OpenID4VP isteğini istemci uygulamanıza gönderin.

  3. Credential Manager API'yi çağırın: İstemci uygulamanızda, OpenID4VP isteğini işletim sistemine göndermek için Credential Manager API'yi kullanın. Yanıt olarak, TS.43 Digital Credential içeren bir OpenID4VP yanıt nesnesi alırsınız. Bu kimlik bilgisi şifrelenmiştir ve şifresi yalnızca ilişkili toplayıcı tarafından çözülebilir. Operatör jetonunu aldıktan sonra istemci uygulamanızdan gelen yanıtı uygulamanın arka ucuna gönderin.

  4. Yanıtı doğrulama: Uygulamanızın arka ucunda OpenID4VP yanıtını doğrulayın.

  5. Telefon numarasıyla değiştirme: Uygulamanızın arka ucundan toplayıcıya TS.43 Digital Credential değerini gönderin. Toplayıcı, kimlik bilgisini doğrular ve doğrulanmış telefon numarasını döndürür.

Telefon numarası doğrulama isteğinin akışını gösteren resim
Şekil 1.Doğrulayıcı arka ucunun bir toplayıcıdan parametre istemesiyle başlayan ve doğrulanmış bir telefon numarasının döndürülmesiyle sona eren telefon numarası doğrulama isteğinin yaşam döngüsü.

Toplayıcıdan DCQL parametreleri isteme

Uygulamanızın arka ucundan, toplayıcıya Dijital Kimlik Bilgisi Sorgu Dili (DCQL) kimlik bilgisi nesnesi için istek gönderin. İsteğinizde tek seferlik rastgele sayı ve istek kimliği sağladığınızdan emin olun. Toplayıcı, aşağıdaki yapıya benzer bir DCQL kimlik bilgisi nesnesi döndürür:

{
  // The credential ID is mapped to the request ID that is sent in your request to the aggregator.
  "id": "aggregator1",
  "format": "dc-authorization+sd-jwt",
  "meta": {
    "vct_values": [
      "number-verification/device-phone-number/ts43"
    ],
    "credential_authorization_jwt": "..."
  },
  "claims": [
    {
      "path": ["subscription_hint"],
      "values": [1]
    },
    {
      "path": ["phone_number_hint"],
      "values": ["+14155552671"]
    }
  ]
}

OpenID4VP isteğini oluşturma

İlk olarak, uygulamanızın arka ucundan, DCQL kimlik bilgisi nesnesini aşağıdaki örnekte gösterildiği gibi bir dcql_query nesnesinin içine yerleştirilmiş credentials dizisine yerleştirerek bir dcql_query nesnesi oluşturun:

"dcql_query": {
  "credentials": [
    {
      "id": "aggregator1",
      "format": "dc-authorization+sd-jwt",
      "meta": {
        "vct_values": [
          "number-verification/device-phone-number/ts43"
        ],
        "credential_authorization_jwt": "..."
      },
      "claims": [
        {
          "path": ["subscription_hint"],
          "values": [1]
        },
        {
          "path": ["phone_number_hint"],
          "values": ["+14155552671"]
        }
      ]
    }
  ]
}

Ardından, aşağıdaki yapıyla bir OpenID4VP isteği oluşturun:

{
  "protocol": "openid4vp-v1-unsigned",
  "data": {
    "response_type": "vp_token",
    "response_mode": "dc_api",
    "nonce": "...",
    "dcql_query": { ... }
  }
}
  • protocol: Telefon numarası doğrulama istekleri için openid4vp-v1-unsigned olarak ayarlanmalıdır.
  • response_type ve response_mode: Sırasıyla vp_token ve dc_api sabit değerleriyle isteğin biçimini belirten sabitler.
  • nonce: Her istek için arka ucunuz tarafından oluşturulan benzersiz bir değer. Toplayıcı DCQL kimlik bilgisi nesnesindeki tek seferlik rastgele sayı, bu tek seferlik rastgele sayıyla eşleşmelidir.
  • dcql_query: Bu durumda, TS.43 Digital Credential isteğinde bulunulduğunu belirtmek için dcql_query kullanın. Diğer dijital kimlik bilgileri için de buradan istekte bulunabilirsiniz.

Ardından, OpenID4VP isteğini bir DigitalCredential API istek nesnesine sarmalayın ve istemci uygulamasına gönderin.

{
  "requests":
    [
      {
        "protocol": "openid4vp-v1-unsigned",
        "data": {
          "response_type": "vp_token",
          "response_mode": "dc_api",
          "nonce": "...",
          "dcql_query": { ... }
        }
      }
    ]
}

Aşağıdaki snippet'te, DigitalCredential API isteğinin nasıl oluşturulacağı gösterilmektedir:

def GenerateDCRequest():
    credentials = []
    aggregator1_dcql = call_aggregator_endpoint(nonce, "aggregator1", additional_params)
    credentials.append(aggregator1_dcql) # You can optionally work with multiple
    # aggregators, or request other types of credentials

    val dc_request =
    {
      "requests":
        [
          {
            "protocol": "openid4vp-v1-unsigned",
            "data": {
              "response_type": "vp_token",
              "response_mode": "dc_api",
              "nonce": "...",
              "dcql_query": {"credentials": credentials}
            }
          }
        ]
    }
    return dc_request

Credential Manager API'yi çağırma

İstemci uygulamanızda, uygulamanızın arka ucu tarafından sağlanan DigitalCredential API isteğiyle Credential Manager API'yi çağırın.

val requestJson = generateTs43DigitalCredentialRequestFromServer()
val digiCredOption = GetDigitalCredentialOption(requestJson = requestJson)
val getCredRequest = GetCredentialRequest(
    listOf(digiCredOption)
)

coroutineScope.launch {
  try {
    val response = credentialManager.getCredential(
      context = activityContext,
      request = getCredRequest
    )
    val credential = response.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}")
      }
    }
  } catch (e : GetCredentialException) {
      // If user cancels the operation, the feature isn't available, or the
      // SIM doesn't support the feature, a GetCredentialCancellationException
      // will be returned. Otherwise, a GetCredentialUnsupportedException will
      // be returned with details in the exception message.
      handleFailure(e)
  }
}

DigitalCredential API yanıtı, OpenID4VP yanıtını içerir. DigitalCredential sonucundan elde edilen tipik bir kimlik bilgisi JSON'u aşağıdaki gibidir:

{
  "protocol": "openid4vp-v1-unsigned",

  "data": {
    "vp_token": {
      "aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
                                             # Credential in an array structure.
    }
  }
}

İstemci uygulamanızdan DigitalCredential API yanıtını arka uç sunucusuna geri gönderin. Burada yanıt doğrulanabilir ve toplayıcı ile doğrulanmış telefon numarasını almak için kullanılabilir.

Bazı durumlarda yanıtta TS.43 hatası olabilir. Hata yanıtı, OpenID4VP hata yanıtı biçimini izleyen bir JSON nesnesidir:

{
  "protocol": "openid4vp-v1-unsigned",

  "data": {
    "error": "<error_code>",
    "error_description": "<Human-readable description of the error>",
  }
}

Olası 2 error_code değeri vardır:

  • invalid_request: Bu, isteğin hatalı biçimlendirildiğini gösterir.
  • server_error: İstek işlenirken hata oluştuğunu gösterir. Bu durum, yerel hatalardan veya TS.43 sorunlarından kaynaklanabilir.

error_description alanı, sorunla ilgili ek ayrıntılar sağlar.

Dijital kimlik bilgisi yanıtını doğrulama

Aşağıda, yanıtın nasıl ayrıştırılacağı ve uygulamanızın arka ucunda doğrulama adımının nasıl gerçekleştirileceğiyle ilgili bir örnek verilmiştir:

def processDigitalCredentialsResponse(response):
  # Step 1: Parse out the TS.43 Digital Credential from the response
  openId4VpResponse = response['data']

  ts43_digital_credential = openId4VpResponse['vp_token']["aggregator1"][0]

  # Step 2: Perform response validation
  verifyResponse(ts43_digital_credential)

def verifyResponse(ts43_digital_credential):
  # The returned ts43_digital_credential is an SD-JWT-based Verifiable Credentials
  # (SD-JWT VC) as defined in this IETF spec. The section 3.4 of the specification
  # outlines how to validate the credential. At a high level, the steps involves
  # validating (1) the nonce in the response credential matches the one in the
  # request, (2) the integrity of the credential by checking the credential is
  # signed by the trusted issuer Android Telephony, and (3) other validity
  # properties associated with this credential, such as issue time and expiration
  # time

  # In most cases, you can use an SD-JWT VC library to perform these validations.

  # Some aggregators may also perform the validation logic for you. Check with your
  # aggregator to decide the exact scope of the validation required.

Telefon numarasıyla değiştirme

Uygulamanızın arka ucundan, doğrulanmış TS.43 Digital Credential değerini toplayıcının uç noktasına göndererek kimlik bilgisini doğrulayın ve doğrulanmış telefon numarasını alın.

def processDigitalCredentialsResponse(response):
  # ... prior steps

  # Step 3: Call aggregator endpoint to exchange the verified phone number
  callAggregatorPnvEndpoint(ts43_digital_credential)