diff --git a/FirebaseAuth/Sources/Backend/FIRAuthBackend.m b/FirebaseAuth/Sources/Backend/FIRAuthBackend.m index bbd942caa11..304c7160d95 100644 --- a/FirebaseAuth/Sources/Backend/FIRAuthBackend.m +++ b/FirebaseAuth/Sources/Backend/FIRAuthBackend.m @@ -468,6 +468,11 @@ */ static NSString *const kUnsupportedFirstFactorErrorMessage = @"UNSUPPORTED_FIRST_FACTOR"; +/** @var kBlockingCloudFunctionErrorResponse + @brief This is the error message blocking Cloud Functions. + */ +static NSString *const kBlockingCloudFunctionErrorResponse = @"BLOCKING_FUNCTION_ERROR_RESPONSE"; + /** @var kEmailChangeNeedsVerificationErrorMessage @brief This is the error message the server will respond with if changing an unverified email. */ @@ -1447,6 +1452,11 @@ + (nullable NSError *)clientErrorWithServerErrorMessage:(NSString *)serverErrorM return [FIRAuthErrorUtils unsupportedTenantOperationError]; } + if ([shortErrorMessage isEqualToString:kBlockingCloudFunctionErrorResponse]) { + return + [FIRAuthErrorUtils blockingCloudFunctionServerResponseWithMessage:serverDetailErrorMessage]; + } + // In this case we handle an error that might be specified in the underlying errors dictionary, // the error message in determined based on the @c reason key in the dictionary. if (errorDictionary[kErrorsKey]) { diff --git a/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthErrors.h b/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthErrors.h index 95047813572..adef87cd54b 100644 --- a/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthErrors.h +++ b/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthErrors.h @@ -413,6 +413,11 @@ typedef NS_ERROR_ENUM(FIRAuthErrorDomain, FIRAuthErrorCode){ */ FIRAuthErrorCodeMissingOrInvalidNonce = 17094, + /** Raised when an Cloud Function returns a blocking error. Will include a message returned from + * the function. + */ + FIRAuthErrorCodeBlockingCloudFunctionError = 17105, + /** Indicates an error for when the client identifier is missing. */ FIRAuthErrorCodeMissingClientIdentifier = 17993, diff --git a/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h b/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h index 7bdefab7426..2c483a98168 100644 --- a/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h +++ b/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.h @@ -605,6 +605,8 @@ NS_ASSUME_NONNULL_BEGIN */ + (NSError *)unsupportedTenantOperationError; ++ (NSError *)blockingCloudFunctionServerResponseWithMessage:(nullable NSString *)message; + @end NS_ASSUME_NONNULL_END diff --git a/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m b/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m index e49324918bf..3a0037aba55 100644 --- a/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m +++ b/FirebaseAuth/Sources/Utilities/FIRAuthErrorUtils.m @@ -591,6 +591,12 @@ @"This operation is not" "supported in a multi-tenant context."; +/** @var kFIRAuthErrorMessageBlockingCloudFunctionReturnedError + @brief Message for @c FIRAuthErrorCodeBlockingCloudFunctionError error code. + */ +static NSString *const kFIRAuthErrorMessageBlockingCloudFunctionReturnedError = + @"Blocking cloud function returned an error."; + /** @var FIRAuthErrorDescription @brief The error descrioption, based on the error code. @remarks No default case so that we get a compiler warning if a new value was added to the enum. @@ -755,6 +761,8 @@ return kFIRAuthErrorMessageTenantIDMismatch; case FIRAuthErrorCodeUnsupportedTenantOperation: return kFIRAuthErrorMessageUnsupportedTenantOperation; + case FIRAuthErrorCodeBlockingCloudFunctionError: + return kFIRAuthErrorMessageBlockingCloudFunctionReturnedError; } } @@ -922,6 +930,8 @@ return @"ERROR_TENANT_ID_MISMATCH"; case FIRAuthErrorCodeUnsupportedTenantOperation: return @"ERROR_UNSUPPORTED_TENANT_OPERATION"; + case FIRAuthErrorCodeBlockingCloudFunctionError: + return @"ERROR_BLOCKING_CLOUD_FUNCTION_RETURNED_ERROR"; } } @@ -1405,6 +1415,32 @@ + (NSError *)unsupportedTenantOperationError { return [self errorWithCode:FIRAuthInternalErrorCodeUnsupportedTenantOperation]; } ++ (NSError *)blockingCloudFunctionServerResponseWithMessage:(nullable NSString *)message { + if (message == nil) { + return [self errorWithCode:FIRAuthInternalErrorBlockingCloudFunctionError message:message]; + } + + NSString *jsonString = + [message stringByReplacingOccurrencesOfString:@"HTTP Cloud Function returned an error:" + withString:@""]; + jsonString = [jsonString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSError *jsonError; + NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData + options:0 + error:&jsonError]; + + if (jsonError) { + return [self JSONSerializationErrorWithUnderlyingError:jsonError]; + } + + NSDictionary *errorDict = jsonDict[@"error"]; + NSString *errorMessage = errorDict[@"message"]; + + return [self errorWithCode:FIRAuthInternalErrorBlockingCloudFunctionError message:errorMessage]; +} + @end NS_ASSUME_NONNULL_END diff --git a/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h b/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h index d8a29707732..96046f8a33f 100644 --- a/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h +++ b/FirebaseAuth/Sources/Utilities/FIRAuthInternalErrors.h @@ -477,6 +477,11 @@ typedef NS_ENUM(NSInteger, FIRAuthInternalErrorCode) { FIRAuthInternalErrorCodeMalformedJWT = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMalformedJWT, + /** Indicates that an authentication blocking cloud function returned an error. + */ + FIRAuthInternalErrorBlockingCloudFunctionError = FIRAuthPublicErrorCodeFlag | + FIRAuthErrorCodeBlockingCloudFunctionError, + /** @var FIRAuthInternalErrorCodeRPCRequestEncodingError @brief Indicates an error encoding the RPC request. @remarks This is typically due to some sort of unexpected input value.