Save the date - Google I/O returns May 18-20. Register to get the most out of the digital experience: Build your schedule, reserve space, participate in Q&As, earn Google Developer profile badges, and more. Register now

Аутентификация с помощью входа в Google на iOS

Вы можете позволить своим пользователям проходить аутентификацию в Firebase, используя свои учетные записи Google, интегрировав Google Sign-In в свое приложение.

Прежде чем вы начнете

  1. Добавьте Firebase в свой проект iOS . Включите в свой Podfile следующие Podfile :
    pod 'Firebase/Auth'
    pod 'GoogleSignIn'
    
  2. Если вы еще не подключили свое приложение к проекту Firebase, сделайте это из консоли Firebase .
  3. Включите Google Sign-In в консоли Firebase:
    1. В консоли Firebase откройте раздел Auth .
    2. На вкладке Метод входа включите метод входа в Google и нажмите Сохранить .

1. Импортируйте необходимые файлы заголовков.

Во-первых, вы должны импортировать файлы заголовков Firebase SDK и Google Sign-In SDK в свое приложение.

Быстрый

В делегате приложения импортируйте следующие файлы заголовков:

import Firebase
import GoogleSignIn

В контроллере представления представления для входа импортируйте следующие файлы заголовков:

import Firebase
import GoogleSignIn

Цель-C

В делегате приложения импортируйте следующие файлы заголовков:

@import Firebase;
@import GoogleSignIn;

В контроллере представления представления для входа импортируйте следующие файлы заголовков:

@import Firebase;
@import GoogleSignIn;

2. Реализуйте вход в Google.

Выполните вход в Google, выполнив следующие действия. См. Документацию разработчика входа в Google для получения подробной информации об использовании входа в Google с iOS.

  1. Добавьте настраиваемые схемы URL-адресов в свой проект Xcode:
    1. Откройте конфигурацию проекта: дважды щелкните имя проекта в левом древовидном представлении. Выберите свое приложение в разделе ЦЕЛИ , затем перейдите на вкладку « Информация » и разверните раздел « Типы URL-адресов ».
    2. Нажмите кнопку + и добавьте схему URL-адреса для обратного идентификатора клиента. Чтобы найти это значение, откройте GoogleService-Info.plist конфигурации GoogleService-Info.plist и REVERSED_CLIENT_ID ключ REVERSED_CLIENT_ID . Скопируйте значение этого ключа и вставьте его в поле Схемы URL-адресов на странице конфигурации. Остальные поля оставьте пустыми.

      По завершении ваша конфигурация должна выглядеть примерно так (но со значениями, зависящими от вашего приложения):

  2. Объявите, что делегат приложения реализует протокол GIDSignInDelegate .

    Быстрый

    В AppDelegate.swift :
    class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {
    

    Цель-C

    В AppDelegate.h :
    @interface AppDelegate : UIResponder<UIApplicationDelegate, GIDSignInDelegate>
    
  3. В методе делегата вашего приложения application:didFinishLaunchingWithOptions: настройте объект FirebaseApp и установите делегата входа.

    Быстрый

    // Use Firebase library to configure APIs
    FirebaseApp.configure()
    
    GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
    GIDSignIn.sharedInstance().delegate = self
    

    Цель-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
    
    [GIDSignIn sharedInstance].clientID = [FIRApp defaultApp].options.clientID;
    [GIDSignIn sharedInstance].delegate = self;
    
  4. application:openURL:options: метод делегата вашего приложения. Метод должен вызывать handleURL метод GIDSignIn экземпляра, который будет правильно обрабатывать URL , что ваше приложение получает в конце процесса аутентификации.

    Быстрый

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

    Цель-C

    - (BOOL)application:(nonnull UIApplication *)application
                openURL:(nonnull NSURL *)url
                options:(nonnull NSDictionary<NSString *, id> *)options {
      return [[GIDSignIn sharedInstance] handleURL:url];
    }
    

    Чтобы ваше приложение application:openURL:sourceApplication:annotation: на iOS 8 и старше, также реализуйте устаревшее application:openURL:sourceApplication:annotation: method.

    Быстрый

    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        return GIDSignIn.sharedInstance().handle(url)
    }
    

    Цель-C

    - (BOOL)application:(UIApplication *)application
                openURL:(NSURL *)url
      sourceApplication:(NSString *)sourceApplication
             annotation:(id)annotation {
      return [[GIDSignIn sharedInstance] handleURL:url];
    }
    
  5. В GIDSignInDelegate приложения GIDSignInDelegate протокол GIDSignInDelegate для обработки процесса входа, определив следующие методы:

    Цель-C

    - (void)signIn:(GIDSignIn *)signIn
    didSignInForUser:(GIDGoogleUser *)user
         withError:(NSError *)error {
      // ...
      if (error == nil) {
        GIDAuthentication *authentication = user.authentication;
        FIRAuthCredential *credential =
        [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                         accessToken:authentication.accessToken];
        // ...
      } else {
        // ...
      }
    }
    
    - (void)signIn:(GIDSignIn *)signIn
    didDisconnectWithUser:(GIDGoogleUser *)user
         withError:(NSError *)error {
      // Perform any operations when the user disconnects from app here.
      // ...
    }
    

    Быстрый

    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
      // ...
      if let error = error {
        // ...
        return
      }
    
      guard let authentication = user.authentication else { return }
      let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
                                                        accessToken: authentication.accessToken)
      // ...
    }
    
    func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
        // Perform any operations when the user disconnects from app here.
        // ...
    }
    
  6. В контроллере представления переопределите метод viewDidLoad чтобы установить контроллер представления объекта GIDSignIn и (необязательно) выполнить вход в автоматическом режиме, когда это возможно.

    Цель-C

    [GIDSignIn sharedInstance].presentingViewController = self;
    [[GIDSignIn sharedInstance] signIn];
    

    Быстрый

    GIDSignIn.sharedInstance()?.presentingViewController = self
    GIDSignIn.sharedInstance().signIn()
    
  7. Добавьте GIDSignInButton в раскадровку, файл XIB или создайте его программным способом. Чтобы добавить кнопку в раскадровку или файл XIB, добавьте представление и установите для его настраиваемого класса значение GIDSignInButton .
  8. Необязательно : если вы хотите настроить кнопку, сделайте следующее:

    Быстрый

    1. В вашем контроллере представления объявите кнопку входа как свойство.
      @IBOutlet weak var signInButton: GIDSignInButton!
    2. Подключите кнопку к только что объявленному свойству signInButton .
    3. Настройте кнопку, задав свойства объекта GIDSignInButton .

    Цель-C

    1. В файле заголовка вашего контроллера представления объявите кнопку входа как свойство.
      @property(weak, nonatomic) IBOutlet GIDSignInButton *signInButton;
    2. Подключите кнопку к только что объявленному свойству signInButton .
    3. Настройте кнопку, задав свойства объекта GIDSignInButton .

3. Выполните аутентификацию с помощью Firebase.

В signIn:didSignInForUser:withError: получите токен Google ID и токен доступа Google из объекта GIDAuthentication и обменяйте их на учетные данные Firebase:

Быстрый

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
  // ...
  if let error = error {
    // ...
    return
  }

  guard let authentication = user.authentication else { return }
  let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
                                                    accessToken: authentication.accessToken)
  // ...
}

Цель-C

- (void)signIn:(GIDSignIn *)signIn
didSignInForUser:(GIDGoogleUser *)user
     withError:(NSError *)error {
  // ...
  if (error == nil) {
    GIDAuthentication *authentication = user.authentication;
    FIRAuthCredential *credential =
    [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                     accessToken:authentication.accessToken];
    // ...
  } else {
    // ...
  }
}

Наконец, аутентифицируйтесь в Firebase, используя учетные данные:

Быстрый

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

Цель-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;
  // ...
}];

Следующие шаги

После того, как пользователь входит в систему в первый раз, создается новая учетная запись пользователя, связанная с учетными данными, то есть с именем пользователя и паролем, номером телефона или информацией о провайдере аутентификации, с которыми пользователь вошел в систему. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя в каждом приложении в вашем проекте, независимо от того, как пользователь входит в систему.

  • В своих приложениях вы можете получить основную информацию профиля пользователя из объекта FIRUser . См. Управление пользователями .

  • В своей базе данных Firebase Realtime и правилах безопасности облачного хранилища вы можете получить уникальный идентификатор пользователя вошедшего в систему из переменной auth и использовать его для управления данными, к которым пользователь может получить доступ.

Вы можете разрешить пользователям входить в ваше приложение с помощью нескольких поставщиков аутентификации, связав учетные данные поставщика аутентификации с существующей учетной записью пользователя.

Чтобы выйти из системы, вызовите signOut:

Быстрый

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

Цель-C

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

Вы также можете добавить код обработки ошибок для всего диапазона ошибок аутентификации. См. Обработка ошибок .