디지털 ID는 인앱 및 웹 흐름 모두에서 허용됩니다. Google 월렛의 사용자 인증 정보를 수락하려면 다음 단계를 따르세요.
- 제공된 안내에 따라 앱 또는 웹을 사용하여 통합합니다.
- 테스트 ID를 사용하여 Google 월렛 샌드박스를 통해 흐름을 테스트합니다.
- 라이브로 전환하려면 이 양식을 작성하여 액세스를 요청하고 Google 월렛 사용자 인증 정보 서비스 약관에 동의하세요. 각 비즈니스 법인에 대해 이 정보를 입력해야 합니다. 양식을 작성해 주시면 Google팀에서 연락을 드리겠습니다.
- 궁금한 점이 있으면
wallet-identity-rp-support@google.com
에 문의하세요.
지원되는 사용자 인증 정보 형식
디지털 신원 문서의 데이터 형식을 정의하는 여러 제안된 표준이 있으며, 그중 두 가지가 업계에서 상당한 관심을 받고 있습니다.
- mdocs - ISO에 의해 정의됩니다.
- w3c Verifiable Credentials - w3c에서 정의합니다.
Android 인증 관리자는 두 형식을 모두 지원하지만 Google 월렛은 현재 mdoc 기반 디지털 ID만 지원합니다.
지원되는 사용자 인증 정보
Google 월렛은 다음 두 가지 사용자 인증 정보 유형을 지원합니다.
- 모바일 운전면허증 (mDL)
- 신분증 패스
단일 매개변수 변경으로 흐름에서 두 사용자 인증 정보 중 하나를 요청할 수 있습니다.
사용자 환경
이 섹션에서는 권장되는 온라인 프레젠테이션 흐름을 설명합니다. 이 흐름은 주류 배송을 위해 앱에 연령을 표시하는 것을 보여주지만 UX는 웹 및 기타 유형의 표시에서도 유사합니다.
![]() |
![]() |
![]() |
![]() |
![]() |
사용자에게 앱 또는 웹사이트에서 연령을 확인하라는 메시지가 표시됨 | 사용자에게 사용 가능한 인증 정보가 표시됨 | Google 월렛에 확인 페이지가 표시됨 | 사용자가 인증하여 공유 확인 | 앱 또는 웹사이트로 전송된 데이터 |
주요 참고사항
- 앱이나 웹사이트는 API 진입점을 만드는 방식에 유연성이 있습니다. 1단계에 표시된 것처럼 시간이 지남에 따라 Google 월렛 이외의 옵션이 API를 통해 제공될 것으로 예상되므로 '디지털 신분증으로 인증'과 같은 일반 버튼을 표시하는 것이 좋습니다.
- 2단계의 선택기 화면은 Android에서 렌더링합니다. 적격 사용자 인증 정보는 각 월렛에서 제공하는 등록 로직과 신뢰 당사자가 전송하는 요청 간의 일치에 따라 결정됩니다.
- 3단계는 Google 월렛에서 렌더링됩니다. Google 월렛에는 개발자가 이 화면에 제공하는 이름, 로고, 개인정보처리방침이 표시됩니다.
디지털 ID 흐름 추가
사용자에게 사용자 인증 정보가 없는 경우 사용자가 디지털 신분증을 추가할 수 있도록 Google 월렛으로 딥 링크되는 링크를 '디지털 신분증으로 인증' 버튼 옆에 제공하는 것이 좋습니다.
![]() |
![]() |
사용자에게 앱 또는 웹사이트에서 연령을 확인하라는 메시지가 표시됨 | 디지털 신분증을 받기 위해 Google 월렛으로 이동한 사용자 |
사용 가능한 디지털 ID 없음
사용자가 디지털 ID가 없는 상태에서 '디지털 ID로 인증' 옵션을 선택하면 이 오류 메시지가 표시됩니다.
![]() |
![]() |
사용자에게 앱 또는 웹사이트에서 연령을 확인하라는 메시지가 표시됨 | 사용자에게 디지털 ID가 없는 경우 오류가 표시됨 |
API는 사용자의 개인 정보를 보호하기 위해 사용자가 사용할 수 있는 디지털 ID가 있는지 여부를 자동으로 학습하는 기능을 지원하지 않습니다. 따라서 표시된 대로 온보딩 링크 옵션을 포함하는 것이 좋습니다.
지갑에서 ID 사용자 인증 정보를 요청하는 요청 형식
다음은 Android 기기 또는 웹의 지갑에서 ID 사용자 인증 정보를 가져오는 mdoc requestJson
요청의 샘플입니다.
{
"requests" : [
{
"protocol": "openid4vp",
"data": {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
암호화 요청
client_metadata
에는 각 요청의 암호화 공개 키가 포함됩니다. 각 요청의 비공개 키를 저장하고 이를 사용하여 지갑 앱에서 수신한 토큰을 인증하고 승인해야 합니다.
requestJson
의 credential_request
매개변수는 다음 필드로 구성됩니다.
{
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "1234",
"dcql_query": {
"credentials": [
{
"id": "cred1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL" // this is for mDL. Use com.google.wallet.idcard.1 for ID pass
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
}
]
},
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
"kty": "EC",
"crv": "P-256",
"x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
"y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
"use": "enc",
"kid" : "1",
"alg" : "ECDH-ES",
}
]
},
"authorization_encrypted_response_alg": "ECDH-ES",
"authorization_encrypted_response_enc": "A128GCM"
}
}
Google 월렛에 저장된 모든 ID 인증 정보에서 원하는 수의 지원되는 속성을 요청할 수 있습니다.
인앱
Android 앱에서 ID 사용자 인증 정보를 요청하려면 다음 단계를 따르세요.
종속 항목 업데이트
프로젝트의 build.gradle에서 인증 관리자 (베타)를 사용하도록 종속 항목을 업데이트합니다.
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
// optional - needed for credentials support from play services, for devices running Android 13 and below.
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
인증 관리자 구성
CredentialManager
객체를 구성하고 초기화하려면 다음과 유사한 로직을 추가하세요.
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
ID 속성 요청
ID 요청에 개별 매개변수를 지정하는 대신 앱은 CredentialOption 내에서 모든 매개변수를 JSON 문자열로 함께 제공합니다. 사용자 인증 정보 관리자는 콘텐츠를 검사하지 않고 이 JSON 문자열을 사용 가능한 디지털 지갑에 전달합니다. 그러면 각 지갑은 다음을 담당합니다. - JSON 문자열을 파싱하여 ID 요청을 이해합니다. - 저장된 사용자 인증 정보 중 요청을 충족하는 사용자 인증 정보가 있는지 확인합니다.
파트너는 Android 앱 통합의 경우에도 서버에서 요청을 생성하는 것이 좋습니다.
GetDigitalCredentialOption()
함수 호출에서 request
로 구성된 요청 형식의 requestJson
를 사용합니다.
// The request in the JSON format to conform with
// the JSON-ified Digital Credentials 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)
)
coroutineScope.launch {
try {
val result = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
verifyResult(result)
} catch (e : GetCredentialException) {
handleFailure(e)
}
}
대답 확인 및 검증
지갑에서 응답을 받으면 응답이 성공적이고 credentialJson
응답이 포함되어 있는지 확인합니다.
// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
val credential = result.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson) // make a server call to validate the response
}
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}")
}
}
credentialJson
응답에는 W3C에서 정의한 암호화된 identityToken (JWT)이 포함됩니다. 이 응답을 작성하는 것은 Wallet 앱의 책임입니다.
예:
{
"protocol" : "openid4vp",
"data" : {
<encrpted_response>
}
}
이 응답을 서버로 다시 전달하여 진위 여부를 확인합니다. 사용자 인증 정보 응답을 검증하는 단계를 확인할 수 있습니다.
웹
Chrome에서 디지털 사용자 인증 정보 API를 사용하여 ID 사용자 인증 정보를 요청하려면 디지털 사용자 인증 정보 API 오리진 트라이얼에 가입해야 합니다.
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
이 API의 응답을 서버로 다시 보내 사용자 인증 정보 응답을 검증합니다.
인증 정보 응답 유효성 검사 단계
앱 또는 웹사이트에서 암호화된 identityToken을 수신하면 응답을 신뢰하기 전에 여러 유효성 검사를 실행해야 합니다.
비공개 키를 사용하여 응답 복호화
첫 번째 단계는 저장된 비공개 키를 사용하여 토큰을 복호화하고 응답 JSON을 가져오는 것입니다.
Python 예:
from jwcrypto import jwe, jwk # Retrieve the Private Key from Datastore reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str) # Decrypt the JWE encrypted response from Google Wallet jwe_object = jwe.JWE() jwe_object.deserialize(encrypted_jwe_response_from_wallet) jwe_object.decrypt(reader_private_jwk) decrypted_payload_bytes = jwe_object.payload decrypted_data = json.loads(decrypted_payload_bytes)
decrypted_data
은 사용자 인증 정보를 포함하는vp_token
JSON을 생성합니다.{ "vp_token": { "cred1": "<credential_token>" } }
세션 스크립트 만들기
다음 단계는 Android 또는 웹 전용 핸드오버 구조를 사용하여 ISO/IEC 18013-5:2021에서 SessionTranscript를 만드는 것입니다.
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]
Android / 웹 핸드오버의 경우
credential_request
를 생성하는 데 사용한 것과 동일한 nonce를 사용해야 합니다.Android 핸드오버
AndroidHandoverData = [ origin, // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>", clientId, // "android-origin:<app_package_name>", nonce, // nonce that was used to generate credential request ] AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
브라우저 핸드오버
BrowserHandoverData =[ origin, // Origin URL clientId, // "web-origin:<origin>" nonce, // nonce that was used to generate credential request ] BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
SessionTranscript
를 사용하여 DeviceResponse는 ISO/IEC 18013-5:2021 조항 9에 따라 검증되어야 합니다. 여기에는 다음과 같은 여러 단계가 포함됩니다.주 발급자 인증서를 확인합니다. 지원되는 발급자의 IACA 인증서 확인
MSO 서명 확인 (18013-5 섹션 9.1.2)
데이터 요소의 ValueDigests 계산 및 확인 (18013-5 섹션 9.1.2)
deviceSignature
서명 확인 (18013-5 섹션 9.1.3)
{
"version": "1.0",
"documents": [
{
"docType": "org.iso.18013.5.1.mDL",
"issuerSigned": {
"nameSpaces": {...}, // contains data elements
"issuerAuth": [...] // COSE_Sign1 w/ issuer PK, mso + sig
},
"deviceSigned": {
"nameSpaces": 24(<< {} >>), // empty
"deviceAuth": {
"deviceSignature": [...] // COSE_Sign1 w/ device signature
}
}
}
],
"status": 0
}
솔루션 테스트
솔루션을 테스트하려면 오픈소스 참조 보유자 Android 애플리케이션을 빌드하고 실행하세요. 참조 보유자 앱을 빌드하고 실행하는 단계는 다음과 같습니다.
- 참조 앱 저장소를 클론합니다.
- Android 스튜디오에서 프로젝트를 엽니다.
- Android 기기 또는 에뮬레이터에서
appholder
타겟을 빌드하고 실행합니다.
영지식 증명 (ZKP) 기반 확인
영지식 증명(ZKP)은 개인이 실제 기본 데이터를 공개하지 않고도 특정 신원 정보를 보유하거나 특정 기준(예: 18세 이상, 유효한 사용자 인증 정보 보유)을 충족함을 검증자에게 증명할 수 있는 암호화 방법입니다. 기본적으로 민감한 세부정보를 비공개로 유지하면서 본인에 관한 진술의 진실성을 확인하는 방법입니다.
신원 데이터의 직접 공유에 의존하는 디지털 신원 시스템은 사용자가 과도한 개인 정보를 공유하도록 요구하는 경우가 많아 데이터 유출 및 신원 도용의 위험이 증가합니다. ZKP는 최소한의 공개로 검증을 지원하는 패러다임 전환을 제공합니다.
디지털 ID의 ZKP 주요 개념:
- 증명자: 신원의 일부를 증명하려는 개인입니다.
- 인증 기관: 신원 속성의 증빙을 요청하는 기관입니다.
- 증명: 증명자가 비밀 정보를 공개하지 않고 검증자에게 주장의 진실성을 확신시킬 수 있는 암호화 프로토콜입니다.
영지식 증명의 핵심 속성:
- 완전성: 명제가 참이고 증명자와 검증자가 모두 정직하면 검증자가 확신하게 됩니다.
- 건전성: 명제가 거짓인 경우 부정직한 증명자는 정직한 검증자에게 명제가 참이라고 확신시킬 수 없습니다 (매우 높은 확률로).
- 영지식: 검증자는 문장이 참이라는 사실 외에는 아무것도 알 수 없습니다. 증명자의 신원에 관한 실제 데이터는 노출되지 않습니다.
Google 월렛에서 제로 지식 증명을 다시 받으려면 요청 형식을 mso_mdoc_zk
로 변경하고 요청에 zk_system_type
를 추가해야 합니다.
...
"dcql_query": {
"credentials": [{
"id": "cred1",
"format": "mso_mdoc_zk",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
"zk_system_type": [
{
"system": "longfellow-libzk-v1",
"circuit_hash": "bd3168ea0a9096b4f7b9b61d1c210dac1b7126a9ec40b8bc770d4d485efce4e9", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 3
},
{
"system": "longfellow-libzk-v1",
"circuit_hash": "89288b9aa69d2120d211618fcca8345deb4f85d2e710c220cc9c059bbee4c91f", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 4
}
],
"verifier_message": "challenge"
},
"claims": [{
...
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
...
월렛에서 암호화된 영지식 증명을 다시 받게 됩니다. Google의 longfellow-zk 라이브러리를 사용하여 발급자 IACA 인증서에 대해 이 증명을 검증할 수 있습니다.
자세한 내용은 지원 이메일로 문의하세요.
wallet-identity-rp-support@google.com