Signing in users with Facebook on iOS
You can let your users authenticate with Identity Platform using their Facebook accounts by integrating Facebook Login or Facebook Limited Login into your app. This page shows you how to use Identity Platform to add Sign in with Facebook to your iOS app.
Before you begin
Include the following pods in your
Podfile:pod 'FirebaseAuth'Go to the Identity Providers page in the Google Cloud console.
Click Add A Provider.
Select Facebook from the list.
Enter your Facebook App ID and App Secret. If you don't already have an ID and secret, you can obtain one from the Facebook for Developers page.
Configure the URI listed under Configure Facebook as a valid OAuth redirect URI for your Facebook app. If you configured a custom domain in Identity Platform, update the redirect URI in your Facebook app configuration to use the custom domain instead of the default domain. For example, change
https://myproject.firebaseapp.com/__/auth/handlertohttps://auth.myownpersonaldomain.com/__/auth/handler.Register your app's domains by clicking Add Domain under Authorized Domains. For development purposes,
localhostis already enabled by default.Under Configure your application, click Setup Details. Copy the snippet into your app's code to initialize the Identity Platform client SDK.
Click Save.
Implement Facebook Login
To use "classic" Facebook Login, complete the following steps. Alternatively, you can use Facebook Limited Login, as shown in the next section.
- Integrate Facebook Login into your app by following the
developer's documentation. When you initialize the
FBSDKLoginButtonobject, set a delegate to receive login and logout events. For example:In your delegate, implementSwift
letloginButton=FBSDKLoginButton() loginButton.delegate=self
Objective-C
FBSDKLoginButton*loginButton=[[FBSDKLoginButtonalloc]init]; loginButton.delegate=self;
didCompleteWithResult:error:.Swift
funcloginButton(_loginButton:FBSDKLoginButton!,didCompleteWithresult:FBSDKLoginManagerLoginResult!,error:Error!){ ifleterror=error{ print(error.localizedDescription) return } // ... }
Objective-C
- (void)loginButton:(FBSDKLoginButton*)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult*)result error:(NSError*)error{ if(error==nil){ // ... }else{ NSLog(error.localizedDescription); } }
- Import the Firebase module in your
UIApplicationDelegate:Swift
importFirebaseCore importFirebaseAuth
Objective-C
@importFirebaseCore; @importFirebaseAuth;
- Configure a
FirebaseAppshared instance, typically in your app'sapplication:didFinishLaunchingWithOptions:method:Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRAppconfigure];
- After a user successfully signs in, in your implementation of
didCompleteWithResult:error:, get an access token for the signed-in user and exchange it for an Identity Platform credential:Swift
letcredential=FacebookAuthProvider .credential(withAccessToken:AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential*credential=[FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessTokencurrentAccessToken].tokenString];
Implement Facebook Limited Login
To use Facebook Limited Login instead of "classic" Facebook Login, complete the following steps.
- Integrate Facebook Limited Login into your app by following the developer's documentation.
- For every sign-in request, generate a unique random string—a "nonce"—which
you will use to make sure the ID token you get was granted specifically in
response to your app's authentication request. This step is important to
prevent replay attacks.
You can generate a cryptographically secure nonce on iOS with
SecRandomCopyBytes(_:_:_), as in the following example:You will send the SHA-256 hash of the nonce with your sign-in request, which Facebook will pass unchanged in the response. Identity Platform validates the response by hashing the original nonce and comparing it to the value passed by Facebook.Swift
privatefuncrandomNonceString(length:Int=32)->String{ precondition(length > 0) varrandomBytes=[UInt8](repeating:0,count:length) leterrorCode=SecRandomCopyBytes(kSecRandomDefault,randomBytes.count,&randomBytes) iferrorCode!=errSecSuccess{ fatalError( "Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)" ) } letcharset:[Character]= Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") letnonce=randomBytes.map{bytein // Pick a random character from the set, wrapping around if needed. charset[Int(byte)%charset.count] } returnString(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=[NSMutableStringstring]; NSIntegerremainingLength=length; while(remainingLength > 0){ NSMutableArray*randoms=[NSMutableArrayarrayWithCapacity:16]; for(NSIntegeri=0;i < 16;i++){ uint8_trandom=0; interrorCode=SecRandomCopyBytes(kSecRandomDefault,1,&random); NSAssert(errorCode==errSecSuccess,@"Unable to generate nonce: OSStatus %i",errorCode); [randomsaddObject:@(random)]; } for(NSNumber*randominrandoms){ if(remainingLength==0){ break; } if(random.unsignedIntValue < characterSet.length){ unicharcharacter=[characterSetcharacterAtIndex:random.unsignedIntValue]; [resultappendFormat:@"%C",character]; remainingLength--; } } } return[resultcopy]; }
Swift
@available(iOS13,*) privatefuncsha256(_input:String)->String{ letinputData=Data(input.utf8) lethashedData=SHA256.hash(data:inputData) lethashString=hashedData.compactMap{ String(format:"%02x",0ドル) }.joined() returnhashString }
Objective-C
- (NSString*)stringBySha256HashingString:(NSString*)input{ constchar*string=[inputUTF8String]; unsignedcharresult[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(string,(CC_LONG)strlen(string),result); NSMutableString*hashed=[NSMutableStringstringWithCapacity:CC_SHA256_DIGEST_LENGTH*2]; for(NSIntegeri=0;i < CC_SHA256_DIGEST_LENGTH;i++){ [hashedappendFormat:@"%02x",result[i]]; } returnhashed; }
- When you set up the
FBSDKLoginButton, set a delegate to receive login and logout events, set the tracking mode toFBSDKLoginTrackingLimited, and attach a nonce. For example:In your delegate, implementSwift
funcsetupLoginButton(){ letnonce=randomNonceString() currentNonce=nonce loginButton.delegate=self loginButton.loginTracking=.limited loginButton.nonce=sha256(nonce) }
Objective-C
- (void)setupLoginButton{ NSString*nonce=[selfrandomNonce:32]; self.currentNonce=nonce; self.loginButton.delegate=self; self.loginButton.loginTracking=FBSDKLoginTrackingLimited self.loginButton.nonce=[selfstringBySha256HashingString:nonce]; }
didCompleteWithResult:error:.Swift
funcloginButton(_loginButton:FBSDKLoginButton!,didCompleteWithresult:FBSDKLoginManagerLoginResult!,error:Error!){ ifleterror=error{ print(error.localizedDescription) return } // ... }
Objective-C
- (void)loginButton:(FBSDKLoginButton*)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult*)result error:(NSError*)error{ if(error==nil){ // ... }else{ NSLog(error.localizedDescription); } }
- Import the Firebase module in your
UIApplicationDelegate:Swift
importFirebase
Objective-C
@importFirebase;
- Configure a
FirebaseAppshared instance, typically in your app'sapplication:didFinishLaunchingWithOptions:method:Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRAppconfigure];
- After a user successfully signs in, in your implementation of
didCompleteWithResult:error:, use the ID token from Facebook's response with the unhashed nonce to get an Identity Platform credential:Swift
// Initialize an Identity Platform credential. letidTokenString=AuthenticationToken.current?.tokenString letnonce=currentNonce letcredential=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=[FIROAuthProvidercredentialWithProviderID:@"facebook.com" IDToken:idTokenString rawNonce:rawNonce];
Authenticate with Identity Platform
Finally, authenticate with Identity Platform using the Identity Platform credential:
Swift
Auth.auth().signIn(with:credential){authResult,errorin ifleterror=error{ letauthError=errorasNSError ifisMFAEnabled,authError.code==AuthErrorCode.secondFactorRequired.rawValue{ // The user is a multi-factor user. Second factor challenge is required. letresolver=authError .userInfo[AuthErrorUserInfoMultiFactorResolverKey]as!MultiFactorResolver vardisplayNameString="" fortmpFactorInfoinresolver.hints{ displayNameString+=tmpFactorInfo.displayName??"" displayNameString+=" " } self.showTextInputPrompt( withMessage:"Select factor to sign in\n\(displayNameString)", completionBlock:{userPressedOK,displayNamein varselectedHint:PhoneMultiFactorInfo? fortmpFactorInfoinresolver.hints{ ifdisplayName==tmpFactorInfo.displayName{ selectedHint=tmpFactorInfoas?PhoneMultiFactorInfo } } PhoneAuthProvider.provider() .verifyPhoneNumber(with:selectedHint!,uiDelegate:nil, multiFactorSession:resolver .session){verificationID,errorin iferror!=nil{ print( "Multi factor start sign in failed. Error: \(error.debugDescription)" ) }else{ self.showTextInputPrompt( withMessage:"Verification code for \(selectedHint?.displayName??"")", completionBlock:{userPressedOK,verificationCodein letcredential:PhoneAuthCredential?=PhoneAuthProvider.provider() .credential(withVerificationID:verificationID!, verificationCode:verificationCode!) letassertion:MultiFactorAssertion?=PhoneMultiFactorGenerator .assertion(with:credential!) resolver.resolveSignIn(with:assertion!){authResult,errorin iferror!=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
[[FIRAuthauth]signInWithCredential:credential completion:^(FIRAuthDataResult*_NullableauthResult, NSError*_Nullableerror){ if(isMFAEnabled && error && error.code==FIRAuthErrorCodeSecondFactorRequired){ FIRMultiFactorResolver*resolver=error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; NSMutableString*displayNameString=[NSMutableStringstring]; for(FIRMultiFactorInfo*tmpFactorInfoinresolver.hints){ [displayNameStringappendString:tmpFactorInfo.displayName]; [displayNameStringappendString:@" "]; } [selfshowTextInputPromptWithMessage:[NSStringstringWithFormat:@"Select factor to sign in\n%@",displayNameString] completionBlock:^(BOOLuserPressedOK,NSString*_NullabledisplayName){ FIRPhoneMultiFactorInfo*selectedHint; for(FIRMultiFactorInfo*tmpFactorInfoinresolver.hints){ if([displayNameisEqualToString:tmpFactorInfo.displayName]){ selectedHint=(FIRPhoneMultiFactorInfo*)tmpFactorInfo; } } [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:selectedHint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString*_NullableverificationID,NSError*_Nullableerror){ if(error){ [selfshowMessagePrompt:error.localizedDescription]; }else{ [selfshowTextInputPromptWithMessage:[NSStringstringWithFormat:@"Verification code for %@",selectedHint.displayName] completionBlock:^(BOOLuserPressedOK,NSString*_NullableverificationCode){ FIRPhoneAuthCredential*credential= [[FIRPhoneAuthProviderprovider]credentialWithVerificationID:verificationID verificationCode:verificationCode]; FIRMultiFactorAssertion*assertion=[FIRPhoneMultiFactorGeneratorassertionWithCredential:credential]; [resolverresolveSignInWithAssertion:assertioncompletion:^(FIRAuthDataResult*_NullableauthResult,NSError*_Nullableerror){ if(error){ [selfshowMessagePrompt:error.localizedDescription]; }else{ NSLog(@"Multi factor finanlize sign in succeeded."); } }]; }]; } }]; }]; } elseif(error){ // ... return; } // User successfully signed in. Get user data from the FIRUser object if(authResult==nil){return;} FIRUser*user=authResult.user; // ... }];
What's next
- Learn more about Identity Platform users.
- Sign in users with other identity providers.