Connecter des utilisateurs avec Facebook sur iOS
Vous pouvez autoriser vos utilisateurs à s'authentifier auprès d'Identity Platform à l'aide de leur compte Facebook en intégrant Facebook Login ou Facebook Limited dans votre application. Cette page explique comment utiliser Identity Platform pour ajouter une option "Se connecter avec Facebook" à votre application iOS.
Avant de commencer
Incluez les pods suivants dans votre fichier
Podfile
:pod 'FirebaseAuth'
Accédez à la page Fournisseurs d'identité dans la console Google Cloud.
Cliquez sur Ajouter un fournisseur.
Sélectionnez Facebook dans la liste.
Saisissez votre ID d'application et votre code secret de l'application Facebook. Si vous ne possédez pas encore d'ID et de code secret, vous pouvez en obtenir un sur la page Facebook for Developers.
Configurez l'URI répertorié sous Configurer Facebook en tant qu'URI de redirection OAuth valide pour votre application Facebook. Si vous avez configuré un domaine personnalisé dans Identity Platform, modifiez l'URI de redirection dans la configuration de votre application Facebook pour utiliser le domaine personnalisé au lieu du domaine par défaut. Par exemple, remplacez
https://myproject.firebaseapp.com/__/auth/handler
parhttps://auth.myownpersonaldomain.com/__/auth/handler
.Enregistrez les domaines de votre application en cliquant sur Ajouter un domaine sous Domaines autorisés. À des fins de développement,
localhost
est déjà activé par défaut.Sous Configurer votre application, cliquez sur Informations sur la configuration. Copiez l'extrait dans le code de votre application pour initialiser le SDK client Identity Platform.
Cliquez sur Enregistrer.
Implémenter Facebook Login
Pour utiliser la connexion Facebook "classique", suivez la procédure ci-dessous. Vous pouvez également utiliser la connexion Facebook Limited, comme indiqué dans la section suivante.
- Intégrez Facebook Login à votre application en vous aidant de la documentation pour les développeurs. Lorsque vous initialisez l'objet
FBSDKLoginButton
, spécifiez le délégué qui doit recevoir les événements de connexion et de déconnexion. Exemple :Swift
let loginButton = FBSDKLoginButton() loginButton.delegate = self
Objective-C
FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init]; loginButton.delegate = self;
didCompleteWithResult:error:
.Swift
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); } }
- Importez le module Firebase dans
UIApplicationDelegate
:Swift
import FirebaseCore import FirebaseAuth
Objective-C
@import FirebaseCore; @import FirebaseAuth;
- Configurez une instance partagée
FirebaseApp
. En général, cela se fait dans la méthodeapplication:didFinishLaunchingWithOptions:
de votre application :Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Une fois l'utilisateur connecté, dans votre implémentation de
didCompleteWithResult:error:
, obtenez un jeton d'accès pour l'utilisateur connecté et échangez-le contre un identifiant Identity Platform :Swift
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Implémenter la connexion Facebook Limited
Pour utiliser la connexion Facebook Limited au lieu d'une connexion Facebook "classique", procédez comme suit :
- Intégrez la connexion Facebook Limited à votre application en vous aidant de la documentation pour les développeurs.
- 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'ID obtenu a été accordé spécifiquement en réponse à la requête d'authentification de votre application. Cette étape est importante pour éviter les attaques par relecture.
Vous pouvez générer un nonce sécurisé par chiffrement sur iOS avec
SecRandomCopyBytes(_:_:_)
, comme dans l'exemple suivant :Swift
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) }
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]; }
Swift
@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; }
- Lorsque vous configurez le paramètre
FBSDKLoginButton
, définissez le délégué qui doit recevoir les événements de connexion et de déconnexion, puis définissez le mode de suivi surFBSDKLoginTrackingLimited
et associez un nonce. Exemple :Swift
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:
.Swift
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); } }
- Importez le module Firebase dans
UIApplicationDelegate
:Swift
import Firebase
Objective-C
@import Firebase;
- Configurez une instance partagée
FirebaseApp
. En général, cela se fait dans la méthodeapplication:didFinishLaunchingWithOptions:
de votre application :Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Une fois qu'un utilisateur s'est connecté, dans votre implémentation de
didCompleteWithResult:error:
, utilisez le jeton d'ID de la réponse de Facebook avec le nonce non haché pour obtenir un identifiant Identity Platform :Swift
// Initialize an Identity Platform credential. let idTokenString = AuthenticationToken.current?.tokenString let nonce = currentNonce let credential = OAuthProvider.credential(withProviderID: "facebook.com", IDToken: idTokenString, rawNonce: nonce)
Objective-C
// Initialize an Identity Platform credential. NSString *idTokenString = FBSDKAuthenticationToken.currentAuthenticationToken.tokenString; NSString *rawNonce = self.currentNonce; FIROAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"facebook.com" IDToken:idTokenString rawNonce:rawNonce];
S'authentifie avec Identity Platform.
Enfin, authentifiez-vous auprès d'Identity Platform à l'aide de l'identifiant Identity Platform :
Swift
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; // ... }];
Étape suivante
- En savoir plus sur les utilisateurs d'Identity Platform.
- Procéder à la connexion des utilisateurs avec d'autres fournisseurs d'identité.