Melakukan Autentikasi Menggunakan OpenID Connect di platform Apple

Jika telah mengupgrade ke Firebase Authentication dengan Identity Platform, Anda dapat mengautentikasi pengguna dengan Firebase menggunakan penyedia yang mendukung OpenID Connect (OIDC) pilihan Anda. Hal ini memungkinkan Anda menggunakan penyedia identitas yang tidak didukung secara native oleh Firebase.

Sebelum memulai

Untuk memproses login pengguna menggunakan penyedia OIDC, Anda harus terlebih dahulu mengumpulkan sejumlah informasi dari penyedia:

  • Client ID: String yang unik untuk penyedia yang mengidentifikasi aplikasi Anda. Penyedia dapat menetapkan client ID yang berbeda untuk setiap platform yang Anda dukung. Ini adalah salah satu nilai dari klaim aud dalam token ID yang dikeluarkan oleh penyedia.

  • Rahasia klien: String rahasia yang digunakan penyedia untuk mengonfirmasi kepemilikan client ID. Untuk setiap client ID, Anda memerlukan rahasia klien yang cocok. (Nilai ini hanya diperlukan jika Anda menggunakan alur kode otorisasi, yang sangat direkomendasikan.)

  • Penerbit: String yang mengidentifikasi penyedia Anda. Nilai ini harus berupa URL yang, jika ditambahkan dengan /.well-known/openid-configuration, merupakan lokasi dokumen penemuan OIDC penyedia. Misalnya, jika penerbitnya adalah https://auth.example.com, dokumen penemuan harus tersedia di https://auth.example.com/.well-known/openid-configuration.

Setelah memiliki informasi di atas, aktifkan OpenID Connect sebagai penyedia login untuk project Firebase Anda:

  1. Tambahkan Firebase ke project iOS.

  2. Jika Anda belum mengupgrade ke Firebase Authentication dengan Identity Platform, lakukan hal tersebut terlebih dahulu. Autentikasi OpenID Connect hanya tersedia di project yang telah diupgrade.

  3. Pada halaman Sign-in providers di Firebase console, klik Add new provider, lalu klik OpenID Connect.

  4. Pilih apakah Anda akan menggunakan alur kode otorisasi atau alur pemberian implisit.

    Anda harus selalu menggunakan alur kode jika penyedia mendukungnya. Alur implisit kurang aman dan sangat tidak dianjurkan.

  5. Beri nama untuk penyedia ini. Catat ID penyedia yang dibuat: seperti oidc.example-provider. Anda akan memerlukan ID ini saat menambahkan kode login ke aplikasi.

  6. Tentukan client ID dan rahasia klien, serta string penerbit penyedia Anda. Nilai ini harus sama persis dengan nilai yang ditetapkan penyedia untuk Anda.

  7. Simpan perubahan Anda.

Menangani alur login dengan Firebase SDK

Cara termudah untuk mengautentikasi pengguna dengan Firebase menggunakan penyedia OIDC Anda adalah dengan menangani seluruh alur login dengan Firebase SDK.

Untuk menangani alur login dengan Firebase SDK untuk platform Apple, ikuti langkah-langkah berikut:

  1. Tambahkan skema URL kustom ke project Xcode Anda:

    1. Buka konfigurasi project: klik dua kali pada nama project dalam tampilan hierarki di sebelah kiri. Pilih aplikasi dari bagian TARGETS, lalu pilih tab Info, dan perluas bagian URL Types.
    2. Klik tombol +, lalu tambahkan ID Aplikasi yang Di-enkode sebagai skema URL. Anda dapat menemukan ID Aplikasi yang Di-enkode pada halaman General Settings di Firebase console, di bagian aplikasi iOS. Biarkan kolom lainnya kosong.

      Jika sudah selesai, konfigurasi akan terlihat seperti berikut (tapi dengan nilai khusus aplikasi Anda):

      Screenshot antarmuka penyiapan skema URL kustom Xcode
  2. Buat instance OAuthProvider menggunakan ID penyedia yang Anda dapatkan di Firebase console.

    Swift

    var provider = OAuthProvider(providerID: "oidc.example-provider")
    

    Objective-C

    FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"oidc.example-provider"];
    
  3. Opsional: Tentukan parameter OAuth kustom tambahan yang ingin dikirim dengan permintaan OAuth.

    Swift

    provider.customParameters = [
      "login_hint": "user@example.com"
    ]
    

    Objective-C

    [provider setCustomParameters:@{@"login_hint": @"user@example.com"}];
    

    Tanyakan kepada penyedia Anda untuk mengetahui parameter yang didukungnya. Perlu diperhatikan bahwa Anda tidak dapat meneruskan parameter yang diperlukan Firebase dengan setCustomParameters. Beberapa parameter tersebut antara lain adalah client_id, response_type, redirect_uri, state, scope, dan response_mode.

  4. Opsional: Tentukan cakupan OAuth 2.0 tambahan di luar profil dasar yang ingin diminta dari penyedia autentikasi.

    Swift

    provider.scopes = ["mail.read", "calendars.read"]
    

    Objective-C

    [provider setScopes:@[@"mail.read", @"calendars.read"]];
    

    Tanyakan kepada penyedia Anda untuk mengetahui cakupan yang didukungnya.

  5. Opsional: Jika Anda ingin menyesuaikan cara aplikasi menyajikan SFSafariViewController atau UIWebView saat menampilkan reCAPTCHA kepada pengguna, buat class kustom yang sesuai dengan protokol AuthUIDelegate.

  6. Lakukan autentikasi dengan Firebase menggunakan objek penyedia OAuth.

    Swift

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    provider.getCredentialWith(nil) { credential, error in
      if error != nil {
        // Handle error.
      }
      if credential != nil {
        Auth().signIn(with: credential) { authResult, error in
          if error != nil {
            // Handle error.
          }
          // User is signed in.
          // IdP data available in authResult.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.accessToken
          // OAuth ID token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.idToken
        }
      }
    }
    

    Objective-C

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    [provider getCredentialWithUIDelegate:nil
                                completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) {
      if (error) {
        // Handle error.
      }
      if (credential) {
        [[FIRAuth auth] signInWithCredential:credential
                                  completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
          if (error) {
            // Handle error.
          }
          // User is signed in.
          // IdP data available in authResult.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).accessToken
          // OAuth ID token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).idToken
        }];
      }
    }];
    
  7. Meskipun contoh di atas berfokus pada alur login, Anda juga dapat menautkan penyedia OIDC kepada pengguna yang ada menggunakan linkWithCredential. Misalnya, Anda dapat menautkan beberapa penyedia kepada pengguna yang sama agar bisa login dengan salah satu penyedia tersebut.

    Swift

    Auth().currentUser.link(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    Objective-C

    [[FIRAuth auth].currentUser
        linkWithCredential:credential
                completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    
  8. Pola yang sama dapat digunakan dengan reauthenticateWithCredential, yang dapat digunakan untuk mengambil kredensial baru untuk operasi sensitif yang memerlukan login terbaru.

    Swift

    Auth().currentUser.reauthenticateWithCredential(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // User is re-authenticated with fresh tokens minted and
      // should be able to perform sensitive operations like account
      // deletion and email or password update.
      // IdP data available in result.additionalUserInfo.profile.
      // Additional OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    Objective-C

    [[FIRAuth auth].currentUser
        reauthenticateWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // User is re-authenticated with fresh tokens minted and
      // should be able to perform sensitive operations like account
      // deletion and email or password update.
      // IdP data available in result.additionalUserInfo.profile.
      // Additional OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    

Menangani alur login secara manual

Jika sudah menerapkan alur login OpenID Connect di aplikasi, Anda dapat langsung menggunakan token ID untuk melakukan autentikasi dengan Firebase:

Swift

let credential = OAuthProvider.credential(
    withProviderID: "oidc.example-provider",  // As registered in Firebase console.
    idToken: idToken,  // ID token from OpenID Connect flow.
    rawNonce: nil
)
Auth.auth().signIn(with: credential) { authResult, error in
    if error {
        // Handle error.
        return
    }
    // User is signed in.
    // IdP data available in authResult?.additionalUserInfo?.profile
}

Objective-C

FIROAuthCredential *credential =
    [FIROAuthProvider credentialWithProviderID:@"oidc.example-provider"  // As registered in Firebase console.
                                       IDToken:idToken  // ID token from OpenID Connect flow.
                                      rawNonce:nil];
[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                      NSError * _Nullable error) {
    if (error != nil) {
        // Handle error.
        return;
    }
    // User is signed in.
    // IdP data available in authResult.additionalUserInfo.profile
}];

Langkah berikutnya

Setelah pengguna login untuk pertama kalinya, akun pengguna baru akan dibuat dan ditautkan ke kredensial, yaitu nama pengguna dan sandi, nomor telepon, atau informasi penyedia autentikasi, yang digunakan pengguna tersebut untuk login. Akun baru ini disimpan sebagai bagian dari project Firebase Anda, dan dapat digunakan untuk mengidentifikasi pengguna di setiap aplikasi dalam project, terlepas dari cara pengguna login.

  • Di aplikasi, Anda bisa mendapatkan informasi profil dasar pengguna dari objek User. Baca bagian Mengelola Pengguna.

  • Di Aturan Keamanan Firebase Realtime Database dan Cloud Storage, Anda bisa mendapatkan ID pengguna unik milik pengguna yang login dari variabel auth, dan menggunakannya untuk mengontrol data yang dapat diakses oleh pengguna.

Anda dapat mengizinkan pengguna untuk login ke aplikasi menggunakan beberapa penyedia autentikasi dengan menautkan kredensial penyedia autentikasi ke akun pengguna yang ada.

Agar pengguna logout, panggil signOut:.

Swift

let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}

Objective-C

NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

Anda juga dapat menambahkan kode penanganan error untuk berbagai error autentikasi. Lihat Menangani Error.