Você pode permitir que seus usuários se autentiquem com o Firebase usando suas contas do Facebook integrando o login do Facebook ou o login limitado do Facebook em seu aplicativo.
Antes de você começar
Use o Swift Package Manager para instalar e gerenciar dependências do Firebase.
- No Xcode, com seu projeto de aplicativo aberto, navegue até File > Add Packages .
- Quando solicitado, adicione o repositório Firebase Apple Platform SDK:
- Escolha a biblioteca Firebase Authentication.
- Quando terminar, o Xcode começará automaticamente a resolver e baixar suas dependências em segundo plano.
https://github.com/firebase/firebase-ios-sdk
Em seguida, execute algumas etapas de configuração:
- No site Facebook for Developers , obtenha o App ID e um App Secret para seu aplicativo.
- Ativar login no Facebook:
- No console do Firebase , abra a seção Auth .
- Na guia Método de login , ative o método de login do Facebook e especifique a ID do aplicativo e o Segredo do aplicativo que você obteve do Facebook.
- Em seguida, certifique-se de que seu URI de redirecionamento OAuth (por exemplo
my-app-12345.firebaseapp.com/__/auth/handler
) esteja listado como um de seus URIs de redirecionamento OAuth na página de configurações do aplicativo do Facebook no site Facebook for Developers no Produto Configurações > Configuração de login do Facebook .
Implementar login no Facebook
Para usar o login "clássico" do Facebook, conclua as etapas a seguir. Como alternativa, você pode usar o Login limitado do Facebook, conforme mostrado na próxima seção.
- Integre o Login do Facebook em seu aplicativo seguindo a documentação do desenvolvedor . Ao inicializar o objeto
FBSDKLoginButton
, defina um delegado para receber eventos de login e logout. Por exemplo:Em seu delegado, implementeRápido
let loginButton = FBSDKLoginButton() loginButton.delegate = self
Objective-C
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init]; loginButton.delegate = self;
didCompleteWithResult:error:
.Rápido
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
Objective-C
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- Importe o módulo
FirebaseCore
em seuUIApplicationDelegate
, bem como quaisquer outros módulos Firebase usados pelo delegado do aplicativo. Por exemplo, para usar Cloud Firestore e autenticação:SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Rápido
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Configure uma instância compartilhada do
FirebaseApp
no métodoapplication(_:didFinishLaunchingWithOptions:)
do delegado do seu aplicativo:SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Rápido
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Se você estiver usando SwiftUI, deverá criar um delegado de aplicativo e anexá-lo à sua estrutura de
App
por meio deUIApplicationDelegateAdaptor
ouNSApplicationDelegateAdaptor
. Você também deve desativar o swizzling de delegado de aplicativo. Para obter mais informações, consulte as instruções do SwiftUI .SwiftUI
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
- Depois que um usuário fizer login com sucesso, em sua implementação de
didCompleteWithResult:error:
, obtenha um token de acesso para o usuário conectado e troque-o por uma credencial do Firebase:Rápido
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Implementar login limitado do Facebook
Para usar o Login limitado do Facebook em vez do Login "clássico" do Facebook, conclua as etapas a seguir.
- Integre o Login limitado do Facebook em seu aplicativo seguindo a documentação do desenvolvedor .
- Para cada solicitação de login, gere uma string aleatória exclusiva — um "nonce" — que você usará para garantir que o token de ID obtido foi concedido especificamente em resposta à solicitação de autenticação do seu aplicativo. Esta etapa é importante para evitar ataques de repetição. Você pode gerar um nonce criptograficamente seguro com
SecRandomCopyBytes(_:_:_)
, como no exemplo a seguir:Você enviará o hash SHA-256 do nonce com sua solicitação de login, que o Facebook passará inalterado na resposta. O Firebase valida a resposta fazendo o hash do nonce original e comparando-o com o valor passado pelo Facebook.Rápido
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } return random } randoms.forEach { random in if remainingLength == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result }
Objective-C
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce - (NSString *)randomNonce:(NSInteger)length { NSAssert(length > 0, @"Expected nonce to have positive length"); NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._"; NSMutableString *result = [NSMutableString string]; NSInteger remainingLength = length; while (remainingLength > 0) { NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16]; for (NSInteger i = 0; i < 16; i++) { uint8_t random = 0; int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random); NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode); [randoms addObject:@(random)]; } for (NSNumber *random in randoms) { if (remainingLength == 0) { break; } if (random.unsignedIntValue < characterSet.length) { unichar character = [characterSet characterAtIndex:random.unsignedIntValue]; [result appendFormat:@"%C", character]; remainingLength--; } } } return [result copy]; }
Rápido
@available(iOS 13, *) private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { String(format: "%02x", $0) }.joined() return hashString }
Objective-C
- (NSString *)stringBySha256HashingString:(NSString *)input { const char *string = [input UTF8String]; unsigned char result[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(string, (CC_LONG)strlen(string), result); NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { [hashed appendFormat:@"%02x", result[i]]; } return hashed; }
- Ao configurar o
FBSDKLoginButton
, defina um delegado para receber eventos de login e logoff, defina o modo de rastreamento comoFBSDKLoginTrackingLimited
e anexe um nonce. Por exemplo:Em seu delegado, implementeRápido
func setupLoginButton() { let nonce = randomNonceString() currentNonce = nonce loginButton.delegate = self loginButton.loginTracking = .limited loginButton.nonce = sha256(nonce) }
Objective-C
- (void)setupLoginButton { NSString *nonce = [self randomNonce:32]; self.currentNonce = nonce; self.loginButton.delegate = self; self.loginButton.loginTracking = FBSDKLoginTrackingLimited self.loginButton.nonce = [self stringBySha256HashingString:nonce]; }
didCompleteWithResult:error:
.Rápido
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
Objective-C
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- Importe o módulo
FirebaseCore
em seuUIApplicationDelegate
, bem como quaisquer outros módulos Firebase usados pelo delegado do aplicativo. Por exemplo, para usar Cloud Firestore e autenticação:SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Rápido
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Configure uma instância compartilhada do
FirebaseApp
no métodoapplication(_:didFinishLaunchingWithOptions:)
do delegado do seu aplicativo:SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Rápido
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Se você estiver usando SwiftUI, deverá criar um delegado de aplicativo e anexá-lo à sua estrutura de
App
por meio deUIApplicationDelegateAdaptor
ouNSApplicationDelegateAdaptor
. Você também deve desativar o swizzling de delegado de aplicativo. Para obter mais informações, consulte as instruções do SwiftUI .SwiftUI
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
- Depois que um usuário fizer login com sucesso, em sua implementação de
didCompleteWithResult:error:
, use o token de ID da resposta do Facebook com o nonce sem hash para obter uma credencial do Firebase:Rápido
// Initialize a Firebase credential. let idTokenString = AuthenticationToken.current?.tokenString let nonce = currentNonce let credential = OAuthProvider.credential(withProviderID: "facebook.com", idToken: idTokenString!, rawNonce: nonce)
Objective-C
// Initialize a Firebase credential. NSString *idTokenString = FBSDKAuthenticationToken.currentAuthenticationToken.tokenString; NSString *rawNonce = self.currentNonce; FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"facebook.com" IDToken:idTokenString rawNonce:rawNonce];
Autenticar com Firebase
Por fim, autentique-se com o Firebase usando a credencial do Firebase:
Rápido
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; // ... }];
Próximos passos
Depois que um usuário faz login pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais — ou seja, nome de usuário e senha, número de telefone ou informações do provedor de autenticação — com as quais o usuário fez login. Essa nova conta é armazenada como parte do seu projeto do Firebase e pode ser usada para identificar um usuário em todos os aplicativos do seu projeto, independentemente de como o usuário faz login.
Em seus aplicativos, você pode obter as informações básicas do perfil do
User
no objeto Usuário. Consulte Gerenciar usuários .Nas regras de segurança do Firebase Realtime Database e Cloud Storage , você pode obter o ID de usuário exclusivo do usuário conectado a partir da variável de
auth
e usá-lo para controlar quais dados um usuário pode acessar.
Você pode permitir que os usuários façam login em seu aplicativo usando vários provedores de autenticação vinculando as credenciais do provedor de autenticação a uma conta de usuário existente.
Para desconectar um usuário, chame signOut:
.
Rápido
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; }
Você também pode querer adicionar código de tratamento de erros para toda a gama de erros de autenticação. Consulte Tratar erros .