Skip to content

Adds reCAPTCHA Token #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 1 addition & 17 deletions Example/Auth/Tests/FIRAuthBackendRPCImplementationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -747,23 +747,7 @@ - (void)testCaptchaCheckFailedResponse {

XCTAssertNotNil(callbackError);
XCTAssertEqualObjects(callbackError.domain, FIRAuthErrorDomain);
XCTAssertEqual(callbackError.code, FIRAuthErrorCodeInternalError);

NSError *underlyingError = callbackError.userInfo[NSUnderlyingErrorKey];
XCTAssertNotNil(underlyingError);
XCTAssertEqualObjects(underlyingError.domain, FIRAuthInternalErrorDomain);
XCTAssertEqual(underlyingError.code, FIRAuthInternalErrorCodeUnexpectedErrorResponse);

NSError *underlyingUnderlyingError = underlyingError.userInfo[NSUnderlyingErrorKey];
XCTAssertNil(underlyingUnderlyingError);

id deserializedResponse = underlyingError.userInfo[FIRAuthErrorUserInfoDeserializedResponseKey];
XCTAssertNotNil(deserializedResponse);
XCTAssert([deserializedResponse isKindOfClass:[NSDictionary class]]);
XCTAssertNotNil(deserializedResponse[@"message"]);

id dataResponse = underlyingError.userInfo[FIRAuthErrorUserInfoDataKey];
XCTAssertNil(dataResponse);
XCTAssertEqual(callbackError.code, FIRAuthErrorCodeCaptchaCheckFailed);
}

/** @fn testCaptchaRequiredInvalidPasswordResponse
Expand Down
7 changes: 7 additions & 0 deletions Example/Auth/Tests/FIRSendVerificationCodeRequestTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
*/
static NSString *const kTestReceipt = @"receipt";

/** @var kTestReCAPTCHAToken
@brief Fake reCAPTCHA token used for testing.
*/
static NSString *const kTestReCAPTCHAToken = @"reCAPTCHAToken";

/** @var kPhoneNumberKey
@brief The key for the "phone number" value in the request.
*/
Expand Down Expand Up @@ -101,10 +106,12 @@ - (void)testSendVerificationCodeRequest {
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:kTestPhoneNumber
appCredential:credential
reCAPTCHAToken:kTestReCAPTCHAToken
requestConfiguration:requestConfiguration];
XCTAssertEqualObjects(request.phoneNumber, kTestPhoneNumber);
XCTAssertEqualObjects(request.appCredential.receipt, kTestReceipt);
XCTAssertEqualObjects(request.appCredential.secret, kTestSecret);
XCTAssertEqualObjects(request.reCAPTCHAToken, kTestReCAPTCHAToken);

[FIRAuthBackend sendVerificationCode:request
callback:^(FIRSendVerificationCodeResponse *_Nullable response,
Expand Down
45 changes: 45 additions & 0 deletions Example/Auth/Tests/FIRSendVerificationCodeResponseTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
*/
static NSString *const kTestReceipt = @"receipt";

/** @var kTestReCAPTCHAToken
@brief Fake reCAPTCHA token used for testing.
*/
static NSString *const kTestReCAPTCHAToken = @"reCAPTCHAToken";

/** @var kInvalidPhoneNumberErrorMessage
@brief This is the error message the server will respond with if an incorrectly formatted phone
number is provided.
Expand All @@ -77,6 +82,12 @@
*/
static NSString *const kAppNotVerifiedErrorMessage = @"APP_NOT_VERIFIED";

/** @var kCaptchaCheckFailedErrorMessage
@brief This is the error message the server will respond with if the reCAPTCHA token provided is
invalid.
*/
static NSString *const kCaptchaCheckFailedErrorMessage = @"CAPTCHA_CHECK_FAILED";

/** @class FIRSendVerificationCodeResponseTests
@brief Tests for @c FIRSendVerificationCodeResponseTests.
*/
Expand Down Expand Up @@ -120,6 +131,7 @@ - (void)testSendVerificationCodeResponseInvalidPhoneNumber {
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:kTestInvalidPhoneNumber
appCredential:credential
reCAPTCHAToken:nil
requestConfiguration:_requestConfiguration];
__block BOOL callbackInvoked;
__block FIRSendVerificationCodeResponse *RPCResponse;
Expand Down Expand Up @@ -148,6 +160,7 @@ - (void)testSendVerificationCodeResponseQuotaExceededError {
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:kTestPhoneNumber
appCredential:credential
reCAPTCHAToken:nil
requestConfiguration:_requestConfiguration];
__block BOOL callbackInvoked;
__block FIRSendVerificationCodeResponse *RPCResponse;
Expand Down Expand Up @@ -177,6 +190,7 @@ - (void)testSendVerificationCodeResponseAppNotVerifiedError {
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:kTestPhoneNumber
appCredential:credential
reCAPTCHAToken:nil
requestConfiguration:_requestConfiguration];
__block BOOL callbackInvoked;
__block FIRSendVerificationCodeResponse *RPCResponse;
Expand All @@ -196,6 +210,36 @@ - (void)testSendVerificationCodeResponseAppNotVerifiedError {
XCTAssertEqual(RPCError.code, FIRAuthErrorCodeAppNotVerified);
}

/** @fn testSendVerificationCodeResponseCaptchaCheckFailedError
@brief Tests a failed attempt to send a verification code due to an invalid reCAPTCHA token
being provided in the request.
*/
- (void)testSendVerificationCodeResponseCaptchaCheckFailedError {
FIRAuthAppCredential *credential =
[[FIRAuthAppCredential alloc]initWithReceipt:kTestReceipt secret:kTestSecret];
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:kTestPhoneNumber
appCredential:credential
reCAPTCHAToken:kTestReCAPTCHAToken
requestConfiguration:_requestConfiguration];
__block BOOL callbackInvoked;
__block FIRSendVerificationCodeResponse *RPCResponse;
__block NSError *RPCError;
[FIRAuthBackend sendVerificationCode:request
callback:^(FIRSendVerificationCodeResponse *_Nullable response,
NSError *_Nullable error) {
RPCResponse = response;
RPCError = error;
callbackInvoked = YES;
}];

[_RPCIssuer respondWithServerErrorMessage:kCaptchaCheckFailedErrorMessage];

XCTAssert(callbackInvoked);
XCTAssertNil(RPCResponse);
XCTAssertEqual(RPCError.code, FIRAuthErrorCodeCaptchaCheckFailed);
}

/** @fn testSuccessfulSendVerificationCodeResponse
@brief Tests a succesful to send a verification code.
*/
Expand All @@ -205,6 +249,7 @@ - (void)testSuccessfulSendVerificationCodeResponse {
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:kTestPhoneNumber
appCredential:credential
reCAPTCHAToken:nil
requestConfiguration:_requestConfiguration];
__block BOOL callbackInvoked;
__block FIRSendVerificationCodeResponse *RPCResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ - (void)verifyClientAndSendVerificationCodeToPhoneNumber:(NSString *)phoneNumber
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber
appCredential:appCredential
reCAPTCHAToken:nil
requestConfiguration:_auth.requestConfiguration];
[FIRAuthBackend sendVerificationCode:request
callback:^(FIRSendVerificationCodeResponse *_Nullable response,
Expand Down
7 changes: 7 additions & 0 deletions Firebase/Auth/Source/FIRAuthErrorUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (NSError *)appNotVerifiedErrorWithMessage:(nullable NSString *)message;

/** @fn captchaCheckFailedErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCaptchaCheckFailed code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)captchaCheckFailedErrorWithMessage:(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
Expand Down
14 changes: 14 additions & 0 deletions Firebase/Auth/Source/FIRAuthErrorUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@
"silent push notification and therefore could not verify your app. Ensure that you configured "
"your app correctly to recieve push notifications.";

/** @var kFIRAuthErrorMessageCaptchaCheckFailed
@brief Message for @c FIRAuthErrorCodeCaptchaCheckFailed error code.
*/
static NSString *const kFIRAuthErrorMessageCaptchaCheckFailed = @"The reCAPTCHA response token "
"provided is either invalid, expired or already";

/** @var kFIRAuthErrorMessageInternalError
@brief Message for @c FIRAuthErrorCodeInternalError error code.
*/
Expand Down Expand Up @@ -447,6 +453,8 @@
return kFIRAuthErrorMessageNotificationNotForwarded;
case FIRAuthErrorCodeAppNotVerified:
return kFIRAuthErrorMessageAppNotVerified;
case FIRAuthErrorCodeCaptchaCheckFailed:
return kFIRAuthErrorMessageCaptchaCheckFailed;
}
}

Expand Down Expand Up @@ -552,6 +560,8 @@
return @"ERROR_NOTIFICATION_NOT_FORWARDED";
case FIRAuthErrorCodeAppNotVerified:
return @"ERROR_APP_NOT_VERIFIED";
case FIRAuthErrorCodeCaptchaCheckFailed:
return @"ERROR_CAPTCHA_CHECK_FAILED";
}
}

Expand Down Expand Up @@ -859,6 +869,10 @@ + (NSError *)appNotVerifiedErrorWithMessage:(nullable NSString *)message {
return [self errorWithCode:FIRAuthInternalErrorCodeAppNotVerified message:message];
}

+ (NSError *)captchaCheckFailedErrorWithMessage:(nullable NSString *)message {
return [self errorWithCode:FIRAuthInternalErrorCodeCaptchaCheckFailed message:message];
}

+ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status {
NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status];
return [self errorWithCode:FIRAuthInternalErrorCodeKeychainError userInfo:@{
Expand Down
5 changes: 5 additions & 0 deletions Firebase/Auth/Source/FIRAuthInternalErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ typedef NS_ENUM(NSInteger, FIRAuthInternalErrorCode) {
FIRAuthInternalErrorCodeInvalidAppCredential =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidAppCredential,

/** Indicates that the reCAPTCHA token is not valid.
*/
FIRAuthInternalErrorCodeCaptchaCheckFailed =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeCaptchaCheckFailed,

/** Indicates that an invalid verification ID was used in the verifyPhoneNumber request.
*/
FIRAuthInternalErrorCodeInvalidVerificationID =
Expand Down
4 changes: 4 additions & 0 deletions Firebase/Auth/Source/Public/FIRAuthErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ typedef NS_ENUM(NSInteger, FIRAuthErrorCode) {
*/
FIRAuthErrorCodeAppNotVerified = 17055,

/** Indicates that the reCAPTCHA token is not valid.
*/
FIRAuthErrorCodeCaptchaCheckFailed = 17056,

/** Indicates an error occurred while attempting to access the keychain.
*/
FIRAuthErrorCodeKeychainError = 17995,
Expand Down
10 changes: 10 additions & 0 deletions Firebase/Auth/Source/RPCs/FIRAuthBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@
*/
static NSString *const kAppNotVerifiedErrorMessage = @"APP_NOT_VERIFIED";

/** @var kCaptchaCheckFailedErrorMessage
@brief This is the error message the server will respond with if the reCAPTCHA token provided is
invalid.
*/
static NSString *const kCaptchaCheckFailedErrorMessage = @"CAPTCHA_CHECK_FAILED";

/** @var gBackendImplementation
@brief The singleton FIRAuthBackendImplementation instance to use.
*/
Expand Down Expand Up @@ -1014,6 +1020,10 @@ + (nullable NSError *)clientErrorWithServerErrorMessage:(NSString *)serverErrorM
return [FIRAuthErrorUtils appNotVerifiedErrorWithMessage:serverErrorMessage];
}

if ([shortErrorMessage isEqualToString:kCaptchaCheckFailedErrorMessage]) {
return [FIRAuthErrorUtils captchaCheckFailedErrorWithMessage:serverErrorMessage];
}

// 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]) {
Expand Down
12 changes: 10 additions & 2 deletions Firebase/Auth/Source/RPCs/FIRSendVerificationCodeRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
/** @property appCredential
@brief The credential to prove the identity of the app in order to send the verification code.
*/
@property(nonatomic, strong, readonly) FIRAuthAppCredential *appCredential;
@property(nonatomic, strong, readonly, nullable) FIRAuthAppCredential *appCredential;

/** @property reCAPTCHAToken
@brief The reCAPTCHA token to prove the identity of the app in order to send the verification
code.
*/
@property(nonatomic, strong, readonly, nullable) NSString *reCAPTCHAToken;

/** @fn initWithEndpoint:requestConfiguration:
@brief Please use initWithPhoneNumber:appCredentials:requestConfiguration: instead.
Expand All @@ -46,10 +52,12 @@ NS_ASSUME_NONNULL_BEGIN
@brief Designated initializer.
@param phoneNumber The phone number to which the verification code is to be sent.
@param appCredential The credential that proves the identity of the app.
@param reCAPTCHAToken The reCAPTCHA token that proves the identity of the app.
@param requestConfiguration An object containing configurations to be added to the request.
*/
- (nullable instancetype)initWithPhoneNumber:(NSString *)phoneNumber
appCredential:(FIRAuthAppCredential *)appCredential
appCredential:(nullable FIRAuthAppCredential *)appCredential
reCAPTCHAToken:(nullable NSString *)reCAPTCHAToken
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
NS_DESIGNATED_INITIALIZER;

Expand Down
12 changes: 11 additions & 1 deletion Firebase/Auth/Source/RPCs/FIRSendVerificationCodeRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,24 @@
*/
static NSString *const kSecretKey = @"iosSecret";

/** @var kreCAPTCHATokenKey
@brief The key for the reCAPTCHAToken parameter in the request.
*/
static NSString *const kreCAPTCHATokenKey = @"recaptchaToken";

@implementation FIRSendVerificationCodeRequest {
}

- (nullable instancetype)initWithPhoneNumber:(NSString *)phoneNumber
appCredential:(FIRAuthAppCredential *)appCredential
appCredential:(nullable FIRAuthAppCredential *)appCredential
reCAPTCHAToken:(nullable NSString *)reCAPTCHAToken
requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration {
self = [super initWithEndpoint:kSendVerificationCodeEndPoint
requestConfiguration:requestConfiguration];
if (self) {
_phoneNumber = [phoneNumber copy];
_appCredential = appCredential;
_reCAPTCHAToken = [reCAPTCHAToken copy];
}
return self;
}
Expand All @@ -66,6 +73,9 @@ - (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)
if (_appCredential.secret) {
postBody[kSecretKey] = _appCredential.secret;
}
if (_reCAPTCHAToken) {
postBody[kreCAPTCHATokenKey] = _reCAPTCHAToken;
}
return postBody;
}

Expand Down