Skip to content

Commit 56dc3bf

Browse files
authored
Merge pull request #995 from firebase/rosalyntan.limited
Add support for Facebook Limited Login.
2 parents 5f1d97c + 0e5697a commit 56dc3bf

File tree

9 files changed

+165
-43
lines changed

9 files changed

+165
-43
lines changed

FirebaseFacebookAuthUI/Sources/FUIFacebookAuth.m

Lines changed: 80 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ @interface FUIFacebookAuth () <FUIAuthProvider>
6868
*/
6969
@property(nonatomic, strong) FIROAuthProvider *providerForEmulator;
7070

71+
/** @property currentNonce
72+
@brief The nonce for the current Facebook Limited Login session, if any.
73+
*/
74+
@property(nonatomic, copy, nullable) NSString *currentNonce;
75+
7176
@end
7277

7378
@implementation FUIFacebookAuth {
@@ -131,6 +136,9 @@ - (nullable NSString *)providerID {
131136
return FIRFacebookAuthProviderID;
132137
}
133138

139+
/** @fn accessToken:
140+
@brief The access token provided by Facebook's login flow.
141+
*/
134142
- (nullable NSString *)accessToken {
135143
if (self.authUI.isEmulatorEnabled) {
136144
return nil;
@@ -139,10 +147,13 @@ - (nullable NSString *)accessToken {
139147
}
140148

141149
/** @fn idToken:
142-
@brief Facebook doesn't provide User Id Token during sign in flow
150+
@brief The ID token provided by Facebook's login flow.
143151
*/
144152
- (nullable NSString *)idToken {
145-
return nil;
153+
if (self.authUI.isEmulatorEnabled) {
154+
return nil;
155+
}
156+
return FBSDKAuthenticationToken.currentAuthenticationToken.tokenString;
146157
}
147158

148159
- (NSString *)shortName {
@@ -191,29 +202,45 @@ - (void)signInWithDefaultValue:(nullable NSString *)defaultValue
191202
return;
192203
}
193204

194-
[_loginManager logInWithPermissions:_scopes
195-
fromViewController:presentingViewController
196-
handler:^(FBSDKLoginManagerLoginResult *result,
197-
NSError *error) {
198-
if (error) {
199-
NSError *newError =
200-
[FUIAuthErrorUtils providerErrorWithUnderlyingError:error
201-
providerID:FIRFacebookAuthProviderID];
202-
[self completeSignInFlowWithAccessToken:nil error:newError];
203-
} else if (result.isCancelled) {
204-
NSError *newError = [FUIAuthErrorUtils userCancelledSignInError];
205-
[self completeSignInFlowWithAccessToken:nil error:newError];
206-
} else {
205+
if (self.useLimitedLogin) {
206+
// Facebook Limited Login
207+
NSString *nonce = [FUIAuthUtils randomNonce];
208+
self.currentNonce = nonce;
209+
FBSDKLoginConfiguration *configuration =
210+
[[FBSDKLoginConfiguration alloc] initWithPermissions:_scopes
211+
tracking:FBSDKLoginTrackingLimited
212+
nonce:[FUIAuthUtils stringBySHA256HashingString:nonce]];
213+
[_loginManager logInFromViewController:presentingViewController
214+
configuration:configuration
215+
completion:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
216+
if ([self maybeHandleCancelledResult:result error:error]) {
217+
return;
218+
}
219+
self->_email = FBSDKProfile.currentProfile.email;
220+
NSString *idToken = FBSDKAuthenticationToken.currentAuthenticationToken.tokenString;
221+
[self completeSignInFlowWithAccessToken:nil idToken:idToken error:nil];
222+
}];
223+
} else {
224+
[_loginManager logInWithPermissions:_scopes
225+
fromViewController:presentingViewController
226+
handler:^(FBSDKLoginManagerLoginResult *result,
227+
NSError *error) {
228+
if ([self maybeHandleCancelledResult:result error:error]) {
229+
return;
230+
}
207231
// Retrieve email.
208-
[[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{ @"fields" : @"email" }] startWithCompletion:^(id<FBSDKGraphRequestConnecting> connection,
209-
id result,
210-
NSError *error) {
232+
[[[FBSDKGraphRequest alloc] initWithGraphPath:@"me"
233+
parameters:@{ @"fields" : @"email" }]
234+
startWithCompletion:^(id<FBSDKGraphRequestConnecting> connection,
235+
id result,
236+
NSError *error) {
211237
self->_email = result[@"email"];
212238
}];
213239
[self completeSignInFlowWithAccessToken:result.token.tokenString
240+
idToken:nil
214241
error:nil];
215-
}
216-
}];
242+
}];
243+
}
217244
}
218245

219246
- (void)signInWithOAuthProvider:(FIROAuthProvider *)oauthProvider
@@ -269,21 +296,31 @@ - (BOOL)handleOpenURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplicati
269296

270297
#pragma mark -
271298

272-
/** @fn completeSignInFlowWithAccessToken:error:
299+
/** @fn completeSignInFlowWithAccessToken:idToken:error:
273300
@brief Called with the result of a Facebook sign-in attempt. Invokes and clears any pending
274301
sign in callback block.
275-
@param accessToken The Facebook access token, if successful.
302+
@param accessToken The Facebook access token, if the Facebook sign-in attempt with tracking enabled is successful.
303+
@param idToken The Facebook ID token, if the Facebook Limited Login attempt is successful.
276304
@param error An error which occurred during the sign-in attempt.
277305
*/
278306
- (void)completeSignInFlowWithAccessToken:(nullable NSString *)accessToken
307+
idToken:(nullable NSString *)idToken
279308
error:(nullable NSError *)error {
280309
if (error) {
281310
[self callbackWithCredential:nil error:error result:nil];
282311
return;
283312
}
284-
// Assume accessToken cannot be nil if there's no error.
285-
NSString *_Nonnull token = (id _Nonnull)accessToken;
286-
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:token];
313+
FIRAuthCredential *credential;
314+
if (idToken) {
315+
NSString *rawNonce = self.currentNonce;
316+
credential = [FIROAuthProvider credentialWithProviderID:FIRFacebookAuthProviderID
317+
IDToken:idToken
318+
rawNonce:rawNonce];
319+
} else {
320+
// Assume accessToken cannot be nil if there's no error and idToken is nil.
321+
NSString *_Nonnull token = (id _Nonnull)accessToken;
322+
credential = [FIRFacebookAuthProvider credentialWithAccessToken:token];
323+
}
287324
UIActivityIndicatorView *activityView =
288325
[FUIAuthBaseViewController addActivityIndicator:_presentingViewController.view];
289326
[activityView startAnimating];
@@ -347,4 +384,22 @@ - (FBSDKLoginManager *)createLoginManager {
347384
return [[FBSDKLoginManager alloc] init];
348385
}
349386

387+
- (BOOL)maybeHandleCancelledResult:(FBSDKLoginManagerLoginResult *)result
388+
error:(NSError *)error {
389+
if (error) {
390+
NSError *newError =
391+
[FUIAuthErrorUtils providerErrorWithUnderlyingError:error
392+
providerID:FIRFacebookAuthProviderID];
393+
[self completeSignInFlowWithAccessToken:nil idToken:nil error:newError];
394+
return true;
395+
}
396+
397+
if (result.isCancelled) {
398+
NSError *newError = [FUIAuthErrorUtils userCancelledSignInError];
399+
[self completeSignInFlowWithAccessToken:nil idToken:nil error:newError];
400+
return true;
401+
}
402+
return false;
403+
}
404+
350405
@end

FirebaseFacebookAuthUI/Sources/Public/FirebaseFacebookAuthUI/FUIFacebookAuth.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ NS_ASSUME_NONNULL_BEGIN
4848
*/
4949
@property(nonatomic, readwrite) FUIButtonAlignment buttonAlignment;
5050

51+
/** @property useLimitedLogin
52+
@brief Whether or not Facebook Login should use Limited Login mode.
53+
*/
54+
@property(nonatomic, assign) BOOL useLimitedLogin;
55+
5156
/** @fn initWithAuthUI
5257
@brief Convenience initializer. Uses a default permission of `@[ "email" ]`.
5358
@param authUI The @c FUIAuth instance that manages this provider.

FirebaseOAuthUI/Sources/FUIOAuth.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ @interface FUIOAuth () <ASAuthorizationControllerDelegate, ASAuthorizationContro
9999
*/
100100
@property(nonatomic, copy, nullable) NSString *loginHintKey;
101101

102+
/** @property currentNonce
103+
@brief The nonce for the current Sign in with Apple session, if any.
104+
*/
102105
@property(nonatomic, copy, nullable) NSString *currentNonce;
103106

104107
/** @property provider

samples/objc/FirebaseUI-demo-objc/FUIAppDelegate.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
@import Firebase;
2020
@import FirebaseAuthUI;
21+
@import FBSDKCoreKit;
2122
#import <GTMSessionFetcher/GTMSessionFetcherLogging.h>
2223

2324
@implementation FUIAppDelegate
@@ -26,13 +27,18 @@ - (BOOL)application:(UIApplication *)application
2627
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
2728
[FIRApp configure];
2829
[GTMSessionFetcher setLoggingEnabled:YES];
30+
[[FBSDKApplicationDelegate sharedInstance] application:application
31+
didFinishLaunchingWithOptions:launchOptions];
2932
return YES;
3033
}
3134

3235
- (BOOL)application:(UIApplication *)app
3336
openURL:(NSURL *)url
3437
options:(NSDictionary<NSString*, id> *)options {
3538
NSString *sourceApplication = options[UIApplicationOpenURLOptionsSourceApplicationKey];
39+
[[FBSDKApplicationDelegate sharedInstance] application:app
40+
openURL:url
41+
options:options];
3642
return [self handleOpenUrl:url sourceApplication:sourceApplication];
3743
}
3844

samples/objc/FirebaseUI-demo-objc/Resources/Main.storyboard

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="7RW-VL-qNI">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="7RW-VL-qNI">
33
<device id="retina4_7" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
77
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
88
</dependencies>
99
<scenes>
@@ -162,7 +162,7 @@
162162
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Custom Authorization UI" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="YxK-c8-9q7">
163163
<rect key="frame" x="27" y="12" width="322" height="20"/>
164164
<fontDescription key="fontDescription" type="system" pointSize="16"/>
165-
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
165+
<color key="textColor" systemColor="darkTextColor"/>
166166
<nil key="highlightedColor"/>
167167
</label>
168168
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="JZd-6c-Soe">
@@ -191,7 +191,7 @@
191191
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Custom Scopes" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="T07-wL-pGr">
192192
<rect key="frame" x="27" y="12" width="322" height="20"/>
193193
<fontDescription key="fontDescription" type="system" pointSize="16"/>
194-
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
194+
<color key="textColor" systemColor="darkTextColor"/>
195195
<nil key="highlightedColor"/>
196196
</label>
197197
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="9Ma-Mx-g56">
@@ -225,14 +225,14 @@
225225
<nil key="textColor"/>
226226
<nil key="highlightedColor"/>
227227
</label>
228-
<label opaque="NO" userInteractionEnabled="NO" alpha="0.80000000000000004" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Link" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ig5-8M-jHk">
228+
<label opaque="NO" userInteractionEnabled="NO" alpha="0.80000000000000004" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Link" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ig5-8M-jHk">
229229
<rect key="frame" x="244" y="10.5" width="48" height="21"/>
230230
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
231231
<fontDescription key="fontDescription" type="system" pointSize="12"/>
232232
<nil key="textColor"/>
233233
<nil key="highlightedColor"/>
234234
</label>
235-
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" ambiguous="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LiB-gr-jDR">
235+
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LiB-gr-jDR">
236236
<rect key="frame" x="300" y="5.5" width="49" height="31"/>
237237
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
238238
<connections>
@@ -273,6 +273,17 @@
273273
<nil key="textColor"/>
274274
<nil key="highlightedColor"/>
275275
</label>
276+
<label opaque="NO" userInteractionEnabled="NO" alpha="0.80000000000000004" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Limited" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XLV-Sd-fV6">
277+
<rect key="frame" x="244" y="11.5" width="48" height="21"/>
278+
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
279+
<fontDescription key="fontDescription" type="system" pointSize="12"/>
280+
<nil key="textColor"/>
281+
<nil key="highlightedColor"/>
282+
</label>
283+
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="H4b-GH-bc7" userLabel="Facebook Switch">
284+
<rect key="frame" x="300" y="6.5" width="49" height="31"/>
285+
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
286+
</switch>
276287
</subviews>
277288
</tableViewCellContentView>
278289
</tableViewCell>
@@ -537,6 +548,7 @@
537548
<outlet property="customScopeSwitch" destination="9Ma-Mx-g56" id="Scy-Do-CrR"/>
538549
<outlet property="emailLabel" destination="ig5-8M-jHk" id="a2T-8z-dxJ"/>
539550
<outlet property="emailSwitch" destination="LiB-gr-jDR" id="I2g-oL-ZRC"/>
551+
<outlet property="facebookSwitch" destination="H4b-GH-bc7" id="z4w-iM-AYz"/>
540552
</connections>
541553
</tableViewController>
542554
<placeholder placeholderIdentifier="IBFirstResponder" id="1w1-3x-wCC" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -561,7 +573,7 @@
561573
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jIg-6e-k6g">
562574
<rect key="frame" x="0.0" y="617" width="375" height="50"/>
563575
<subviews>
564-
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="T3i-kj-emg">
576+
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="T3i-kj-emg">
565577
<rect key="frame" x="333" y="8" width="34" height="34"/>
566578
<state key="normal" title="Load"/>
567579
<connections>
@@ -608,4 +620,9 @@
608620
<point key="canvasLocation" x="2377" y="315"/>
609621
</scene>
610622
</scenes>
623+
<resources>
624+
<systemColor name="darkTextColor">
625+
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
626+
</systemColor>
627+
</resources>
611628
</document>

0 commit comments

Comments
 (0)