aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Zsika Phillip <protocol86@users.noreply.github.com>2018-04-03 17:19:51 -0700
committerGravatar GitHub <noreply@github.com>2018-04-03 17:19:51 -0700
commit6566328dc461c38c6000c64996c17883b9895d06 (patch)
tree1f072d106b95e87fbd9d163194d08c3a76977e07
parent1be9737fb28deb388cbcfaf6324ebad49683340b (diff)
Adds copy auth state API (#1018)
* Adds copy auth state API * improvements * Addresses comments
-rw-r--r--Example/Auth/Sample/MainViewController.m31
-rw-r--r--Example/Auth/Tests/FIRAuthTests.m120
-rw-r--r--Firebase/Auth/Source/FIRAuth.m46
-rw-r--r--Firebase/Auth/Source/FIRAuthErrorUtils.h7
-rw-r--r--Firebase/Auth/Source/FIRAuthErrorUtils.m19
-rw-r--r--Firebase/Auth/Source/FIRAuthInternalErrors.h6
-rw-r--r--Firebase/Auth/Source/FIRUser.m6
-rw-r--r--Firebase/Auth/Source/FIRUser_Internal.h6
-rw-r--r--Firebase/Auth/Source/Public/FIRAuth.h13
-rw-r--r--Firebase/Auth/Source/Public/FIRAuthErrors.h5
10 files changed, 252 insertions, 7 deletions
diff --git a/Example/Auth/Sample/MainViewController.m b/Example/Auth/Sample/MainViewController.m
index 18f1e02..e343508 100644
--- a/Example/Auth/Sample/MainViewController.m
+++ b/Example/Auth/Sample/MainViewController.m
@@ -429,6 +429,11 @@ static NSString *const kRemoveIDTokenListenerTitle = @"Remove Last ID Token Chan
*/
static NSString *const kSectionTitleApp = @"APP";
+/** @var kUpdateCurrentUserFromSavedTitle
+ @brief The text of the "Upgrade to saved user" button.
+ */
+static NSString *const kUpdateCurrentUserFromSavedTitle = @"Upgrade to saved user";
+
/** @var kCreateUserTitle
@brief The text of the "Create User" button.
*/
@@ -745,6 +750,9 @@ typedef enum {
}],
]],
[StaticContentTableViewSection sectionWithTitle:kSectionTitleSignIn cells:@[
+ [StaticContentTableViewCell cellWithTitle:kUpdateCurrentUserFromSavedTitle
+ value:nil
+ action:^{ [weakSelf updateToSavedUser]; }],
[StaticContentTableViewCell cellWithTitle:kCreateUserTitle
value:nil
action:^{ [weakSelf createUser]; }
@@ -2744,6 +2752,29 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}];
}
+/** @fn updateToSavedUser
+ @brief updates the current user to the saved user.
+ */
+- (void)updateToSavedUser {
+ if(![AppManager auth].currentUser) {
+ NSLog(@"You must be signed in to perform this action");
+ return;
+ }
+
+ if (!_userInMemory) {
+ NSLog(@"You need an in memory user to perform this action");
+ return;
+ }
+
+ [[AppManager auth] updateCurrentUser:_userInMemory completion:^(NSError *_Nullable error) {
+ if (error) {
+ [self showMessagePrompt:
+ [NSString stringWithFormat:@"An error Occurred: %@", error.localizedDescription]];
+ return;
+ }
+ }];
+}
+
/** @fn createUser
@brief Creates a new user.
*/
diff --git a/Example/Auth/Tests/FIRAuthTests.m b/Example/Auth/Tests/FIRAuthTests.m
index 914c58b..2e2d2c5 100644
--- a/Example/Auth/Tests/FIRAuthTests.m
+++ b/Example/Auth/Tests/FIRAuthTests.m
@@ -1773,6 +1773,111 @@ static const NSTimeInterval kWaitInterval = .5;
return actionCodeSettings;
}
+/** @fn testUpdateCurrentUserFailure
+ @brief Tests the flow of a failed @c updateCurrentUser:completion:
+ call.
+ */
+- (void)testUpdateCurrentUserFailure {
+ NSString *kTestAccessToken = @"fakeAccessToken";
+ NSString *kTestAPIKey = @"fakeAPIKey";
+ [self waitForSignInWithAccessToken:kTestAccessToken
+ APIKey:kTestAPIKey
+ completion:nil];
+ NSString *kTestAPIKey2 = @"fakeAPIKey2";
+ FIRUser *user2 = [FIRAuth auth].currentUser;
+ user2.requestConfiguration = [[FIRAuthRequestConfiguration alloc]initWithAPIKey:kTestAPIKey2];
+ OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
+ .andDispatchError2([FIRAuthErrorUtils invalidAPIKeyError]);
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] updateCurrentUser:user2 completion:^(NSError *_Nullable error) {
+ XCTAssertEqual(error.code, FIRAuthErrorCodeInvalidAPIKey);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn testUpdateCurrentUserFailureNetworkError
+ @brief Tests the flow of a failed @c updateCurrentUser:completion:
+ call with a network error.
+ */
+- (void)testUpdateCurrentUserFailureNetworkError {
+ NSString *kTestAPIKey = @"fakeAPIKey";
+ NSString *kTestAccessToken = @"fakeAccessToken";
+ [self waitForSignInWithAccessToken:kTestAccessToken
+ APIKey:kTestAPIKey
+ completion:nil];
+ NSString *kTestAPIKey2 = @"fakeAPIKey2";
+ FIRUser *user2 = [FIRAuth auth].currentUser;
+ user2.requestConfiguration = [[FIRAuthRequestConfiguration alloc]initWithAPIKey:kTestAPIKey2];
+ OCMExpect([_mockBackend getAccountInfo:[OCMArg any] callback:[OCMArg any]])
+ .andDispatchError2([FIRAuthErrorUtils networkErrorWithUnderlyingError:[NSError new]]);
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] updateCurrentUser:user2 completion:^(NSError *_Nullable error) {
+ XCTAssertEqual(error.code, FIRAuthErrorCodeNetworkError);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn testUpdateCurrentUserFailureNUllUser
+ @brief Tests the flow of a failed @c updateCurrentUser:completion:
+ call with FIRAuthErrorCodeNullUser.
+ */
+- (void)testUpdateCurrentUserFailureNUllUser {
+ NSString *kTestAccessToken = @"fakeAccessToken";
+ NSString *kTestAPIKey = @"fakeAPIKey";
+ [self waitForSignInWithAccessToken:kTestAccessToken
+ APIKey:kTestAPIKey
+ completion:nil];
+ FIRUser *fakeNilUser = nil;
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ [[FIRAuth auth] updateCurrentUser:fakeNilUser completion:^(NSError *_Nullable error) {
+ XCTAssertEqual(error.code, FIRAuthErrorCodeNullUser);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
+/** @fn testUpdateCurrentUserSuccess
+ @brief Tests the flow of a successful @c updateCurrentUser:completion:
+ call with a network error.
+ */
+- (void)testUpdateCurrentUserSuccess {
+ // Sign in with the first user.
+ [self waitForSignInWithAccessToken:kAccessToken
+ APIKey:kAPIKey
+ completion:nil];
+
+ FIRUser *user1 = [FIRAuth auth].currentUser;
+ NSString *kTestAPIKey = @"fakeAPIKey";
+ user1.requestConfiguration = [[FIRAuthRequestConfiguration alloc]initWithAPIKey:kTestAPIKey];
+ [[FIRAuth auth] signOut:nil];
+
+ NSString *kTestAccessToken2 = @"fakeAccessToken2";
+ [self waitForSignInWithAccessToken:kTestAccessToken2
+ APIKey:kAPIKey
+ completion:nil];
+ FIRUser *user2 = [FIRAuth auth].currentUser;
+
+ [self expectGetAccountInfoWithAccessToken:kAccessToken];
+
+ XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
+ // Current user should now be user2.
+ XCTAssertEqualObjects([FIRAuth auth].currentUser, user2);
+ [[FIRAuth auth] updateCurrentUser:user1 completion:^(NSError *_Nullable error) {
+ XCTAssertNil(error);
+ // Current user should now be user1.
+ XCTAssertEqualObjects([FIRAuth auth].currentUser, user1);
+ XCTAssertNotEqualObjects([FIRAuth auth].currentUser, user2);
+ [expectation fulfill];
+ }];
+ [self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
+ OCMVerifyAll(_mockBackend);
+}
+
/** @fn testSignOut
@brief Tests the @c signOut: method.
*/
@@ -1884,7 +1989,7 @@ static const NSTimeInterval kWaitInterval = .5;
// Listener should fire for signing in again as the same user with another access token.
expectation = [self expectationWithDescription:@"sign-in again"];
shouldHaveUser = YES;
- [self waitForSignInWithAccessToken:kNewAccessToken];
+ [self waitForSignInWithAccessToken:kNewAccessToken APIKey:nil completion:nil];
// Listener should fire for signing out.
expectation = [self expectationWithDescription:@"sign-out"];
@@ -2256,15 +2361,19 @@ static const NSTimeInterval kWaitInterval = .5;
@remarks This method also waits for all other pending @c XCTestExpectation instances.
*/
- (void)waitForSignIn {
- [self waitForSignInWithAccessToken:kAccessToken];
+ [self waitForSignInWithAccessToken:kAccessToken APIKey:nil completion:nil];
}
/** @fn waitForSignInWithAccessToken:
@brief Signs in a user to prepare for tests.
@param accessToken The access token for the user to have.
+ @param APIKey Optionally, The API key associated with the user.
+ @param completion Optionally, The completion invoked at the end of the flow.
@remarks This method also waits for all other pending @c XCTestExpectation instances.
*/
-- (void)waitForSignInWithAccessToken:(NSString *)accessToken {
+- (void)waitForSignInWithAccessToken:(NSString *)accessToken
+ APIKey:(nullable NSString *)APIKey
+ completion:(nullable FIRAuthResultCallback)completion {
OCMExpect([_mockBackend verifyPassword:[OCMArg any] callback:[OCMArg any]])
.andCallBlock2(^(FIRVerifyPasswordRequest *_Nullable request,
FIRVerifyPasswordResponseCallback callback) {
@@ -2281,7 +2390,12 @@ static const NSTimeInterval kWaitInterval = .5;
XCTestExpectation *expectation = [self expectationWithDescription:@"callback"];
[[FIRAuth auth] signInWithEmail:kEmail password:kFakePassword completion:^(FIRUser *_Nullable user,
NSError *_Nullable error) {
+
+ user.requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:APIKey];
[expectation fulfill];
+ if (completion) {
+ completion(user, error);
+ }
}];
[self waitForExpectationsWithTimeout:kExpectationTimeout handler:nil];
OCMVerifyAll(_mockBackend);
diff --git a/Firebase/Auth/Source/FIRAuth.m b/Firebase/Auth/Source/FIRAuth.m
index dc3154f..d4ced9c 100644
--- a/Firebase/Auth/Source/FIRAuth.m
+++ b/Firebase/Auth/Source/FIRAuth.m
@@ -1137,6 +1137,52 @@ static NSMutableDictionary *gKeychainServiceNameForAppName;
});
}
+- (void)updateCurrentUser:(FIRUser *)user completion:(nullable FIRUserUpdateCallback)completion {
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^{
+ if (!user) {
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion([FIRAuthErrorUtils nullUserErrorWithMessage:nil]);
+ });
+ }
+ return;
+ }
+ void (^updateUserBlock)(FIRUser *user) = ^(FIRUser *user) {
+ NSError *error;
+ [self updateCurrentUser:user byForce:YES savingToDisk:YES error:(&error)];
+ if (error) {
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(error);
+ });
+ }
+ return;
+ } if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(nil);
+ });
+ }
+ };
+ if (![user.requestConfiguration.APIKey isEqualToString:self->_requestConfiguration.APIKey]) {
+ // If the API keys are different, then we need to confirm that the user belongs to the same
+ // project before proceeding.
+ user.requestConfiguration = self->_requestConfiguration;
+ [user reloadWithCompletion:^(NSError *_Nullable error) {
+ if (error) {
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(error);
+ });
+ }
+ return;
+ }
+ updateUserBlock(user);
+ }];
+ } else {
+ updateUserBlock(user);
+ }
+ });
+}
- (BOOL)signOut:(NSError *_Nullable __autoreleasing *_Nullable)error {
__block BOOL result = YES;
diff --git a/Firebase/Auth/Source/FIRAuthErrorUtils.h b/Firebase/Auth/Source/FIRAuthErrorUtils.h
index c3fad0d..5b8205f 100644
--- a/Firebase/Auth/Source/FIRAuthErrorUtils.h
+++ b/Firebase/Auth/Source/FIRAuthErrorUtils.h
@@ -481,6 +481,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (NSError *)URLResponseErrorWithCode:(NSString *)code message:(nullable NSString *)message;
+/** @fn nullUserErrorWithMessage:
+ @brief Constructs an @c NSError with the code and message provided.
+ @param message Error message from the backend, if any.
+ @return The nullable NSError instance associated with the given error message, if one is found.
+ */
++ (NSError *)nullUserErrorWithMessage:(nullable NSString *)message;
+
/** @fn keychainErrorWithFunction:status:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeKeychainError code.
@param keychainFunction The keychain function which was invoked and yielded an unexpected
diff --git a/Firebase/Auth/Source/FIRAuthErrorUtils.m b/Firebase/Auth/Source/FIRAuthErrorUtils.m
index 3748048..f4dbb94 100644
--- a/Firebase/Auth/Source/FIRAuthErrorUtils.m
+++ b/Firebase/Auth/Source/FIRAuthErrorUtils.m
@@ -139,8 +139,9 @@ static NSString *const kFIRAuthErrorMessageNoSuchProvider = @"User was not linke
/** @var kFIRAuthErrorMessageInvalidUserToken
@brief Message for @c FIRAuthErrorCodeInvalidUserToken error code.
*/
-static NSString *const kFIRAuthErrorMessageInvalidUserToken = @"The user's credential is no longer "
- "valid. The user must sign in again.";
+static NSString *const kFIRAuthErrorMessageInvalidUserToken = @"This user's credential isn't valid "
+ "for this project. This can happen if the user's token has been tampered with, or if the user "
+ "doesn’t belong to the project associated with the API key used in your request.";
/** @var kFIRAuthErrorMessageNetworkError
@brief Message for @c FIRAuthErrorCodeNetworkError error code.
@@ -400,6 +401,12 @@ static NSString *const kFIRAuthErrorMessageWebInternalError = @"An internal erro
static NSString *const kFIRAuthErrorMessageAppVerificationUserInteractionFailure = @"The app "
"verification process has failed, print and inspect the error details for more information";
+/** @var kFIRAuthErrorMessageNullUser
+ @brief Message for @c FIRAuthErrorCodeNullUser error code.
+ */
+static NSString *const kFIRAuthErrorMessageNullUser = @"A null user object was provided as the "
+ "argument for an operation which requires a non-null user object.";
+
/** @var kFIRAuthErrorMessageInternalError
@brief Message for @c FIRAuthErrorCodeInternalError error code.
*/
@@ -520,6 +527,8 @@ static NSString *FIRAuthErrorDescription(FIRAuthErrorCode code) {
return kFIRAuthErrorMessageAppVerificationUserInteractionFailure;
case FIRAuthErrorCodeWebNetworkRequestFailed:
return kFIRAuthErrorMessageWebRequestFailed;
+ case FIRAuthErrorCodeNullUser:
+ return kFIRAuthErrorMessageNullUser;
case FIRAuthErrorCodeWebInternalError:
return kFIRAuthErrorMessageWebInternalError;
}
@@ -639,6 +648,8 @@ static NSString *const FIRAuthErrorCodeString(FIRAuthErrorCode code) {
return @"ERROR_APP_VERIFICATION_FAILED";
case FIRAuthErrorCodeWebNetworkRequestFailed:
return @"ERROR_WEB_NETWORK_REQUEST_FAILED";
+ case FIRAuthErrorCodeNullUser:
+ return @"ERROR_NULL_USER";
case FIRAuthErrorCodeWebInternalError:
return @"ERROR_WEB_INTERNAL_ERROR";
}
@@ -981,6 +992,10 @@ static NSString *const FIRAuthErrorCodeString(FIRAuthErrorCode code) {
return nil;
}
++ (NSError *)nullUserErrorWithMessage:(nullable NSString *)message {
+ return [self errorWithCode:FIRAuthInternalErrorCodeNullUser message:message];
+}
+
+ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status {
NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status];
return [self errorWithCode:FIRAuthInternalErrorCodeKeychainError userInfo:@{
diff --git a/Firebase/Auth/Source/FIRAuthInternalErrors.h b/Firebase/Auth/Source/FIRAuthInternalErrors.h
index d2905cc..fd08022 100644
--- a/Firebase/Auth/Source/FIRAuthInternalErrors.h
+++ b/Firebase/Auth/Source/FIRAuthInternalErrors.h
@@ -370,6 +370,12 @@ typedef NS_ENUM(NSInteger, FIRAuthInternalErrorCode) {
FIRAuthInternalErrorCodeAppNotVerified =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAppNotVerified,
+ /** Indicates that a non-null user was expected as an argmument to the operation but a null
+ user was provided.
+ */
+ FIRAuthInternalErrorCodeNullUser =
+ FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNullUser,
+
/** @var FIRAuthInternalErrorCodeRPCRequestEncodingError
@brief Indicates an error encoding the RPC request.
@remarks This is typically due to some sort of unexpected input value.
diff --git a/Firebase/Auth/Source/FIRUser.m b/Firebase/Auth/Source/FIRUser.m
index fc7930f..1b10976 100644
--- a/Firebase/Auth/Source/FIRUser.m
+++ b/Firebase/Auth/Source/FIRUser.m
@@ -251,6 +251,7 @@ static void callInMainThreadWithAuthDataResultAndError(
refreshToken:refreshToken];
FIRUser *user = [[self alloc] initWithTokenService:tokenService];
user.auth = auth;
+ user.requestConfiguration = auth.requestConfiguration;
[user internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) {
if (error) {
callback(nil, error);
@@ -316,6 +317,8 @@ static void callInMainThreadWithAuthDataResultAndError(
[aDecoder decodeObjectOfClass:[FIRSecureTokenService class] forKey:kTokenServiceCodingKey];
FIRUserMetadata *metadata =
[aDecoder decodeObjectOfClass:[FIRUserMetadata class] forKey:kMetadataCodingKey];
+ NSString *APIKey =
+ [aDecoder decodeObjectOfClass:[FIRUserMetadata class] forKey:kAPIKeyCodingKey];
if (!userID || !tokenService) {
return nil;
}
@@ -334,6 +337,7 @@ static void callInMainThreadWithAuthDataResultAndError(
_providerData = providerData;
_phoneNumber = phoneNumber;
_metadata = metadata ?: [[FIRUserMetadata alloc] initWithCreationDate:nil lastSignInDate:nil];
+ _requestConfiguration = [[FIRAuthRequestConfiguration alloc] initWithAPIKey:APIKey];
}
return self;
}
@@ -349,8 +353,6 @@ static void callInMainThreadWithAuthDataResultAndError(
[aCoder encodeObject:_photoURL forKey:kPhotoURLCodingKey];
[aCoder encodeObject:_displayName forKey:kDisplayNameCodingKey];
[aCoder encodeObject:_metadata forKey:kMetadataCodingKey];
- // The API key is encoded even it is not used in decoding to be compatible with previous versions
- // of the library.
[aCoder encodeObject:_auth.requestConfiguration.APIKey forKey:kAPIKeyCodingKey];
[aCoder encodeObject:_tokenService forKey:kTokenServiceCodingKey];
}
diff --git a/Firebase/Auth/Source/FIRUser_Internal.h b/Firebase/Auth/Source/FIRUser_Internal.h
index 9a069bb..4f89c00 100644
--- a/Firebase/Auth/Source/FIRUser_Internal.h
+++ b/Firebase/Auth/Source/FIRUser_Internal.h
@@ -17,6 +17,7 @@
#import "FIRUser.h"
@class FIRAuth;
+@class FIRAuthRequestConfiguration;
NS_ASSUME_NONNULL_BEGIN
@@ -42,6 +43,11 @@ typedef void(^FIRRetrieveUserCallback)(FIRUser *_Nullable user, NSError *_Nullab
*/
@property(nonatomic, weak) FIRAuth *auth;
+/** @property auth
+ @brief A strong reference to a requestConfiguration instance associated with this user instance.
+ */
+@property(nonatomic, strong) FIRAuthRequestConfiguration *requestConfiguration;
+
/** @var accessTokenExpirationDate
@brief The expiration date of the cached access token.
*/
diff --git a/Firebase/Auth/Source/Public/FIRAuth.h b/Firebase/Auth/Source/Public/FIRAuth.h
index aefba57..7d5ea42 100644
--- a/Firebase/Auth/Source/Public/FIRAuth.h
+++ b/Firebase/Auth/Source/Public/FIRAuth.h
@@ -32,6 +32,11 @@
NS_ASSUME_NONNULL_BEGIN
+/** @typedef FIRUserUpdateCallback
+ @brief The type of block invoked when a request to update a current user is completed.
+ */
+typedef void (^FIRUserUpdateCallback)(NSError *_Nullable error) NS_SWIFT_NAME(UserUpdateCallback);
+
/** @typedef FIRAuthStateDidChangeListenerHandle
@brief The type of handle returned by `FIRAuth.addAuthStateDidChangeListener:`.
*/
@@ -297,6 +302,14 @@ NS_SWIFT_NAME(Auth)
*/
- (instancetype)init NS_UNAVAILABLE;
+/** @fn updateCurrentUser:completion:
+ @brief Sets the currentUser on the calling Auth instance to the provided user object.
+ @param user The user object to be set as the current user of the calling Auth instance.
+ @param completion Optionally; a block invoked after the user of the calling Auth instance has
+ been updated or an error was encountered.
+ */
+- (void)updateCurrentUser:(FIRUser *)user completion:(nullable FIRUserUpdateCallback)completion;
+
/** @fn fetchProvidersForEmail:completion:
@brief Fetches the list of IdPs that can be used for signing in with the provided email address.
Useful for an "identifier-first" sign-in flow.
diff --git a/Firebase/Auth/Source/Public/FIRAuthErrors.h b/Firebase/Auth/Source/Public/FIRAuthErrors.h
index b8e5fb6..4a1a6f1 100644
--- a/Firebase/Auth/Source/Public/FIRAuthErrors.h
+++ b/Firebase/Auth/Source/Public/FIRAuthErrors.h
@@ -299,6 +299,11 @@ typedef NS_ENUM(NSInteger, FIRAuthErrorCode) {
*/
FIRAuthErrorCodeWebInternalError = 17062,
+ /** Indicates that a non-null user was expected as an argmument to the operation but a null
+ user was provided.
+ */
+ FIRAuthErrorCodeNullUser = 17067,
+
/** Indicates an error occurred while attempting to access the keychain.
*/
FIRAuthErrorCodeKeychainError = 17995,