Vous pouvez permettre à vos utilisateurs de s'authentifier auprès de Firebase à l'aide de leurs comptes Facebook en intégrant Facebook Login ou Facebook Limited Login dans votre application.
Avant que tu commences
Utilisez Swift Package Manager pour installer et gérer les dépendances Firebase.
- Dans Xcode, avec votre projet d'application ouvert, accédez à File > Add Packages .
- Lorsque vous y êtes invité, ajoutez le référentiel SDK des plates-formes Apple Firebase :
- Choisissez la bibliothèque d'authentification Firebase.
- Ajoutez l'indicateur
-ObjC
à la section Autres indicateurs de l'éditeur de liens des paramètres de construction de votre cible. - Une fois terminé, Xcode commencera automatiquement à résoudre et à télécharger vos dépendances en arrière-plan.
https://github.com/firebase/firebase-ios-sdk.git
Ensuite, effectuez quelques étapes de configuration :
- Sur le site Facebook pour les développeurs , obtenez l' ID d'application et un secret d'application pour votre application.
- Activer la connexion Facebook :
- Dans la console Firebase , ouvrez la section Auth .
- Dans l'onglet Méthode de connexion , activez la méthode de connexion Facebook et spécifiez l' ID d'application et le secret d'application que vous avez obtenus de Facebook.
- Ensuite, assurez-vous que votre URI de redirection OAuth (par exemple
my-app-12345.firebaseapp.com/__/auth/handler
) est répertorié comme l'un de vos URI de redirection OAuth dans la page des paramètres de votre application Facebook sur le site Facebook pour les développeurs dans la section Produit. Paramètres > Configuration de connexion Facebook .
Implémenter la connexion Facebook
Pour utiliser la connexion Facebook « classique », procédez comme suit. Vous pouvez également utiliser la connexion limitée à Facebook, comme indiqué dans la section suivante.
- Intégrez Facebook Login dans votre application en suivant la documentation du développeur . Lorsque vous initialisez l'objet
FBSDKLoginButton
, définissez un délégué pour recevoir les événements de connexion et de déconnexion. Par exemple:Dans votre délégué, implémentezRapide
let loginButton = FBSDKLoginButton() loginButton.delegate = self
Objectif c
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init]; loginButton.delegate = self;
didCompleteWithResult:error:
.Rapide
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
Objectif c
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- Importez le module
FirebaseCore
dans votreUIApplicationDelegate
, ainsi que tous les autres modules Firebase utilisés par votre délégué d'application. Par exemple, pour utiliser Cloud Firestore et l'authentification :SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Rapide
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objectif c
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Configurez une instance partagée
FirebaseApp
dans la méthodeapplication(_:didFinishLaunchingWithOptions:)
de votre délégué d'application :SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Rapide
// Use Firebase library to configure APIs FirebaseApp.configure()
Objectif c
// Use Firebase library to configure APIs [FIRApp configure];
- Si vous utilisez SwiftUI, vous devez créer un délégué d'application et l'attacher à votre structure
App
viaUIApplicationDelegateAdaptor
ouNSApplicationDelegateAdaptor
. Vous devez également désactiver le swizzling des délégués d’application. Pour plus d'informations, consultez les instructions SwiftUI .SwiftUI
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
- Une fois qu'un utilisateur s'est connecté avec succès, dans votre implémentation de
didCompleteWithResult:error:
, obtenez un jeton d'accès pour l'utilisateur connecté et échangez-le contre un identifiant Firebase :Rapide
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objectif c
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Implémenter la connexion limitée à Facebook
Pour utiliser la connexion Facebook limitée au lieu de la connexion Facebook « classique », procédez comme suit.
- Intégrez Facebook Limited Login dans votre application en suivant la documentation du développeur .
- Pour chaque demande de connexion, générez une chaîne aléatoire unique (un « nonce ») que vous utiliserez pour vous assurer que le jeton d'identification que vous obtenez a été accordé spécifiquement en réponse à la demande d'authentification de votre application. Cette étape est importante pour empêcher les attaques par rejeu. Vous pouvez générer un nom occasionnel cryptographiquement sécurisé avec
SecRandomCopyBytes(_:_:_)
, comme dans l'exemple suivant :Vous enverrez le hachage SHA-256 du nonce avec votre demande de connexion, que Facebook transmettra sans modification dans la réponse. Firebase valide la réponse en hachant le nom occasionnel d'origine et en le comparant à la valeur transmise par Facebook.Rapide
private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) var randomBytes = [UInt8](repeating: 0, count: length) let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes) if errorCode != errSecSuccess { fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } let charset: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") let nonce = randomBytes.map { byte in // Pick a random character from the set, wrapping around if needed. charset[Int(byte) % charset.count] } return String(nonce) }
Objectif 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]; }
Rapide
@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 }
Objectif 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; }
- Lorsque vous configurez
FBSDKLoginButton
, définissez un délégué pour recevoir les événements de connexion et de déconnexion, définissez le mode de suivi surFBSDKLoginTrackingLimited
et attachez un nom occasionnel. Par exemple:Dans votre délégué, implémentezRapide
func setupLoginButton() { let nonce = randomNonceString() currentNonce = nonce loginButton.delegate = self loginButton.loginTracking = .limited loginButton.nonce = sha256(nonce) }
Objectif 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:
.Rapide
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let error = error { print(error.localizedDescription) return } // ... }
Objectif c
- (void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error { if (error == nil) { // ... } else { NSLog(error.localizedDescription); } }
- Importez le module
FirebaseCore
dans votreUIApplicationDelegate
, ainsi que tous les autres modules Firebase utilisés par votre délégué d'application. Par exemple, pour utiliser Cloud Firestore et l'authentification :SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Rapide
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objectif c
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Configurez une instance partagée
FirebaseApp
dans la méthodeapplication(_:didFinishLaunchingWithOptions:)
de votre délégué d'application :SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Rapide
// Use Firebase library to configure APIs FirebaseApp.configure()
Objectif c
// Use Firebase library to configure APIs [FIRApp configure];
- Si vous utilisez SwiftUI, vous devez créer un délégué d'application et l'attacher à votre structure
App
viaUIApplicationDelegateAdaptor
ouNSApplicationDelegateAdaptor
. Vous devez également désactiver le swizzling des délégués d’application. Pour plus d'informations, consultez les instructions SwiftUI .SwiftUI
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
- Une fois qu'un utilisateur s'est connecté avec succès, dans votre implémentation de
didCompleteWithResult:error:
, utilisez le jeton d'identification de la réponse de Facebook avec le nom occasionnel non haché pour obtenir un identifiant Firebase :Rapide
// Initialize a Firebase credential. let idTokenString = AuthenticationToken.current?.tokenString let nonce = currentNonce let credential = OAuthProvider.credential(withProviderID: "facebook.com", idToken: idTokenString!, rawNonce: nonce)
Objectif c
// Initialize a Firebase credential. NSString *idTokenString = FBSDKAuthenticationToken.currentAuthenticationToken.tokenString; NSString *rawNonce = self.currentNonce; FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"facebook.com" IDToken:idTokenString rawNonce:rawNonce];
S'authentifier avec Firebase
Enfin, authentifiez-vous auprès de Firebase à l'aide des informations d'identification Firebase :
Rapide
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 // ... }
Objectif 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; // ... }];
Prochaines étapes
Après qu'un utilisateur se connecte pour la première fois, un nouveau compte utilisateur est créé et lié aux informations d'identification (c'est-à-dire le nom d'utilisateur et le mot de passe, le numéro de téléphone ou les informations du fournisseur d'authentification) avec lesquels l'utilisateur s'est connecté. Ce nouveau compte est stocké dans le cadre de votre projet Firebase et peut être utilisé pour identifier un utilisateur dans chaque application de votre projet, quelle que soit la manière dont l'utilisateur se connecte.
Dans vos applications, vous pouvez obtenir les informations de base du profil de l'utilisateur à partir de l'objet
User
. Voir Gérer les utilisateurs .Dans vos règles de sécurité Firebase Realtime Database et Cloud Storage, vous pouvez obtenir l'ID utilisateur unique de l'utilisateur connecté à partir de la variable
auth
et l'utiliser pour contrôler les données auxquelles un utilisateur peut accéder.
Vous pouvez autoriser les utilisateurs à se connecter à votre application à l'aide de plusieurs fournisseurs d'authentification en associant les informations d'identification du fournisseur d'authentification à un compte utilisateur existant.
Pour déconnecter un utilisateur, appelez signOut:
.
Rapide
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
Objectif c
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
Vous souhaiterez peut-être également ajouter un code de gestion des erreurs pour la gamme complète des erreurs d'authentification. Voir Gérer les erreurs .