Skip to content

Commit 6673e7c

Browse files
author
renkelvin
authored
Use sign up endpoint for link with email password (resubmit #11925) (#12009)
1 parent 86ef7d8 commit 6673e7c

File tree

11 files changed

+223
-77
lines changed

11 files changed

+223
-77
lines changed

FirebaseAuth/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# 10.18.0
2+
- [fixed] Fix a bug where anonymous account can't be linked with email password credential. (#11911)
3+
14
# 10.16.0
25
- [added] Added custom auth domain support in recaptcha v2 authentication flows. (#7553)
36

FirebaseAuth/Sources/Auth/FIRAuth.m

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#import "FirebaseAuth/Sources/AuthProvider/FIRAuthCredential_Internal.h"
3636
#import "FirebaseAuth/Sources/AuthProvider/GameCenter/FIRGameCenterAuthCredential.h"
3737
#import "FirebaseAuth/Sources/AuthProvider/OAuth/FIROAuthCredential_Internal.h"
38-
#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h"
3938
#import "FirebaseAuth/Sources/Backend/FIRAuthRequestConfiguration.h"
4039
#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIRequest.h"
4140
#import "FirebaseAuth/Sources/Backend/RPC/FIRCreateAuthURIResponse.h"
@@ -165,11 +164,6 @@
165164
*/
166165
static NSString *const kRevertSecondFactorAdditionRequestType = @"REVERT_SECOND_FACTOR_ADDITION";
167166

168-
/** @var kMissingRecaptchaTokenErrorPrefix
169-
@brief The prefix of the error message of missing recaptcha token during authenticating.
170-
*/
171-
static NSString *const kMissingRecaptchaTokenErrorPrefix = @"MISSING_RECAPTCHA_TOKEN";
172-
173167
/** @var kMissingPasswordReason
174168
@brief The reason why the @c FIRAuthErrorCodeWeakPassword error is thrown.
175169
@remarks This error message will be localized in the future.
@@ -1994,6 +1988,7 @@ - (void)internalCreateUserWithEmail:(NSString *)email
19941988
[[FIRSignUpNewUserRequest alloc] initWithEmail:email
19951989
password:password
19961990
displayName:nil
1991+
idToken:nil
19971992
requestConfiguration:_requestConfiguration];
19981993
if (![request.password length]) {
19991994
completion(

FirebaseAuth/Sources/Auth/FIRAuth_Internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#import <Foundation/Foundation.h>
1818
#import "FirebaseAuth/Interop/FIRAuthInterop.h"
19+
#import "FirebaseAuth/Sources/Backend/FIRAuthBackend.h"
1920
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuth.h"
2021
#import "FirebaseCore/Extension/FIRLogger.h"
2122

FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ NS_ASSUME_NONNULL_BEGIN
3838
*/
3939
@property(nonatomic, copy, nullable) NSString *displayName;
4040

41+
/** @property idToken
42+
@brief The idToken of the user.
43+
*/
44+
@property(nonatomic, copy, nullable) NSString *idToken;
45+
4146
/** @property captchaResponse
4247
@brief Response to the captcha.
4348
*/
@@ -74,6 +79,7 @@ NS_ASSUME_NONNULL_BEGIN
7479
- (nullable instancetype)initWithEmail:(nullable NSString *)email
7580
password:(nullable NSString *)password
7681
displayName:(nullable NSString *)displayName
82+
idToken:(nullable NSString *)idToken
7783
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
7884
NS_DESIGNATED_INITIALIZER;
7985

FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
*/
3939
static NSString *const kDisplayNameKey = @"displayName";
4040

41+
/** @var kIDToken
42+
@brief The key for the "kIDToken" value in the request.
43+
*/
44+
static NSString *const kIDToken = @"idToken";
45+
4146
/** @var kCaptchaResponseKey
4247
@brief The key for the "captchaResponse" value in the request.
4348
*/
@@ -68,12 +73,14 @@ @implementation FIRSignUpNewUserRequest
6873
- (nullable instancetype)initWithEmail:(nullable NSString *)email
6974
password:(nullable NSString *)password
7075
displayName:(nullable NSString *)displayName
76+
idToken:(nullable NSString *)idToken
7177
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration {
7278
self = [super initWithEndpoint:kSignupNewUserEndpoint requestConfiguration:requestConfiguration];
7379
if (self) {
7480
_email = [email copy];
7581
_password = [password copy];
7682
_displayName = [displayName copy];
83+
_idToken = [idToken copy];
7784
_returnSecureToken = YES;
7885
}
7986
return self;
@@ -84,6 +91,7 @@ - (nullable instancetype)initWithRequestConfiguration:
8491
self = [self initWithEmail:nil
8592
password:nil
8693
displayName:nil
94+
idToken:nil
8795
requestConfiguration:requestConfiguration];
8896
return self;
8997
}
@@ -99,6 +107,9 @@ - (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)
99107
if (_displayName) {
100108
postBody[kDisplayNameKey] = _displayName;
101109
}
110+
if (_idToken) {
111+
postBody[kIDToken] = _idToken;
112+
}
102113
if (_captchaResponse) {
103114
postBody[kCaptchaResponseKey] = _captchaResponse;
104115
}

FirebaseAuth/Sources/User/FIRUser.m

Lines changed: 110 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#import "FirebaseAuth/Sources/Backend/RPC/FIRSetAccountInfoResponse.h"
4444
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterRequest.h"
4545
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignInWithGameCenterResponse.h"
46+
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserRequest.h"
47+
#import "FirebaseAuth/Sources/Backend/RPC/FIRSignUpNewUserResponse.h"
4648
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionRequest.h"
4749
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyAssertionResponse.h"
4850
#import "FirebaseAuth/Sources/Backend/RPC/FIRVerifyCustomTokenRequest.h"
@@ -61,9 +63,9 @@
6163
#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h"
6264

6365
#if TARGET_OS_IOS
64-
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRPhoneAuthProvider.h"
65-
6666
#import "FirebaseAuth/Sources/AuthProvider/Phone/FIRPhoneAuthCredential_Internal.h"
67+
#import "FirebaseAuth/Sources/Public/FirebaseAuth/FIRPhoneAuthProvider.h"
68+
#import "FirebaseAuth/Sources/Utilities/FIRAuthRecaptchaVerifier.h"
6769
#endif
6870

6971
NS_ASSUME_NONNULL_BEGIN
@@ -582,7 +584,6 @@ - (void)setTokenService:(FIRSecureTokenService *)tokenService
582584
}
583585

584586
#pragma mark -
585-
586587
/** @fn updateEmail:password:callback:
587588
@brief Updates email address and/or password for the current user.
588589
@remarks May fail if there is already an email/password-based account for the same email
@@ -1079,6 +1080,109 @@ - (void)internalVerifyBeforeUpdateEmailWithNewEmail:(NSString *)newEmail
10791080
});
10801081
}
10811082

1083+
- (void)linkWithEmailPassword:(FIREmailPasswordAuthCredential *)credential
1084+
authResult:(FIRAuthDataResult *)authResult
1085+
completion:(nullable FIRAuthDataResultCallback)completion {
1086+
[self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) {
1087+
FIRAuthRequestConfiguration *requestConfiguration = self.auth.requestConfiguration;
1088+
FIRSignUpNewUserRequest *request =
1089+
[[FIRSignUpNewUserRequest alloc] initWithEmail:credential.email
1090+
password:credential.password
1091+
displayName:nil
1092+
idToken:accessToken
1093+
requestConfiguration:requestConfiguration];
1094+
FIRSignupNewUserCallback signUpNewUserCallback = ^(FIRSignUpNewUserResponse *_Nullable response,
1095+
NSError *_Nullable error) {
1096+
if (error) {
1097+
[self signOutIfTokenIsInvalidWithError:error];
1098+
callInMainThreadWithAuthDataResultAndError(completion, nil, error);
1099+
} else {
1100+
// Update the new token and refresh user info again.
1101+
self->_tokenService = [[FIRSecureTokenService alloc]
1102+
initWithRequestConfiguration:requestConfiguration
1103+
accessToken:response.IDToken
1104+
accessTokenExpirationDate:response.approximateExpirationDate
1105+
refreshToken:response.refreshToken];
1106+
1107+
[self internalGetTokenWithCallback:^(NSString *_Nullable accessToken,
1108+
NSError *_Nullable error) {
1109+
if (error) {
1110+
callInMainThreadWithAuthDataResultAndError(completion, nil, error);
1111+
return;
1112+
}
1113+
FIRGetAccountInfoRequest *getAccountInfoRequest =
1114+
[[FIRGetAccountInfoRequest alloc] initWithAccessToken:accessToken
1115+
requestConfiguration:requestConfiguration];
1116+
[FIRAuthBackend
1117+
getAccountInfo:getAccountInfoRequest
1118+
callback:^(FIRGetAccountInfoResponse *_Nullable response,
1119+
NSError *_Nullable error) {
1120+
if (error) {
1121+
[self signOutIfTokenIsInvalidWithError:error];
1122+
callInMainThreadWithAuthDataResultAndError(completion, nil, error);
1123+
return;
1124+
}
1125+
self.anonymous = NO;
1126+
[self updateWithGetAccountInfoResponse:response];
1127+
NSError *keychainError;
1128+
if (![self updateKeychain:&keychainError]) {
1129+
callInMainThreadWithAuthDataResultAndError(completion, nil, keychainError);
1130+
return;
1131+
}
1132+
[self signOutIfTokenIsInvalidWithError:error];
1133+
callInMainThreadWithAuthDataResultAndError(completion, authResult, nil);
1134+
}];
1135+
}];
1136+
}
1137+
};
1138+
1139+
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST && (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION)
1140+
if ([[FIRAuthRecaptchaVerifier sharedRecaptchaVerifier:self.auth]
1141+
enablementStatusForProvider:FIRAuthRecaptchaProviderPassword]) {
1142+
[[FIRAuthRecaptchaVerifier sharedRecaptchaVerifier:self.auth]
1143+
injectRecaptchaFields:request
1144+
provider:FIRAuthRecaptchaProviderPassword
1145+
action:FIRAuthRecaptchaActionSignUpPassword
1146+
completion:^(
1147+
FIRIdentityToolkitRequest<FIRAuthRPCRequest> *requestWithRecaptchaToken) {
1148+
[FIRAuthBackend
1149+
signUpNewUser:(FIRSignUpNewUserRequest *)requestWithRecaptchaToken
1150+
callback:signUpNewUserCallback];
1151+
}];
1152+
} else {
1153+
[FIRAuthBackend
1154+
signUpNewUser:request
1155+
callback:^(FIRSignUpNewUserResponse *_Nullable response, NSError *_Nullable error) {
1156+
if (!error) {
1157+
signUpNewUserCallback(response, nil);
1158+
return;
1159+
}
1160+
NSError *underlyingError = [error.userInfo objectForKey:NSUnderlyingErrorKey];
1161+
if (error.code == FIRAuthErrorCodeInternalError &&
1162+
[[underlyingError.userInfo
1163+
objectForKey:FIRAuthErrorUserInfoDeserializedResponseKey][@"message"]
1164+
hasPrefix:kMissingRecaptchaTokenErrorPrefix]) {
1165+
[[FIRAuthRecaptchaVerifier sharedRecaptchaVerifier:self.auth]
1166+
injectRecaptchaFields:request
1167+
provider:FIRAuthRecaptchaProviderPassword
1168+
action:FIRAuthRecaptchaActionSignUpPassword
1169+
completion:^(FIRIdentityToolkitRequest<FIRAuthRPCRequest>
1170+
*requestWithRecaptchaToken) {
1171+
[FIRAuthBackend signUpNewUser:(FIRSignUpNewUserRequest *)
1172+
requestWithRecaptchaToken
1173+
callback:signUpNewUserCallback];
1174+
}];
1175+
} else {
1176+
signUpNewUserCallback(nil, error);
1177+
}
1178+
}];
1179+
}
1180+
#else
1181+
[FIRAuthBackend signUpNewUser:request callback:signUpNewUserCallback];
1182+
#endif
1183+
}];
1184+
}
1185+
10821186
- (void)linkWithCredential:(FIRAuthCredential *)credential
10831187
completion:(nullable FIRAuthDataResultCallback)completion {
10841188
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
@@ -1098,15 +1202,9 @@ - (void)linkWithCredential:(FIRAuthCredential *)credential
10981202
FIREmailPasswordAuthCredential *emailPasswordCredential =
10991203
(FIREmailPasswordAuthCredential *)credential;
11001204
if (emailPasswordCredential.password) {
1101-
[self updateEmail:emailPasswordCredential.email
1102-
password:emailPasswordCredential.password
1103-
callback:^(NSError *error) {
1104-
if (error) {
1105-
callInMainThreadWithAuthDataResultAndError(completion, nil, error);
1106-
} else {
1107-
callInMainThreadWithAuthDataResultAndError(completion, result, nil);
1108-
}
1109-
}];
1205+
[self linkWithEmailPassword:emailPasswordCredential
1206+
authResult:result
1207+
completion:completion];
11101208
} else {
11111209
[self internalGetTokenWithCallback:^(NSString *_Nullable accessToken,
11121210
NSError *_Nullable error) {

FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323

2424
NS_ASSUME_NONNULL_BEGIN
2525

26+
/** @var kMissingRecaptchaTokenErrorPrefix
27+
@brief The prefix of the error message of missing recaptcha token during authenticating.
28+
*/
29+
static NSString *const kMissingRecaptchaTokenErrorPrefix = @"MISSING_RECAPTCHA_TOKEN";
30+
2631
/** @class FIRAuthErrorUtils
2732
@brief Utility class used to construct @c NSError instances.
2833
*/

FirebaseAuth/Tests/Unit/FIRAuthTests.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@
138138
*/
139139
static NSString *const kDisplayName = @"User Doe";
140140

141+
/** @var kIDToken
142+
@brief The fake id token.
143+
*/
144+
static NSString *const kIDToken = @"IDToken";
145+
141146
/** @var kFakeGivenName
142147
@brief The fake user given name.
143148
*/
@@ -1818,6 +1823,7 @@ - (void)testCreateUserWithEmailPasswordWithRecaptchaVerificationSuccess {
18181823
[[FIRSignUpNewUserRequest alloc] initWithEmail:kEmail
18191824
password:kFakePassword
18201825
displayName:kDisplayName
1826+
idToken:kIDToken
18211827
requestConfiguration:[FIRAuth auth].requestConfiguration];
18221828
[constRequestWithRecaptchaToken injectRecaptchaFields:kFakeRecaptchaResponse
18231829
recaptchaVersion:kFakeRecaptchaVersion];
@@ -1867,6 +1873,7 @@ - (void)testCreateUserWithEmailPasswordWithRecaptchaFallbackSuccess {
18671873
[[FIRSignUpNewUserRequest alloc] initWithEmail:kEmail
18681874
password:kFakePassword
18691875
displayName:kDisplayName
1876+
idToken:kIDToken
18701877
requestConfiguration:[FIRAuth auth].requestConfiguration];
18711878
[constRequestWithRecaptchaToken injectRecaptchaFields:kFakeRecaptchaResponse
18721879
recaptchaVersion:kFakeRecaptchaVersion];

FirebaseAuth/Tests/Unit/FIRSignUpNewUserRequestTests.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@
6060
*/
6161
static NSString *const kTestDisplayName = @"DisplayName";
6262

63+
/** @var kIDTokenKey
64+
@brief the name of the "kIDTokenKey" property in the request.
65+
*/
66+
static NSString *const kIDTokenKey = @"idToken";
67+
68+
/** @var kTestIDToken
69+
@brief Testing id token.
70+
*/
71+
static NSString *const kTestIDToken = @"testIDToken";
72+
6373
/** @var kPasswordKey
6474
@brief the name of the "password" property in the request.
6575
*/
@@ -167,6 +177,7 @@ - (void)testSignUpNewUserRequestNotAnonymous {
167177
[[FIRSignUpNewUserRequest alloc] initWithEmail:kTestEmail
168178
password:kTestPassword
169179
displayName:kTestDisplayName
180+
idToken:kTestIDToken
170181
requestConfiguration:_requestConfiguration];
171182
[FIRAuthBackend
172183
signUpNewUser:request
@@ -190,6 +201,7 @@ - (void)testSignUpNewUserRequestOptionalFields {
190201
[[FIRSignUpNewUserRequest alloc] initWithEmail:kTestEmail
191202
password:kTestPassword
192203
displayName:kTestDisplayName
204+
idToken:kTestIDToken
193205
requestConfiguration:_requestConfiguration];
194206
request.captchaResponse = kTestCaptchaResponse;
195207
request.clientType = kTestClientType;

FirebaseAuth/Tests/Unit/FIRSignUpNewUserResponseTests.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ - (void)testSuccessfulSignUp {
159159
[[FIRSignUpNewUserRequest alloc] initWithEmail:kTestEmail
160160
password:kTestPassword
161161
displayName:kTestDisplayName
162+
idToken:kTestIDToken
162163
requestConfiguration:_requestConfiguration];
163164

164165
__block BOOL callbackInvoked;

0 commit comments

Comments
 (0)