Telefonnummern mit digitalen Anmeldedaten bestätigen

In diesem Leitfaden wird beschrieben, wie Sie die DigitalCredential API verwenden, um bestätigte Telefonnummern für Ihre Nutzer zu erhalten. Der Prozess umfasst zwei Schritte:

  1. TS.43 token anfordern: Ihre Client-App (der „Prüfer“) fordert ein temporäres TS.43-Token vom Gerät des Nutzers an. TS.43 token ist eine vom Mobilfunkanbieter ausgestellte Anmeldedaten, die die Identität des Nutzers repräsentieren.
  2. Token gegen eine Telefonnummer eintauschen: Das Backend Ihrer App tauscht das TS.43 token mit einem Aggregator oder Mobilfunkanbieter gegen die bestätigte Telefonnummer des Nutzers ein.

Voraussetzungen

Wenn Sie die Telefonnummernbestätigung mit der DigitalCredential API implementieren möchten, benötigen Sie ein Konto bei einem Aggregator. Ein Aggregator interagiert mit Mobilfunkanbietern und stellt die erforderliche API-Oberfläche für Ihre App bereit, in der Regel als abrechenbarer Cloud-API-Endpunkt.

Außerdem müssen Sie Ihrem Gradle-Build-Skript die folgenden Abhängigkeiten hinzufügen:

Kotlin

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

Cool

dependencies {
    implementation "androidx.credentials:credentials:1.6.0-alpha05"
    implementation "androidx.credentials:credentials-play-services-auth:1.6.0-alpha05"
}

Implementierung

Der End-to-End-Prozess umfasst in der Regel die folgenden Schritte:

  1. DCQL-Parameter (Digital Credential Query Language) von einem Aggregator anfordern: Rufen Sie einen oder mehrere Aggregatoren auf und fordern Sie eine Reihe von DCQL-Parametern an. Mit DCQL können Sie genau angeben, welche digitalen Anmeldedaten Sie von den einzelnen Aggregatoren benötigen.
  2. OpenID4VP-Anfrage erstellen: Erstellen Sie im Backend Ihrer App die OpenID4VP-Anfrage und fügen Sie die DCQL-Parameter des Aggregators ein. Senden Sie dann die OpenID4VP-Anfrage an Ihre Client-App.

  3. Credential Manager API aufrufen: Verwenden Sie in Ihrer Client-App die Credential Manager API, um die OpenID4VP-Anfrage an das Betriebssystem zu senden. Als Antwort erhalten Sie ein OpenID4VP-Antwortobjekt, das die TS.43 Digital Credential enthält. Diese Anmeldedaten sind verschlüsselt und können nur vom zugehörigen Aggregator entschlüsselt werden. Nachdem Sie das Transportunternehmen-Token erhalten haben, senden Sie die Antwort von Ihrer Client-App an das Backend der App.

  4. Antwort validieren: Validieren Sie im Backend Ihrer App die OpenID4VP-Antwort.

  5. Telefonnummer austauschen: Senden Sie die TS.43 Digital Credential über das Backend Ihrer App an den Aggregator. Der Aggregator validiert die Anmeldedaten und gibt die bestätigte Telefonnummer zurück.

Bild mit dem Ablauf einer Anfrage zur Bestätigung der Telefonnummer
Abbildung 1.Der Lebenszyklus einer Anfrage zur Bestätigung der Telefonnummer, beginnend mit dem Verifier-Backend, das Parameter von einem Aggregator anfordert, und endend mit einer zurückgegebenen bestätigten Telefonnummer.

DCQL-Parameter von einem Aggregator anfordern

Senden Sie vom Backend Ihrer App eine Anfrage an den Aggregator für ein DCQL-Anmeldedatenobjekt (Digital Credential Query Language). Geben Sie in Ihrer Anfrage eine Nonce und eine Anfrage-ID an. Der Aggregator gibt das DCQL-Anmeldedatenobjekt zurück, das eine Struktur ähnlich der folgenden hat:

{
  // 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-Anfrage erstellen

Erstellen Sie zuerst im Backend Ihrer App ein dcql_query-Objekt, indem Sie das DCQL-Anmeldedatenobjekt in ein credentials-Array einfügen, das in einem dcql_query-Objekt verschachtelt ist, wie im folgenden Beispiel gezeigt:

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

Erstellen Sie dann eine OpenID4VP-Anfrage mit der folgenden Struktur:

{
  "protocol": "openid4vp-v1-unsigned",
  "data": {
    "response_type": "vp_token",
    "response_mode": "dc_api",
    "nonce": "...",
    "dcql_query": { ... }
  }
}
  • protocol: Muss für Anfragen zur Bestätigung der Telefonnummer auf openid4vp-v1-unsigned gesetzt werden.
  • response_type und response_mode: Konstanten, die das Format der Anfrage mit den festen Werten vp_token bzw. dc_api angeben.
  • nonce: Ein eindeutiger Wert, der von Ihrem Backend für jede Anfrage generiert wird. Die Nonce im DCQL-Anmeldedatenobjekt des Aggregators muss mit dieser Nonce übereinstimmen.
  • dcql_query: In diesem Fall geben Sie mit dcql_query an, dass ein TS.43 Digital Credential angefordert wird. Sie können hier auch andere digitale Anmeldedaten anfordern.

Umschließen Sie dann die OpenID4VP-Anfrage mit einem DigitalCredential API-Anfrageobjekt und senden Sie sie an die Client-App.

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

Das folgende Snippet zeigt, wie die DigitalCredential API-Anfrage generiert wird:

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 aufrufen

Rufen Sie in Ihrer Client-App die Credential Manager API mit der vom Backend Ihrer App bereitgestellten DigitalCredential API-Anfrage auf.

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

Die DigitalCredential API-Antwort enthält die OpenID4VP-Antwort. Ein typisches JSON-Anmeldedatenobjekt aus dem Ergebnis von DigitalCredential sieht so aus:

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

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

Senden Sie die DigitalCredential API-Antwort von Ihrer Client-App zurück an den Backend-Server, wo sie validiert und gegen die bestätigte Telefonnummer bei einem Aggregator eingetauscht werden kann.

Antwort auf digitale Anmeldedaten validieren

Das folgende Beispiel zeigt, wie Sie die Antwort parsen und den Validierungsschritt im Backend Ihrer App ausführen:

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

  ts43_digital_credential = response['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.

Telefonnummer tauschen

Senden Sie das validierte TS.43 Digital Credential über das Backend Ihrer App an den Endpunkt des Aggregators, um die Anmeldedaten zu validieren und die bestätigte Telefonnummer zu erhalten.

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

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