Skip to content

Commit c13cc92

Browse files
author
chuanr
authored
Fix a bug where the linking/reauth flows errors are not caught (#10407)
1 parent f5af4a9 commit c13cc92

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

FirebaseAuth/Sources/User/FIRUser.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,10 @@ - (void)reauthenticateWithProvider:(id<FIRFederatedAuthProvider>)provider
852852
[provider getCredentialWithUIDelegate:UIDelegate
853853
completion:^(FIRAuthCredential *_Nullable credential,
854854
NSError *_Nullable error) {
855+
if (error) {
856+
completion(nil, error);
857+
return;
858+
}
855859
[self reauthenticateWithCredential:credential
856860
completion:completion];
857861
}];
@@ -1335,6 +1339,10 @@ - (void)linkWithProvider:(id<FIRFederatedAuthProvider>)provider
13351339
[provider getCredentialWithUIDelegate:UIDelegate
13361340
completion:^(FIRAuthCredential *_Nullable credential,
13371341
NSError *_Nullable error) {
1342+
if (error) {
1343+
completion(nil, error);
1344+
return;
1345+
}
13381346
[self linkWithCredential:credential completion:completion];
13391347
}];
13401348
});

FirebaseAuth/Tests/Unit/FIRUserTests.m

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818
#import <OCMock/OCMock.h>
1919
#import <XCTest/XCTest.h>
2020

21+
#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h"
2122
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthTokenResult.h"
2223
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIREmailAuthProvider.h"
2324
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRFacebookAuthProvider.h"
2425
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRGoogleAuthProvider.h"
26+
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIROAuthCredential.h"
27+
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIROAuthProvider.h"
2528
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRUserInfo.h"
2629
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRUserMetadata.h"
2730

@@ -383,6 +386,21 @@
383386
*/
384387
static NSString *const kEnrolledAt = @"2022-08-01T18:31:15.426458Z";
385388

389+
/** @var kOAuthRequestURI
390+
@brief Fake OAuthRequest URI for testing.
391+
*/
392+
static NSString *const kOAuthRequestURI = @"requestURI";
393+
394+
/** @var kOAuthSessionID
395+
@brief Fake session ID for testing.
396+
*/
397+
static NSString *const kOAuthSessionID = @"sessionID";
398+
399+
/** @var kFakeWebSignInUserInteractionFailureReason
400+
@brief Fake reason for FIRAuthErrorCodeWebSignInUserInteractionFailure error while testing.
401+
*/
402+
static NSString *const kFakeWebSignInUserInteractionFailureReason = @"fake_reason";
403+
386404
/** @extention FIRSecureTokenService
387405
@brief Extends the FIRSecureTokenService class to expose one private method for testing only.
388406
*/
@@ -2643,6 +2661,134 @@ - (void)testlinkCredentialProviderAlreadyLinkedError {
26432661
}
26442662

26452663
#if TARGET_OS_IOS
2664+
/** @fn testlinkProviderFailure
2665+
@brief Tests the flow of a failed @c linkWithProvider:completion:
2666+
call.
2667+
*/
2668+
- (void)testlinkProviderFailure {
2669+
[self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
2670+
federatedID:kFacebookID
2671+
displayName:kFacebookDisplayName
2672+
profile:[[self class] googleProfile]
2673+
providerIDToken:kFacebookIDToken
2674+
providerAccessToken:kFacebookAccessToken];
2675+
2676+
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
2677+
[[FIRAuth auth] signOut:NULL];
2678+
FIRAuthCredential *facebookCredential =
2679+
[FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
2680+
[[FIRAuth auth]
2681+
signInWithCredential:facebookCredential
2682+
completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
2683+
XCTAssertTrue([NSThread isMainThread]);
2684+
[self assertUserFacebook:authResult.user];
2685+
XCTAssertEqualObjects(authResult.additionalUserInfo.profile,
2686+
[[self class] googleProfile]);
2687+
XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
2688+
XCTAssertEqualObjects(authResult.additionalUserInfo.providerID,
2689+
FIRFacebookAuthProviderID);
2690+
XCTAssertNil(error);
2691+
2692+
OCMExpect([self->_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
2693+
.andDispatchError2(
2694+
[FIRAuthErrorUtils webSignInUserInteractionFailureWithReason:
2695+
kFakeWebSignInUserInteractionFailureReason]);
2696+
id mockProvider = OCMClassMock([FIROAuthProvider class]);
2697+
OCMExpect([mockProvider getCredentialWithUIDelegate:[OCMArg any]
2698+
completion:[OCMArg any]])
2699+
.andCallBlock2(^(id<FIRAuthUIDelegate> delegate,
2700+
FIRAuthCredentialCallback callback) {
2701+
dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
2702+
FIROAuthCredential *credential =
2703+
[[FIROAuthCredential alloc] initWithProviderID:FIRGoogleAuthProviderID
2704+
sessionID:kOAuthSessionID
2705+
OAuthResponseURLString:kOAuthRequestURI];
2706+
callback(credential, nil);
2707+
});
2708+
});
2709+
2710+
[authResult.user
2711+
linkWithProvider:mockProvider
2712+
UIDelegate:nil
2713+
completion:^(FIRAuthDataResult *_Nullable result,
2714+
NSError *_Nullable error) {
2715+
XCTAssertTrue([NSThread isMainThread]);
2716+
XCTAssertEqual(error.code,
2717+
FIRAuthErrorCodeWebSignInUserInteractionFailure);
2718+
XCTAssertEqualObjects(
2719+
error.userInfo[NSLocalizedFailureReasonErrorKey],
2720+
kFakeWebSignInUserInteractionFailureReason);
2721+
[expectation fulfill];
2722+
}];
2723+
}];
2724+
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
2725+
OCMVerifyAll(_mockBackend);
2726+
}
2727+
2728+
/** @fn testReauthenticateWithProviderFailure
2729+
@brief Tests the flow of a failed @c reauthenticateWithProvider:completion: call.
2730+
*/
2731+
- (void)testReauthenticateWithProviderFailure {
2732+
[self expectVerifyAssertionRequest:FIRFacebookAuthProviderID
2733+
federatedID:kFacebookID
2734+
displayName:kFacebookDisplayName
2735+
profile:[[self class] googleProfile]
2736+
providerIDToken:kFacebookIDToken
2737+
providerAccessToken:kFacebookAccessToken];
2738+
2739+
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
2740+
[[FIRAuth auth] signOut:NULL];
2741+
FIRAuthCredential *facebookCredential =
2742+
[FIRFacebookAuthProvider credentialWithAccessToken:kFacebookAccessToken];
2743+
[[FIRAuth auth]
2744+
signInWithCredential:facebookCredential
2745+
completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
2746+
XCTAssertTrue([NSThread isMainThread]);
2747+
[self assertUserFacebook:authResult.user];
2748+
XCTAssertEqualObjects(authResult.additionalUserInfo.profile,
2749+
[[self class] googleProfile]);
2750+
XCTAssertEqualObjects(authResult.additionalUserInfo.username, kUserName);
2751+
XCTAssertEqualObjects(authResult.additionalUserInfo.providerID,
2752+
FIRFacebookAuthProviderID);
2753+
XCTAssertNil(error);
2754+
2755+
OCMExpect([self->_mockBackend verifyAssertion:[OCMArg any] callback:[OCMArg any]])
2756+
.andDispatchError2(
2757+
[FIRAuthErrorUtils webSignInUserInteractionFailureWithReason:
2758+
kFakeWebSignInUserInteractionFailureReason]);
2759+
id mockProvider = OCMClassMock([FIROAuthProvider class]);
2760+
OCMExpect([mockProvider getCredentialWithUIDelegate:[OCMArg any]
2761+
completion:[OCMArg any]])
2762+
.andCallBlock2(^(id<FIRAuthUIDelegate> delegate,
2763+
FIRAuthCredentialCallback callback) {
2764+
dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
2765+
FIROAuthCredential *credential =
2766+
[[FIROAuthCredential alloc] initWithProviderID:FIRGoogleAuthProviderID
2767+
sessionID:kOAuthSessionID
2768+
OAuthResponseURLString:kOAuthRequestURI];
2769+
callback(credential, nil);
2770+
});
2771+
});
2772+
2773+
[authResult.user
2774+
reauthenticateWithProvider:mockProvider
2775+
UIDelegate:nil
2776+
completion:^(FIRAuthDataResult *_Nullable result,
2777+
NSError *_Nullable error) {
2778+
XCTAssertTrue([NSThread isMainThread]);
2779+
XCTAssertEqual(
2780+
error.code,
2781+
FIRAuthErrorCodeWebSignInUserInteractionFailure);
2782+
XCTAssertEqualObjects(
2783+
error.userInfo[NSLocalizedFailureReasonErrorKey],
2784+
kFakeWebSignInUserInteractionFailureReason);
2785+
[expectation fulfill];
2786+
}];
2787+
}];
2788+
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
2789+
OCMVerifyAll(_mockBackend);
2790+
}
2791+
26462792
/** @fn testlinkPhoneAuthCredentialSuccess
26472793
@brief Tests the flow of a successful @c linkWithCredential:completion:
26482794
call using a phoneAuthCredential.

0 commit comments

Comments
 (0)