Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Otentikasi Menggunakan Google Sign-In di Platform Apple

Anda dapat mengizinkan pengguna Anda mengautentikasi dengan Firebase menggunakan Akun Google mereka dengan mengintegrasikan Google Sign-In ke dalam aplikasi Anda.

Sebelum kamu memulai

  1. Tambahkan Firebase ke proyek Apple Anda . Sertakan pod berikut di Podfile Anda: l10n
    pod 'FirebaseAuth'
    pod 'GoogleSignIn'
    
  2. Jika Anda belum menghubungkan aplikasi ke proyek Firebase, lakukan dari Firebase console .
  3. Aktifkan Google sebagai metode masuk di konsol Firebase:
    1. Di Firebase console , buka bagian Auth .
    2. Pada tab Metode masuk , aktifkan metode masuk dengan Google dan klik Simpan .

1. Impor file header yang diperlukan

Pertama, Anda harus mengimpor file header Firebase SDK dan Google Sign-In SDK ke dalam aplikasi Anda.

Cepat

import FirebaseCore
import GoogleSignIn

Objective-C

@import FirebaseCore;
@import GoogleSignIn;

2. Terapkan Google Sign-In

Terapkan Google Sign-In dengan mengikuti langkah-langkah ini. Lihat dokumentasi pengembang Google Sign-In untuk detail tentang menggunakan Google Sign-In dengan iOS.

  1. Tambahkan skema URL khusus ke proyek Xcode Anda:
    1. Buka konfigurasi proyek Anda: klik dua kali nama proyek di tampilan hierarki kiri. Pilih aplikasi Anda dari bagian TARGET , lalu pilih tab Info , dan perluas bagian Jenis URL .
    2. Klik tombol + , dan tambahkan skema URL untuk ID klien terbalik Anda. Untuk menemukan nilai ini, buka file konfigurasi GoogleService-Info.plist , dan cari kunci REVERSED_CLIENT_ID . Salin nilai kunci itu, dan tempelkan ke kotak Skema URL di halaman konfigurasi. Biarkan bidang lainnya kosong.

      Setelah selesai, konfigurasi Anda akan terlihat seperti berikut ini (tetapi dengan nilai khusus aplikasi Anda):

  2. Dalam metode application:didFinishLaunchingWithOptions: , konfigurasikan objek FirebaseApp .

    Cepat

    // Use Firebase library to configure APIs
    FirebaseApp.configure()
    

    Objective-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
    
  3. Terapkan metode application:openURL:options: dari delegasi aplikasi Anda. Metode tersebut harus memanggil metode handleURL dari instance GIDSignIn , yang akan menangani dengan benar URL yang diterima aplikasi Anda di akhir proses autentikasi.

    Cepat

    @available(iOS 9.0, *)
    func application(_ application: UIApplication, open url: URL,
                     options: [UIApplication.OpenURLOptionsKey: Any])
      -> Bool {
      return GIDSignIn.sharedInstance.handle(url)
    }
    

    Objective-C

    - (BOOL)application:(nonnull UIApplication *)application
                openURL:(nonnull NSURL *)url
                options:(nonnull NSDictionary<NSString *, id> *)options {
      return [[GIDSignIn sharedInstance] handleURL:url];
    }
    
  4. Teruskan pengontrol tampilan presentasi dan ID klien untuk aplikasi Anda ke metode masuk dengan Google Sign-in dan buat kredensial autentikasi Firebase dari token autentikasi Google yang dihasilkan:

    Cepat

    guard let clientID = FirebaseApp.app()?.options.clientID else { return }
    
    // Create Google Sign In configuration object.
    let config = GIDConfiguration(clientID: clientID)
    
    // Start the sign in flow!
    GIDSignIn.sharedInstance.signIn(with: config, presenting: self) { [unowned self] user, error in
    
      if let error = error {
        // ...
        return
      }
    
      guard
        let authentication = user?.authentication,
        let idToken = authentication.idToken
      else {
        return
      }
    
      let credential = GoogleAuthProvider.credential(withIDToken: idToken,
                                                     accessToken: authentication.accessToken)
    
      // ...
    }
    

    Objective-C

    GIDConfiguration *config = [[GIDConfiguration alloc] initWithClientID:[FIRApp defaultApp].options.clientID];
    
    __weak __auto_type weakSelf = self;
    [GIDSignIn.sharedInstance signInWithConfiguration:config presentingViewController:self callback:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) {
      __auto_type strongSelf = weakSelf;
      if (strongSelf == nil) { return; }
    
      if (error == nil) {
        GIDAuthentication *authentication = user.authentication;
        FIRAuthCredential *credential =
        [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                         accessToken:authentication.accessToken];
        // ...
      } else {
        // ...
      }
    }];
    
    
  5. Tambahkan GIDSignInButton ke storyboard, file XIB, atau buat instance secara terprogram. Untuk menambahkan tombol ke storyboard atau file XIB Anda, tambahkan View dan setel kelas kustomnya ke GIDSignInButton .
  6. Opsional : Jika Anda ingin menyesuaikan tombol, lakukan hal berikut:

    Cepat

    1. Di pengontrol tampilan Anda, nyatakan tombol masuk sebagai properti.
      @IBOutlet weak var signInButton: GIDSignInButton!
    2. Hubungkan tombol ke properti signInButton yang baru saja Anda nyatakan.
    3. Kustomisasi tombol dengan menyetel properti objek GIDSignInButton .

    Objective-C

    1. Di file header pengontrol tampilan Anda, nyatakan tombol masuk sebagai properti.
      @property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
    2. Hubungkan tombol ke properti signInButton yang baru saja Anda nyatakan.
    3. Kustomisasi tombol dengan menyetel properti objek GIDSignInButton .

3. Otentikasi dengan Firebase

Terakhir, selesaikan proses login Firebase dengan kredensial autentikasi yang dibuat pada langkah sebelumnya.

Cepat

Auth.auth().signIn(with: credential) { authResult, error in
    if let error = error {
      let authError = error as NSError
      if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue {
        // The user is a multi-factor user. Second factor challenge is required.
        let resolver = authError
          .userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
        var displayNameString = ""
        for tmpFactorInfo in resolver.hints {
          displayNameString += tmpFactorInfo.displayName ?? ""
          displayNameString += " "
        }
        self.showTextInputPrompt(
          withMessage: "Select factor to sign in\n\(displayNameString)",
          completionBlock: { userPressedOK, displayName in
            var selectedHint: PhoneMultiFactorInfo?
            for tmpFactorInfo in resolver.hints {
              if displayName == tmpFactorInfo.displayName {
                selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
              }
            }
            PhoneAuthProvider.provider()
              .verifyPhoneNumber(with: selectedHint!, uiDelegate: nil,
                                 multiFactorSession: resolver
                                   .session) { verificationID, error in
                if error != nil {
                  print(
                    "Multi factor start sign in failed. Error: \(error.debugDescription)"
                  )
                } else {
                  self.showTextInputPrompt(
                    withMessage: "Verification code for \(selectedHint?.displayName ?? "")",
                    completionBlock: { userPressedOK, verificationCode in
                      let credential: PhoneAuthCredential? = PhoneAuthProvider.provider()
                        .credential(withVerificationID: verificationID!,
                                    verificationCode: verificationCode!)
                      let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator
                        .assertion(with: credential!)
                      resolver.resolveSignIn(with: assertion!) { authResult, error in
                        if error != nil {
                          print(
                            "Multi factor finanlize sign in failed. Error: \(error.debugDescription)"
                          )
                        } else {
                          self.navigationController?.popViewController(animated: true)
                        }
                      }
                    }
                  )
                }
              }
          }
        )
      } else {
        self.showMessagePrompt(error.localizedDescription)
        return
      }
      // ...
      return
    }
    // User is signed in
    // ...
}

Objective-C

[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                       NSError * _Nullable error) {
    if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
      FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
      NSMutableString *displayNameString = [NSMutableString string];
      for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
        [displayNameString appendString:tmpFactorInfo.displayName];
        [displayNameString appendString:@" "];
      }
      [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
                           completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
       FIRPhoneMultiFactorInfo* selectedHint;
       for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
         if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
           selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
         }
       }
       [FIRPhoneAuthProvider.provider
        verifyPhoneNumberWithMultiFactorInfo:selectedHint
        UIDelegate:nil
        multiFactorSession:resolver.session
        completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
          if (error) {
            [self showMessagePrompt:error.localizedDescription];
          } else {
            [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
                                 completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
             FIRPhoneAuthCredential *credential =
                 [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
                                                              verificationCode:verificationCode];
             FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
             [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
               if (error) {
                 [self showMessagePrompt:error.localizedDescription];
               } else {
                 NSLog(@"Multi factor finanlize sign in succeeded.");
               }
             }];
           }];
          }
        }];
     }];
    }
  else if (error) {
    // ...
    return;
  }
  // User successfully signed in. Get user data from the FIRUser object
  if (authResult == nil) { return; }
  FIRUser *user = authResult.user;
  // ...
}];

Langkah selanjutnya

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

  • Di aplikasi Anda, Anda bisa mendapatkan informasi profil dasar pengguna dari objek FIRUser . Lihat Kelola Pengguna .

  • Dalam Aturan Keamanan Firebase Realtime Database dan Cloud Storage , Anda bisa mendapatkan ID pengguna unik pengguna yang masuk dari variabel auth , dan menggunakannya untuk mengontrol data apa yang dapat diakses pengguna.

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

Untuk mengeluarkan pengguna, panggil signOut: .

Cepat

    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 mungkin juga ingin menambahkan kode penanganan kesalahan untuk rangkaian lengkap kesalahan otentikasi. Lihat Menangani Kesalahan .

,

Anda dapat mengizinkan pengguna Anda mengautentikasi dengan Firebase menggunakan Akun Google mereka dengan mengintegrasikan Google Sign-In ke dalam aplikasi Anda.

Sebelum kamu memulai

  1. Tambahkan Firebase ke proyek Apple Anda . Sertakan pod berikut di Podfile Anda: l10n
    pod 'FirebaseAuth'
    pod 'GoogleSignIn'
    
  2. Jika Anda belum menghubungkan aplikasi ke proyek Firebase, lakukan dari Firebase console .
  3. Aktifkan Google sebagai metode masuk di konsol Firebase:
    1. Di Firebase console , buka bagian Auth .
    2. Pada tab Metode masuk , aktifkan metode masuk dengan Google dan klik Simpan .

1. Impor file header yang diperlukan

Pertama, Anda harus mengimpor file header Firebase SDK dan Google Sign-In SDK ke dalam aplikasi Anda.

Cepat

import FirebaseCore
import GoogleSignIn

Objective-C

@import FirebaseCore;
@import GoogleSignIn;

2. Terapkan Google Sign-In

Terapkan Google Sign-In dengan mengikuti langkah-langkah ini. Lihat dokumentasi pengembang Google Sign-In untuk detail tentang menggunakan Google Sign-In dengan iOS.

  1. Tambahkan skema URL khusus ke proyek Xcode Anda:
    1. Buka konfigurasi proyek Anda: klik dua kali nama proyek di tampilan hierarki kiri. Pilih aplikasi Anda dari bagian TARGET , lalu pilih tab Info , dan perluas bagian Jenis URL .
    2. Klik tombol + , dan tambahkan skema URL untuk ID klien terbalik Anda. Untuk menemukan nilai ini, buka file konfigurasi GoogleService-Info.plist , dan cari kunci REVERSED_CLIENT_ID . Salin nilai kunci itu, dan tempelkan ke kotak Skema URL di halaman konfigurasi. Biarkan bidang lainnya kosong.

      Setelah selesai, konfigurasi Anda akan terlihat seperti berikut ini (tetapi dengan nilai khusus aplikasi Anda):

  2. Dalam metode application:didFinishLaunchingWithOptions: , konfigurasikan objek FirebaseApp .

    Cepat

    // Use Firebase library to configure APIs
    FirebaseApp.configure()
    

    Objective-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
    
  3. Terapkan metode application:openURL:options: dari delegasi aplikasi Anda. Metode tersebut harus memanggil metode handleURL dari instance GIDSignIn , yang akan menangani dengan benar URL yang diterima aplikasi Anda di akhir proses autentikasi.

    Cepat

    @available(iOS 9.0, *)
    func application(_ application: UIApplication, open url: URL,
                     options: [UIApplication.OpenURLOptionsKey: Any])
      -> Bool {
      return GIDSignIn.sharedInstance.handle(url)
    }
    

    Objective-C

    - (BOOL)application:(nonnull UIApplication *)application
                openURL:(nonnull NSURL *)url
                options:(nonnull NSDictionary<NSString *, id> *)options {
      return [[GIDSignIn sharedInstance] handleURL:url];
    }
    
  4. Teruskan pengontrol tampilan presentasi dan ID klien untuk aplikasi Anda ke metode masuk dengan Google Sign-in dan buat kredensial autentikasi Firebase dari token autentikasi Google yang dihasilkan:

    Cepat

    guard let clientID = FirebaseApp.app()?.options.clientID else { return }
    
    // Create Google Sign In configuration object.
    let config = GIDConfiguration(clientID: clientID)
    
    // Start the sign in flow!
    GIDSignIn.sharedInstance.signIn(with: config, presenting: self) { [unowned self] user, error in
    
      if let error = error {
        // ...
        return
      }
    
      guard
        let authentication = user?.authentication,
        let idToken = authentication.idToken
      else {
        return
      }
    
      let credential = GoogleAuthProvider.credential(withIDToken: idToken,
                                                     accessToken: authentication.accessToken)
    
      // ...
    }
    

    Objective-C

    GIDConfiguration *config = [[GIDConfiguration alloc] initWithClientID:[FIRApp defaultApp].options.clientID];
    
    __weak __auto_type weakSelf = self;
    [GIDSignIn.sharedInstance signInWithConfiguration:config presentingViewController:self callback:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) {
      __auto_type strongSelf = weakSelf;
      if (strongSelf == nil) { return; }
    
      if (error == nil) {
        GIDAuthentication *authentication = user.authentication;
        FIRAuthCredential *credential =
        [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                         accessToken:authentication.accessToken];
        // ...
      } else {
        // ...
      }
    }];
    
    
  5. Tambahkan GIDSignInButton ke storyboard, file XIB, atau buat instance secara terprogram. Untuk menambahkan tombol ke storyboard atau file XIB Anda, tambahkan View dan setel kelas kustomnya ke GIDSignInButton .
  6. Opsional : Jika Anda ingin menyesuaikan tombol, lakukan hal berikut:

    Cepat

    1. Di pengontrol tampilan Anda, nyatakan tombol masuk sebagai properti.
      @IBOutlet weak var signInButton: GIDSignInButton!
    2. Hubungkan tombol ke properti signInButton yang baru saja Anda nyatakan.
    3. Kustomisasi tombol dengan menyetel properti objek GIDSignInButton .

    Objective-C

    1. Di file header pengontrol tampilan Anda, nyatakan tombol masuk sebagai properti.
      @property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
    2. Hubungkan tombol ke properti signInButton yang baru saja Anda nyatakan.
    3. Kustomisasi tombol dengan menyetel properti objek GIDSignInButton .

3. Otentikasi dengan Firebase

Terakhir, selesaikan proses login Firebase dengan kredensial autentikasi yang dibuat pada langkah sebelumnya.

Cepat

Auth.auth().signIn(with: credential) { authResult, error in
    if let error = error {
      let authError = error as NSError
      if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue {
        // The user is a multi-factor user. Second factor challenge is required.
        let resolver = authError
          .userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
        var displayNameString = ""
        for tmpFactorInfo in resolver.hints {
          displayNameString += tmpFactorInfo.displayName ?? ""
          displayNameString += " "
        }
        self.showTextInputPrompt(
          withMessage: "Select factor to sign in\n\(displayNameString)",
          completionBlock: { userPressedOK, displayName in
            var selectedHint: PhoneMultiFactorInfo?
            for tmpFactorInfo in resolver.hints {
              if displayName == tmpFactorInfo.displayName {
                selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
              }
            }
            PhoneAuthProvider.provider()
              .verifyPhoneNumber(with: selectedHint!, uiDelegate: nil,
                                 multiFactorSession: resolver
                                   .session) { verificationID, error in
                if error != nil {
                  print(
                    "Multi factor start sign in failed. Error: \(error.debugDescription)"
                  )
                } else {
                  self.showTextInputPrompt(
                    withMessage: "Verification code for \(selectedHint?.displayName ?? "")",
                    completionBlock: { userPressedOK, verificationCode in
                      let credential: PhoneAuthCredential? = PhoneAuthProvider.provider()
                        .credential(withVerificationID: verificationID!,
                                    verificationCode: verificationCode!)
                      let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator
                        .assertion(with: credential!)
                      resolver.resolveSignIn(with: assertion!) { authResult, error in
                        if error != nil {
                          print(
                            "Multi factor finanlize sign in failed. Error: \(error.debugDescription)"
                          )
                        } else {
                          self.navigationController?.popViewController(animated: true)
                        }
                      }
                    }
                  )
                }
              }
          }
        )
      } else {
        self.showMessagePrompt(error.localizedDescription)
        return
      }
      // ...
      return
    }
    // User is signed in
    // ...
}

Objective-C

[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                       NSError * _Nullable error) {
    if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
      FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
      NSMutableString *displayNameString = [NSMutableString string];
      for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
        [displayNameString appendString:tmpFactorInfo.displayName];
        [displayNameString appendString:@" "];
      }
      [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
                           completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
       FIRPhoneMultiFactorInfo* selectedHint;
       for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
         if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
           selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
         }
       }
       [FIRPhoneAuthProvider.provider
        verifyPhoneNumberWithMultiFactorInfo:selectedHint
        UIDelegate:nil
        multiFactorSession:resolver.session
        completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
          if (error) {
            [self showMessagePrompt:error.localizedDescription];
          } else {
            [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
                                 completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
             FIRPhoneAuthCredential *credential =
                 [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
                                                              verificationCode:verificationCode];
             FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
             [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
               if (error) {
                 [self showMessagePrompt:error.localizedDescription];
               } else {
                 NSLog(@"Multi factor finanlize sign in succeeded.");
               }
             }];
           }];
          }
        }];
     }];
    }
  else if (error) {
    // ...
    return;
  }
  // User successfully signed in. Get user data from the FIRUser object
  if (authResult == nil) { return; }
  FIRUser *user = authResult.user;
  // ...
}];

Langkah selanjutnya

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

  • Di aplikasi Anda, Anda bisa mendapatkan informasi profil dasar pengguna dari objek FIRUser . Lihat Kelola Pengguna .

  • Dalam Aturan Keamanan Firebase Realtime Database dan Cloud Storage , Anda bisa mendapatkan ID pengguna unik pengguna yang masuk dari variabel auth , dan menggunakannya untuk mengontrol data apa yang dapat diakses pengguna.

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

Untuk mengeluarkan pengguna, panggil signOut: .

Cepat

    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 mungkin juga ingin menambahkan kode penanganan kesalahan untuk rangkaian lengkap kesalahan otentikasi. Lihat Menangani Kesalahan .