การยอมรับบัตรประจำตัวจาก Google Wallet

ออนไลน์

ระบบจะยอมรับบัตรประจำตัวดิจิทัลทั้งสำหรับขั้นตอนในแอปและบนเว็บ หากต้องการยอมรับข้อมูลเข้าสู่ระบบจาก Google Wallet คุณจะต้องดำเนินการดังนี้

  1. ผสานรวมโดยใช้แอปหรือเว็บโดยทําตามวิธีการที่ระบุไว้ และ
  2. กรอกแบบฟอร์มนี้เพื่อขอและยอมรับข้อกำหนดในการให้บริการของการรับข้อมูลเข้าสู่ระบบจาก Google Wallet

ข้อกำหนดเบื้องต้น

หากต้องการทดสอบการแสดงบัตรประจำตัว คุณต้องลงทะเบียนเข้าร่วมโปรแกรมเบต้าสาธารณะโดยใช้บัญชีทดสอบที่ต้องการก่อน จากนั้นให้ส่งรายละเอียดต่อให้กับผู้ติดต่อ Google ที่คุณกำหนด

  • ลิงก์ข้อกำหนดในการให้บริการ
  • โลโก้
  • เว็บไซต์
  • รหัสแพ็กเกจ Play Store (สำหรับการผสานรวมแอป Android)
  • รหัส Gmail ที่ใช้เข้าร่วมเวอร์ชันเบต้าแบบสาธารณะ

รูปแบบข้อมูลเข้าสู่ระบบที่รองรับ

มาตรฐานที่เสนอมีหลายรายการซึ่งกำหนดรูปแบบข้อมูลของเอกสารระบุตัวตนดิจิทัล โดยมี 2 รายการที่ได้รับความนิยมอย่างมากในอุตสาหกรรม ดังนี้

  1. mdocs - กำหนดโดย ISO
  2. ข้อมูลประจำตัวที่ตรวจสอบได้ของ W3C - ตามที่ W3C กำหนด

แม้ว่าเครื่องมือจัดการข้อมูลเข้าสู่ระบบของ Android จะรองรับทั้ง 2 รูปแบบ แต่ Google Wallet รองรับเฉพาะบัตรประจำตัวดิจิทัลแบบ mdoc เท่านั้นในขณะนี้

ประสบการณ์ของผู้ใช้

เมื่อแอปพลิเคชันขอแอตทริบิวต์ตัวตน ระบบจะดำเนินการตามขั้นตอนต่อไปนี้

  1. การค้นหาข้อมูลเข้าสู่ระบบ: แอปพลิเคชันจะค้นหากระเป๋าสตางค์ที่ใช้ได้เพื่อระบุข้อมูลเข้าสู่ระบบที่ตอบสนองคำขอได้ จากนั้น Android จะแสดงตัวเลือก UI ของระบบ ซึ่งจะแสดงข้อมูลที่แชร์ ซึ่งช่วยให้ผู้ใช้มีข้อมูลประกอบการตัดสินใจเกี่ยวกับข้อมูลเข้าสู่ระบบที่จะใช้

  2. การเลือกของผู้ใช้และการโต้ตอบกับ Wallet: ผู้ใช้เลือกข้อมูลเข้าสู่ระบบ แล้ว Android จะเรียกใช้แอป Wallet ที่เกี่ยวข้องเพื่อทำธุรกรรมให้เสร็จสมบูรณ์ แอป Wallet อาจแสดงหน้าจอแสดงความยินยอมของตนเองหรือกำหนดให้ต้องมีการยืนยันข้อมูลไบโอเมตริก

ผลลัพธ์: หากผู้ใช้ให้ความยินยอม ระบบจะแชร์ข้อมูลเข้าสู่ระบบเพื่อระบุตัวตนที่เลือกกับแอปพลิเคชันที่ขอ หากผู้ใช้ปฏิเสธ ระบบจะแสดงข้อผิดพลาด

ในแอป

หากต้องการขอข้อมูลเข้าสู่ระบบเพื่อระบุตัวตนจากแอป Android ให้ทำตามขั้นตอนต่อไปนี้

อัปเดตทรัพยากร Dependency

ใน build.gradle ของโปรเจ็กต์ ให้อัปเดต Dependency เพื่อใช้ Credential Manager (เบต้า) โดยทำดังนี้

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)

แอตทริบิวต์อัตลักษณ์ของคำขอ

แอปจะระบุพารามิเตอร์ทั้งหมดเป็นสตริง JSON ภายใน CredentialOption แทนที่จะระบุพารามิเตอร์แต่ละรายการสำหรับคำขอข้อมูลประจำตัว เครื่องมือจัดการข้อมูลเข้าสู่ระบบจะส่งสตริง JSON นี้ไปยังกระเป๋าเงินดิจิทัลที่ใช้ได้โดยไม่ตรวจสอบเนื้อหา จากนั้นแต่ละกระเป๋าสตางค์จะมีหน้าที่ดังนี้ - แยกวิเคราะห์สตริง JSON เพื่อให้เข้าใจคำขอระบุตัวตน - พิจารณาว่าข้อมูลเข้าสู่ระบบใดที่เก็บไว้ (หากมี) ตรงกับคำขอ

เราคาดว่า W3C จะกำหนดโครงสร้างของคำขอ JSON นี้อย่างเป็นทางการโดยเป็นส่วนหนึ่งของข้อกำหนดของ Web API อย่างไรก็ตาม โปรดทราบว่าข้อกําหนดยังอยู่ในรูปแบบฉบับร่างและอาจมีการเปลี่ยนแปลง

ในช่วงแรก เราจะใช้โปรโตคอลเวอร์ชันตัวอย่างเพื่อรับบัตรประจำตัวจาก Google Wallet ซึ่งจะช่วยให้เราเริ่มการผสานรวมและการทดสอบได้ในขณะที่ข้อมูลจำเพาะของ Web API เสร็จสมบูรณ์

ต่อไปนี้คือตัวอย่าง mdoc requestJson สำหรับโปรโตคอลเวอร์ชันตัวอย่าง

{
  identity: {
    providers: [{
      holder: {
        selector: {
          format: ['mdoc'],
          type: 'org.iso.18013.5.1.mDL',
          fields: [
            'org.iso.18013.5.1.family_name',
            'org.iso.18013.5.1.portrait',
          ]
        },
        params: {
          nonce: '1234',
          readerPublicKey: '<public_key>',
          extraParamAsNeededByWallets: true,
        },
      },
    }]
  }
}
// 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)
    }
}

// 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.
        }
        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}")
    }
}

การตอบกลับจะแสดง identityToken (สตริง JSON) ซึ่ง W3C เป็นผู้กำหนด แอป Wallet มีหน้าที่รับผิดชอบในการสร้างคำตอบนี้

ตัวอย่าง

{
    "token": "<base64 encoded response>"
}

ส่งโทเค็นและประมวลผลในเซิร์ฟเวอร์

เมื่อได้รับ identityToken แล้ว แอปพลิเคชันควรส่ง identityToken ดังกล่าวไปยังเซิร์ฟเวอร์แอปพลิเคชันเพื่อรับการยืนยัน ขั้นตอนแรกคือการถอดรหัสโทเค็นจากรูปแบบ Base64 อาร์เรย์ไบต์ที่ได้จะแสดงข้อมูล CBOR ซึ่งเป็นไปตาม CDDL ต่อไปนี้

CredentialDocument = {
  "version": tstr,       // Set to "ANDROID-HPKE-v1"
  "pkEm": bstr,          // Public key, in uncompressed form
  "cipherText": bstr     // The encrypted data
}

ขั้นตอนถัดไปคือการคำนวณ SessionTranscript จาก ISO/IEC 18013-5:2021 ด้วยโครงสร้างการส่งต่อสำหรับ Android โดยเฉพาะ ดังนี้

SessionTranscript = [
  null,                // DeviceEngagementBytes not available
  null,                // EReaderKeyBytes not available
  AndroidHandover      // Defined below
]

AndroidHandover = [
  "AndroidHandoverv1", // Version number
  nonce,               // nonce that comes from request
  appId,               // RP package name
  pkRHash,             // The SHA256 hash of the recipient public key
]

cipherText ได้รับการเข้ารหัสโดยใช้การเข้ารหัส HPKE หากต้องการถอดรหัส ให้ใช้ SessionTranscript เป็นข้อมูลเพิ่มเติมที่ตรวจสอบสิทธิ์ รวมถึงคีย์ส่วนตัว EC ที่สร้างขึ้นก่อนหน้านี้ และการตั้งค่าต่อไปนี้

  • KEM: DHKEM(P-256, HKDF-SHA256)
  • KDF: HKDF-SHA256
  • AEAD: AES-128-GCM

ข้อความที่ชัดเจนที่ได้จะเป็นไบต์ CBOR ของ DeviceResponse ตามที่ระบุไว้ใน ISO/IEC 18013-5:2021 DeviceResponse ต้องได้รับการตรวจสอบตามข้อ 9 ของมาตรฐาน ISO/IEC 18013-5:2021 ซึ่งประกอบด้วยหลายขั้นตอน เช่น การตรวจสอบว่า mdoc มาจากผู้ออกใบรับรองที่เชื่อถือได้ และการตอบกลับได้รับการลงนามโดยอุปกรณ์ที่ต้องการ คุณสามารถใช้คลาส DeviceResponseParser จากโปรเจ็กต์ข้อมูลเข้าสู่ระบบของ OpenWallet Foundation เป็นส่วนหนึ่งของกระบวนการตรวจสอบนี้

เว็บ

หากต้องการขอข้อมูลเข้าสู่ระบบเพื่อระบุตัวตนโดยใช้ Digital Credentials API ใน Chrome คุณจะต้องลงชื่อสมัครใช้ช่วงทดลองใช้จากต้นทางของ Digital Credentials API

ถ่ายทอดอารมณ์ส่วนตัว

การยอมรับบัตรประจำตัวจาก Google Wallet จะต้องดำเนินการตามขั้นตอนต่อไปนี้

  • สร้างหรือซื้อเครื่องอ่านเพื่อรับบัตรประจำตัวตามที่ระบุไว้ใน ISO 18013-5
  • โหลดใบรับรอง IACA ลงในเครื่องอ่านเพื่อให้มั่นใจว่าบัตรที่ยอมรับเป็นของจริง
  • ทดสอบโซลูชัน
  • ลงทะเบียนแอปพลิเคชันกับ Google Wallet

สร้างหรือซื้อเครื่องอ่านเพื่อรับบัตรประจำตัวตามที่ระบุไว้ใน ISO 18013-5

บัตรประจำตัวใน Wallet จะใช้ตามมาตรฐาน ISO 18013-5 สำหรับใบขับขี่บนอุปกรณ์เคลื่อนที่ โดยจะใช้การมีส่วนร่วมแบบ NFC หรือคิวอาร์โค้ดร่วมกับ BLE เป็นกลไกการโอนข้อมูล ดังนั้นอุปกรณ์ใดก็ตามที่สามารถใช้มาตรฐานด้านเหล่านั้นได้ก็จะทำหน้าที่เป็นเครื่องมืออ่านได้ แม้แต่แอปพลิเคชันบนอุปกรณ์เคลื่อนที่ เนื่องจากเป็นมาตรฐานแบบเปิด จึงมีการใช้งานของบุคคลที่สามหลายรายการในตลาด นอกจากนี้ คุณยังใช้ฟังก์ชันการทำงานดังกล่าวได้โดยตรงหากต้องการ

ดูคำแนะนำเกี่ยวกับวิธีใช้ฟังก์ชันการทำงานด้วยตนเองได้จากแอป Android สำหรับโปรแกรมอ่านข้อมูลอ้างอิงแบบโอเพนซอร์สของเรา ซึ่งใช้มาตรฐาน ISO และยอมรับ mDL จาก Google Wallet ได้

คุณเริ่มต้นได้ด้วยการสร้างและเรียกใช้แอปโปรแกรมอ่านข้อมูลอ้างอิง ดังนี้

  • โคลนที่เก็บแอปอ้างอิง
  • เปิดโปรเจ็กต์ใน Android Studio
  • บิลด์และเรียกใช้เป้าหมาย appverifier ในอุปกรณ์ Android หรือโปรแกรมจำลอง

โหลดใบรับรอง IACA ลงในเครื่องอ่านเพื่อให้มั่นใจว่าบัตรที่ยอมรับเป็นของจริง

คุณต้องระบุบัตรประจำตัวใน Wallet จากผู้ออกบัตรที่รองรับเพื่อตรวจสอบข้อมูลเข้าสู่ระบบจริง รายชื่อผู้ออกบัตรที่ Google Wallet รองรับแสดงอยู่ด้านล่างพร้อมลิงก์ไปยังใบรับรองสำหรับการยืนยัน

ทดสอบโซลูชัน

หากต้องการทดสอบโซลูชัน ให้สร้างและเรียกใช้แอปพลิเคชัน Android ที่ใช้อ้างอิงแบบโอเพนซอร์ส ขั้นตอนการสร้างและเรียกใช้แอปผู้ถือข้อมูลอ้างอิงมีดังนี้

  • โคลนที่เก็บแอปอ้างอิง
  • เปิดโปรเจ็กต์ใน Android Studio
  • บิลด์และเรียกใช้เป้าหมาย appholder ในอุปกรณ์ Android หรือโปรแกรมจำลอง

(ไม่บังคับ) ลงทะเบียนแอปพลิเคชันกับ Google Wallet

ลงทะเบียนแอปพลิเคชันกับ Google Wallet โดยกรอกแบบฟอร์มนี้