diff --git a/Example/Auth/Sample/MainViewController+OAuth.m b/Example/Auth/Sample/MainViewController+OAuth.m index 88c39942c22..c6a36019458 100644 --- a/Example/Auth/Sample/MainViewController+OAuth.m +++ b/Example/Auth/Sample/MainViewController+OAuth.m @@ -29,6 +29,10 @@ - (StaticContentTableViewSection *)oAuthSection { return [StaticContentTableViewSection sectionWithTitle:@"OAuth" cells:@[ [StaticContentTableViewCell cellWithTitle:@"Sign in with Google" action:^{ [weakSelf signInGoogleHeadfulLite]; }], + [StaticContentTableViewCell cellWithTitle:@"Link with Google" + action:^{ [weakSelf linkWithGoogleHeadfulLite]; }], + [StaticContentTableViewCell cellWithTitle:@"Reauthenticate with Google" + action:^{ [weakSelf reauthenticateWithGoogleHeadfulLite]; }], [StaticContentTableViewCell cellWithTitle:@"Sign in with Twitter" action:^{ [weakSelf signInTwitterHeadfulLite]; }], [StaticContentTableViewCell cellWithTitle:@"Sign in with GitHub" @@ -75,6 +79,68 @@ - (void)signInGoogleHeadfulLite { }]; } +- (void)linkWithGoogleHeadfulLite { + FIROAuthProvider *provider = self.googleOAuthProvider; + provider.customParameters = @{ + @"prompt" : @"consent", + }; + provider.scopes = @[ @"profile", @"email", @"https://www.googleapis.com/auth/plus.me" ]; + [self showSpinner:^{ + [[AppManager auth].currentUser linkWithProvider:provider + UIDelegate:nil + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + [self hideSpinner:^{ + if (error) { + [self logFailure:@"Reauthenticate with provider (Google) failed" error:error]; + } else if (authResult.additionalUserInfo) { + [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]]; + if (self.isNewUserToggleOn) { + NSString *newUserString = authResult.additionalUserInfo.newUser ? + @"New user" : @"Existing user"; + [self showMessagePromptWithTitle:@"New or Existing" + message:newUserString + showCancelButton:NO + completion:nil]; + } + } + [self showTypicalUIForUserUpdateResultsWithTitle:@"Link Error" error:error]; + }]; + }]; + }]; +} + +- (void)reauthenticateWithGoogleHeadfulLite { + FIROAuthProvider *provider = self.googleOAuthProvider; + provider.customParameters = @{ + @"prompt" : @"consent", + }; + provider.scopes = @[ @"profile", @"email", @"https://www.googleapis.com/auth/plus.me" ]; + [self showSpinner:^{ + [[AppManager auth].currentUser reauthenticateWithProvider:provider + UIDelegate:nil + completion:^(FIRAuthDataResult *_Nullable authResult, + NSError *_Nullable error) { + [self hideSpinner:^{ + if (error) { + [self logFailure:@"Link with provider (Google) failed" error:error]; + } else if (authResult.additionalUserInfo) { + [self logSuccess:[self stringWithAdditionalUserInfo:authResult.additionalUserInfo]]; + if (self.isNewUserToggleOn) { + NSString *newUserString = authResult.additionalUserInfo.newUser ? + @"New user" : @"Existing user"; + [self showMessagePromptWithTitle:@"New or Existing" + message:newUserString + showCancelButton:NO + completion:nil]; + } + } + [self showTypicalUIForUserUpdateResultsWithTitle:@"Reauthenticate Error" error:error]; + }]; + }]; + }]; +} + - (void)signInTwitterHeadfulLite { FIROAuthProvider *provider = self.twitterOAuthProvider; [self showSpinner:^{ diff --git a/Firebase/Auth/Source/Public/FIRUser.h b/Firebase/Auth/Source/Public/FIRUser.h index 5055ea64531..e0df1b1ee6b 100644 --- a/Firebase/Auth/Source/Public/FIRUser.h +++ b/Firebase/Auth/Source/Public/FIRUser.h @@ -18,6 +18,7 @@ #import "FIRAuth.h" #import "FIRAuthDataResult.h" +#import "FIRAuthUIDelegate.h" #import "FIRUserInfo.h" @class FIRAuthTokenResult; @@ -269,6 +270,20 @@ DEPRECATED_MSG_ATTRIBUTE( "Please use reauthenticateWithCredential:completion: f " Objective-C or reauthenticate(withCredential:completion:)" " for Swift instead."); +/** @fn reauthenticateWithProvider:UIDelegate:completion: + @brief Renews the user's authentication using the provided auth provider instance. + + @param provider An instance of an auth provider used to initiate the reauthenticate flow. + @param UIDelegate Optionally an instance of a class conforming to the FIRAuthUIDelegate + protocol, this is used for presenting the web context. If nil, a default FIRAuthUIDelegate + will be used. + @param completion Optionally; a block which is invoked when the reauthenticate flow finishes, or + is canceled. Invoked asynchronously on the main thread in the future. + */ +- (void)reauthenticateWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion; + /** @fn getIDTokenResultWithCompletion: @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired. @@ -359,6 +374,20 @@ DEPRECATED_MSG_ATTRIBUTE("Please use linkWithCredential:completion: for Objectiv - (void)linkWithCredential:(FIRAuthCredential *)credential completion:(nullable FIRAuthDataResultCallback)completion; +/** @fn linkWithProvider:UIDelegate:completion: + @brief link the user with the provided auth provider instance. + + @param provider An instance of an auth provider used to initiate the link flow. + @param UIDelegate Optionally an instance of a class conforming to the FIRAuthUIDelegate + protocol, this is used for presenting the web context. If nil, a default FIRAuthUIDelegate + will be used. + @param completion Optionally; a block which is invoked when the link flow finishes, or + is canceled. Invoked asynchronously on the main thread in the future. + */ +- (void)linkWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion; + /** @fn unlinkFromProvider:completion: @brief Disassociates a user account from a third-party identity provider with this user. diff --git a/Firebase/Auth/Source/User/FIRUser.m b/Firebase/Auth/Source/User/FIRUser.m index 781c897ecdd..d91b90440fe 100644 --- a/Firebase/Auth/Source/User/FIRUser.m +++ b/Firebase/Auth/Source/User/FIRUser.m @@ -36,6 +36,7 @@ #import "FIREmailAuthProvider.h" #import "FIREmailPasswordAuthCredential.h" #import "FIREmailLinkSignInRequest.h" +#import "FIRFederatedAuthProvider.h" #import "FIRGameCenterAuthCredential.h" #import "FIRGetAccountInfoRequest.h" #import "FIRGetAccountInfoResponse.h" @@ -791,6 +792,17 @@ - (void)reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *) creden }); } +- (void)reauthenticateWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion { + [provider getCredentialWithUIDelegate:UIDelegate + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) { + [self reauthenticateWithCredential:credential + completion:completion]; + }]; +} + - (nullable NSString *)refreshToken { __block NSString *result; dispatch_sync(FIRAuthGlobalWorkQueue(), ^{ @@ -1234,6 +1246,17 @@ - (void)linkAndRetrieveDataWithCredential:(FIRAuthCredential *)credential }); } +- (void)linkWithProvider:(id)provider + UIDelegate:(nullable id)UIDelegate + completion:(nullable FIRAuthDataResultCallback)completion { + [provider getCredentialWithUIDelegate:UIDelegate + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error) { + [self linkWithCredential:credential + completion:completion]; + }]; +} + - (void)unlinkFromProvider:(NSString *)provider completion:(nullable FIRAuthResultCallback)completion { [_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock _Nonnull complete) {