Membuat kunci sandi

Sebelum pengguna dapat melakukan autentikasi dengan kunci sandi, aplikasi Anda harus terlebih dahulu mendaftarkan atau membuat kunci sandi untuk akun mereka.

Untuk membuat kunci sandi, dapatkan detail yang diperlukan untuk membuat kunci sandi dari server aplikasi Anda, lalu panggil Credential Manager API, yang akan menampilkan pasangan kunci publik dan pribadi. Kunci pribadi yang ditampilkan disimpan di penyedia kredensial, seperti Pengelola Sandi Google, sebagai kunci sandi. Kunci publik disimpan di server aplikasi Anda.

Kunci sandi disimpan di penyedia kredensial dan kunci publik disimpan di server aplikasi
Gambar 1: Pembuatan kunci sandi

Prasyarat

Pastikan Anda telah menyiapkan Digital Asset Links dan menargetkan perangkat yang menjalankan Android 9 (API level 28) atau yang lebih tinggi.

Ringkasan

Panduan ini berfokus pada perubahan yang diperlukan di aplikasi klien pihak tepercaya untuk membuat kunci sandi, dan memberikan ringkasan singkat tentang penerapan server aplikasi pihak tepercaya. Untuk mempelajari integrasi sisi server lebih lanjut, lihat Pendaftaran kunci sandi sisi server.

  1. Menambahkan dependensi ke aplikasi Anda: Tambahkan library Pengelola Kredensial yang diperlukan.
  2. Membuat instance Pengelola Kredensial: Buat instance Pengelola Kredensial.
  3. Mendapatkan opsi pembuatan kredensial dari server aplikasi: Dari server aplikasi Anda, kirim detail yang diperlukan untuk membuat kunci sandi ke aplikasi klien, seperti informasi tentang aplikasi, pengguna, serta challenge dan kolom lainnya.
  4. Meminta kunci sandi: Di aplikasi Anda, gunakan detail yang diterima dari server aplikasi untuk membuat objek GetPublicKeyCredentialOption dan gunakan objek ini untuk memanggil metode credentialManager.getCredential() guna membuat kunci sandi.
  5. Menangani respons pembuatan kunci sandi: Saat menerima kredensial di aplikasi klien, Anda harus mengenkode, membuat serialisasi, lalu mengirim kunci publik ke server aplikasi. Anda juga harus menangani setiap pengecualian yang dapat terjadi jika kunci sandi dibuat.
  6. Memverifikasi dan menyimpan kunci publik di server: Selesaikan langkah-langkah sisi server untuk memverifikasi asal kredensial, lalu simpan kunci publik.
  7. Memberi tahu pengguna: Beri tahu pengguna bahwa kunci sandi mereka telah dibuat.

Menambahkan dependensi ke aplikasi

Tambahkan dependensi berikut ke file build.gradle modul aplikasi Anda:

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

Membuat instance Pengelola Kredensial

Gunakan konteks aplikasi atau aktivitas Anda untuk membuat objek CredentialManager.

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

Mendapatkan opsi pembuatan kredensial dari server aplikasi Anda

Saat pengguna mengklik tombol "Buat Kunci Sandi" atau saat pengguna baru mendaftar, buat permintaan dari aplikasi Anda ke server aplikasi untuk mendapatkan informasi yang diperlukan untuk memulai proses pendaftaran kunci sandi.

Gunakan library yang sesuai dengan FIDO di server aplikasi Anda untuk mengirimkan informasi yang diperlukan untuk membuat kunci sandi ke aplikasi klien, seperti informasi tentang pengguna, aplikasi, dan properti konfigurasi tambahan. Untuk mempelajari lebih lanjut, lihat Pendaftaran kunci sandi sisi server.

Di aplikasi klien, dekode opsi pembuatan kunci publik yang dikirim oleh server aplikasi. Opsi ini biasanya ditampilkan dalam format JSON. Untuk mempelajari lebih lanjut cara decoding ini dilakukan untuk klien web, lihat Encoding dan Decoding. Untuk aplikasi klien Android, Anda harus menangani decoding secara terpisah.

Cuplikan berikut menunjukkan struktur opsi pembuatan kunci publik yang dikirim oleh server aplikasi:

{
  "challenge": "<base64url-encoded challenge>",
  "rp": {
    "name": "<relying party name>",
    "id": "<relying party host name>"
  },
  "user": {
    "id": "<base64url-encoded user ID>",
    "name": "<user name>",
    "displayName": "<user display name>"
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    }
  ],
  "attestation": "none",
  "excludeCredentials": [
    {
        "id": "<base64url-encoded credential ID to exclude>", 
        "type": "public-key"
    }
  ],
  "authenticatorSelection": {
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}

Kolom kunci dalam opsi pembuatan kunci publik mencakup:

  • challenge: String acak yang dibuat server dan digunakan untuk mencegah serangan replay.
  • rp: Detail tentang aplikasi.
    • rp.name: Nama aplikasi.
    • rp.id: Domain atau subdomain aplikasi.
  • user: Detail tentang pengguna.
    • id: ID unik pengguna. Nilai ini tidak boleh menyertakan informasi identitas pribadi, misalnya alamat email atau nama pengguna. Anda dapat menggunakan nilai acak 16 byte.
    • name: ID unik untuk akun yang akan dikenali pengguna, seperti alamat email atau nama pengguna. ID unik ini akan ditampilkan di pemilih akun. Jika menggunakan nama pengguna, gunakan nilai yang sama dengan autentikasi sandi.
    • displayName: Nama opsional yang mudah digunakan untuk akun yang akan ditampilkan di pemilih akun.
  • authenticatorSelection: Detail tentang perangkat yang akan digunakan untuk autentikasi.

    • authenticatorAttachment: Menunjukkan pengautentikasi pilihan . Kemungkinan nilainya adalah sebagai berikut: - platform: Nilai ini digunakan untuk pengautentikasi yang terpasang di perangkat pengguna, seperti sensor sidik jari. - cross-platform: Nilai ini digunakan untuk perangkat roaming seperti kunci keamanan. Biasanya tidak digunakan dalam konteks kunci sandi. - Tidak ditentukan (direkomendasikan): Jika nilai ini tidak ditentukan pengguna akan memiliki fleksibilitas untuk membuat kunci sandi di perangkat pilihan mereka. Dalam sebagian besar kasus, tidak menentukan parameter adalah opsi terbaik.
      • requireResidentKey: Untuk membuat kunci sandi, tetapkan nilai kolom Boolean ini ke true.
      • residentKey: Untuk membuat kunci sandi, tetapkan nilai ke required.
      • userVerification: Digunakan untuk menentukan persyaratan verifikasi pengguna selama pendaftaran kunci sandi. Kemungkinan nilainya adalah sebagai berikut: - preferred: Gunakan nilai ini jika Anda memprioritaskan pengalaman pengguna daripada perlindungan, seperti di lingkungan tempat verifikasi pengguna menyebabkan lebih banyak gesekan daripada perlindungan. - required: Gunakan nilai ini jika memanggil metode verifikasi pengguna yang tersedia di perangkat diperlukan. - discouraged: Gunakan nilai ini jika penggunaan metode verifikasi pengguna tidak dianjurkan.
        Untuk mempelajari userVerification lebih lanjut, lihat pembahasan mendalam userVerification.
  • excludeCredentials: Mencantumkan ID kredensial dalam array untuk mencegah pembuatan kunci sandi duplikat jika sudah ada yang memiliki penyedia kredensial yang sama.

Membuat kunci sandi

Setelah mengurai opsi pembuatan kunci publik sisi server, buat kunci sandi dengan menggabungkan opsi ini dalam objek CreatePublicKeyCredentialRequest dan memanggil createCredential().

createPublicKeyCredentialRequest mencakup hal berikut:

  • requestJson: Opsi pembuatan kredensial yang dikirim oleh server aplikasi.
  • preferImmediatelyAvailableCredentials: Kolom Boolean opsional yang menentukan apakah hanya menggunakan kredensial yang tersedia secara lokal atau kredensial yang disinkronkan penyedia kredensial untuk memenuhi permintaan, bukan kredensial dari kunci keamanan atau alur kunci campuran. Kemungkinan penggunaannya adalah sebagai berikut:
    • false (default): Gunakan nilai ini jika panggilan ke Pengelola Kredensial dipicu oleh tindakan pengguna yang eksplisit.
    • true: Gunakan nilai ini jika Pengelola Kredensial dipanggil secara oportunistik, seperti saat pertama kali membuka aplikasi.
      Jika Anda menetapkan nilai ke true dan tidak ada kredensial yang langsung tersedia, Pengelola Kredensial tidak akan menampilkan UI apa pun dan permintaan akan segera gagal, sehingga menampilkan NoCredentialException untuk permintaan get dan CreateCredentialNoCreateOptionException untuk permintaan create.
  • origin: Kolom ini ditetapkan secara otomatis untuk aplikasi Android. Untuk browser dan aplikasi dengan hak istimewa serupa yang perlu menetapkan origin, lihat Melakukan panggilan Pengelola Kredensial atas nama pihak lain untuk aplikasi dengan hak istimewa.
  • isConditional: Kolom opsional yang secara default ditetapkan ke false. Untuk mengetahui informasi selengkapnya, lihat Membuat kunci sandi secara otomatis.

Memanggil fungsi createCredential() akan meluncurkan UI sheet bawah bawaan Pengelola Kredensial yang meminta pengguna untuk menggunakan kunci sandi dan memilih penyedia kredensial serta akun untuk penyimpanan. Namun, jika isConditional ditetapkan ke true, UI sheet bawah tidak akan ditampilkan, dan kunci sandi akan dibuat secara otomatis.

Membuat kunci sandi secara otomatis

Anda dapat membuat kunci sandi secara otomatis untuk pengguna setelah login sandi berhasil dengan menetapkan parameter isConditional ke true di CreatePublicKeyCredentialRequest saat membuat kunci sandi. Jika pengguna belum memiliki kunci sandi, aplikasi Anda akan otomatis mencoba membuatnya di latar belakang dan menyimpannya di penyedia kredensial pengguna, seperti Pengelola Sandi Google. Untuk contoh cara penerapannya, lihat contoh publik.

Contoh notifikasi yang ditampilkan Pengelola Sandi Google setelah pembuatan kunci sandi
Gambar 2: Notifikasi Pengelola Sandi Google

Menangani respons

Setelah pengguna diverifikasi menggunakan kunci layar perangkat, kunci sandi akan dibuat dan disimpan di penyedia kredensial yang dipilih pengguna.

Respons setelah Anda berhasil memanggil createCredential() adalah objek PublicKeyCredential.

PublicKeyCredential terlihat sebagai berikut:

{
  "id": "<identifier>",
  "type": "public-key",
  "rawId": "<identifier>",
  "response": {
    "clientDataJSON": "<ArrayBuffer encoded object with the origin and signed challenge>",
    "attestationObject": "<ArrayBuffer encoded object with the public key and other information.>"
  },
  "authenticatorAttachment": "platform"
}

Di aplikasi klien, buat serialisasi objek dan kirimkan ke server aplikasi.

Tambahkan kode untuk menangani kegagalan seperti yang ditunjukkan dalam cuplikan berikut:

fun handleFailure(e: CreateCredentialException) {
    when (e) {
        is CreatePublicKeyCredentialDomException -> {
            // Handle the passkey DOM errors thrown according to the
            // WebAuthn spec.
        }
        is CreateCredentialCancellationException -> {
            // The user intentionally canceled the operation and chose not
            // to register the credential.
        }
        is CreateCredentialInterruptedException -> {
            // Retry-able error. Consider retrying the call.
        }
        is CreateCredentialProviderConfigurationException -> {
            // Your app is missing the provider configuration dependency.
            // Most likely, you're missing the
            // "credentials-play-services-auth" module.
        }
        is CreateCredentialCustomException -> {
            // You have encountered an error from a 3rd-party SDK. If you
            // make 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.name}")
    }
}

Memverifikasi dan menyimpan kunci publik di server aplikasi

Di server aplikasi, Anda harus memverifikasi kredensial kunci publik, lalu menyimpan kunci publik.

Untuk memverifikasi asal kredensial kunci publik, bandingkan dengan daftar aplikasi yang disetujui. Jika kunci memiliki asal yang tidak dikenal, tolak kunci tersebut.

Untuk mendapatkan sidik jari SHA 256 aplikasi:

  1. Cetak sertifikat penandatanganan aplikasi rilis Anda dengan menjalankan perintah berikut di terminal:

    keytool -list -keystore <path-to-apk-signing-keystore>
    

    Dalam respons, identifikasi sidik jari SHA 256 sertifikat penandatanganan, yang disebutkan sebagai Certificate fingerprints block : SHA256.

  2. Enkode sidik jari SHA256 dengan encoding base64url. Contoh Python ini menunjukkan cara mengenkode sidik jari dengan benar:

    import binascii
    import base64
    fingerprint = '<SHA256 finerprint>' # your app's SHA256 fingerprint
    print(base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))
    
  3. Tambahkan android:apk-key-hash: ke awal output dari langkah sebelumnya sehingga Anda mendapatkan sesuatu yang mirip dengan berikut ini:

    android:apk-key-hash:<encoded SHA 256 fingerprint>
    

    Hasilnya harus cocok dengan asal yang diizinkan di server aplikasi Anda. Jika Anda memiliki beberapa sertifikat penandatanganan, seperti sertifikat untuk proses debug dan rilis, atau beberapa aplikasi, ulangi proses dan setujui semua asal tersebut sebagai valid di server aplikasi.

Memberi tahu pengguna

Setelah kunci sandi berhasil dibuat, beri tahu pengguna tentang kunci sandi tersebut dan informasikan bahwa mereka dapat mengelola kunci sandi dari aplikasi penyedia kredensial atau dari dalam setelan aplikasi. Beri tahu pengguna menggunakan dialog kustom, notifikasi, atau snackbar. Karena pembuatan kunci sandi yang tidak terduga oleh entitas berbahaya memerlukan peringatan keamanan segera, pertimbangkan untuk melengkapi metode dalam aplikasi ini dengan komunikasi eksternal, seperti email.

Meningkatkan pengalaman pengguna

Untuk meningkatkan pengalaman pengguna saat menerapkan pendaftaran dengan Pengelola Kredensial, pertimbangkan untuk menambahkan fungsi untuk memulihkan kredensial dan menyembunyikan dialog isi otomatis.

Menambahkan fungsi untuk memulihkan kredensial di perangkat baru

Untuk memungkinkan pengguna login ke akun mereka di perangkat baru dengan lancar, terapkan fungsi Pulihkan Kredensial. Menambahkan kredensial pemulihan dengan BackupAgent akan membuat pengguna login saat mereka membuka aplikasi yang dipulihkan di perangkat baru, sehingga mereka dapat langsung menggunakan aplikasi Anda.

Menyembunyikan isi otomatis di kolom kredensial (opsional)

Untuk layar aplikasi tempat pengguna diharapkan menggunakan UI sheet bawah Pengelola Kredensial untuk autentikasi, tambahkan atribut isCredential ke kolom nama pengguna dan sandi. Tindakan ini akan menyembunyikan dialog isi otomatis (FillDialog dan SaveDialog) agar tidak tumpang tindih dengan UI sheet bawah Pengelola Kredensial.

Atribut isCredential didukung di Android 14 dan yang lebih tinggi.

Contoh berikut menunjukkan cara menambahkan atribut isCredential ke kolom nama pengguna dan sandi yang relevan dalam tampilan yang relevan untuk aplikasi Anda:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:isCredential="true" />

Langkah berikutnya