From aebb293f3dcfaef012e847689d8b814477c0c301 Mon Sep 17 00:00:00 2001 From: Zsika Phillip Date: Wed, 27 Sep 2017 00:16:33 -0700 Subject: Add operation phone auth (#309) * Adds operation to verify PhoneNumber requests * Improvements and unit tests * Fixes typo * Addresses comments - Removes the FIRAuthOperation class. - Defines the FIRAuthOperationType as an enum in a class of the same name. - Passes the FIRAuthOperationType value down to the verifyPhoneNumber RPC where it is translated to a string. * Fixes unit tests * Actually fixes the unit tests. --- Firebase/Auth/FIRAuthOperationType.h | 47 ++++++++++++++++++++++ Firebase/Auth/Source/FIRAuth.m | 13 +++++- Firebase/Auth/Source/FIRAuthOperationType.h | 47 ++++++++++++++++++++++ Firebase/Auth/Source/FIRUser.m | 22 ++++++---- .../Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.h | 14 ++++++- .../Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.m | 32 +++++++++++++++ 6 files changed, 164 insertions(+), 11 deletions(-) create mode 100644 Firebase/Auth/FIRAuthOperationType.h create mode 100644 Firebase/Auth/Source/FIRAuthOperationType.h (limited to 'Firebase') diff --git a/Firebase/Auth/FIRAuthOperationType.h b/Firebase/Auth/FIRAuthOperationType.h new file mode 100644 index 0000000..15d3dd7 --- /dev/null +++ b/Firebase/Auth/FIRAuthOperationType.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief Indicates the type of operation performed for RPCs that support the operation + parameter. + */ +typedef NS_ENUM(NSInteger, FIRAuthOperationType) { + /** Indicates that the operation type is uspecified. + */ + FIRAuthOperationTypeUnspecified = 0, + + /** Indicates that the operation type is sign in or sign up. + */ + FIRAuthOperationTypeSignUpOrSignIn = 1, + + /** Indicates that the operation type is reauthentication. + */ + FIRAuthOperationTypeReauth = 2, + + /** Indicates that the operation type is update. + */ + FIRAuthOperationTypeUpdate = 3, + + /** Indicates that the operation type is link. + */ + FIRAuthOperationTypeLink = 4, +}; + +NS_ASSUME_NONNULL_END diff --git a/Firebase/Auth/Source/FIRAuth.m b/Firebase/Auth/Source/FIRAuth.m index 8d29eb2..f0a069c 100644 --- a/Firebase/Auth/Source/FIRAuth.m +++ b/Firebase/Auth/Source/FIRAuth.m @@ -31,6 +31,7 @@ #import "FIRAuthExceptionUtils.h" #import "FIRAuthGlobalWorkQueue.h" #import "FIRAuthKeychain.h" +#import "FIRAuthOperationType.h" #import "FIRUser_Internal.h" #import "FirebaseAuth.h" #import "FIRAuthBackend.h" @@ -600,8 +601,12 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; if ([credential isKindOfClass:[FIRPhoneAuthCredential class]]) { // Special case for phone auth credentials FIRPhoneAuthCredential *phoneCredential = (FIRPhoneAuthCredential *)credential; - [self signInWithPhoneCredential:phoneCredential callback:^(FIRUser *_Nullable user, - NSError *_Nullable error) { + FIRAuthOperationType operation = + isReauthentication ? FIRAuthOperationTypeReauth : FIRAuthOperationTypeSignUpOrSignIn; + [self signInWithPhoneCredential:phoneCredential + operation:operation + callback:^(FIRUser *_Nullable user, + NSError *_Nullable error) { if (callback) { FIRAuthDataResult *result = user ? [[FIRAuthDataResult alloc] initWithUser:user additionalUserInfo:nil] : nil; @@ -1023,15 +1028,18 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; /** @fn signInWithPhoneCredential:callback: @brief Signs in using a phone credential. @param credential The Phone Auth credential used to sign in. + @param operation The type of operation for which this sign-in attempt is initiated. @param callback A block which is invoked when the sign in finishes (or is cancelled.) Invoked asynchronously on the global auth work queue in the future. */ - (void)signInWithPhoneCredential:(FIRPhoneAuthCredential *)credential + operation:(FIRAuthOperationType)operation callback:(FIRAuthResultCallback)callback { if (credential.temporaryProof.length && credential.phoneNumber.length) { FIRVerifyPhoneNumberRequest *request = [[FIRVerifyPhoneNumberRequest alloc] initWithTemporaryProof:credential.temporaryProof phoneNumber:credential.phoneNumber + operation:operation requestConfiguration:_requestConfiguration]; [self phoneNumberSignInWithRequest:request callback:callback]; return; @@ -1048,6 +1056,7 @@ static NSMutableDictionary *gKeychainServiceNameForAppName; FIRVerifyPhoneNumberRequest *request = [[FIRVerifyPhoneNumberRequest alloc]initWithVerificationID:credential.verificationID verificationCode:credential.verificationCode + operation:operation requestConfiguration:_requestConfiguration]; [self phoneNumberSignInWithRequest:request callback:callback]; } diff --git a/Firebase/Auth/Source/FIRAuthOperationType.h b/Firebase/Auth/Source/FIRAuthOperationType.h new file mode 100644 index 0000000..15d3dd7 --- /dev/null +++ b/Firebase/Auth/Source/FIRAuthOperationType.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + @brief Indicates the type of operation performed for RPCs that support the operation + parameter. + */ +typedef NS_ENUM(NSInteger, FIRAuthOperationType) { + /** Indicates that the operation type is uspecified. + */ + FIRAuthOperationTypeUnspecified = 0, + + /** Indicates that the operation type is sign in or sign up. + */ + FIRAuthOperationTypeSignUpOrSignIn = 1, + + /** Indicates that the operation type is reauthentication. + */ + FIRAuthOperationTypeReauth = 2, + + /** Indicates that the operation type is update. + */ + FIRAuthOperationTypeUpdate = 3, + + /** Indicates that the operation type is link. + */ + FIRAuthOperationTypeLink = 4, +}; + +NS_ASSUME_NONNULL_END diff --git a/Firebase/Auth/Source/FIRUser.m b/Firebase/Auth/Source/FIRUser.m index 049bb30..ef42a29 100644 --- a/Firebase/Auth/Source/FIRUser.m +++ b/Firebase/Auth/Source/FIRUser.m @@ -27,6 +27,7 @@ #import "FIRAuthErrorUtils.h" #import "FIRAuthGlobalWorkQueue.h" #import "FIRAuthSerialTaskQueue.h" +#import "FIRAuthOperationType.h" #import "FIRAuth_Internal.h" #import "FIRSecureTokenService.h" #import "FIRUserInfoImpl.h" @@ -615,27 +616,32 @@ static void callInMainThreadWithAuthDataResultAndError( } #if TARGET_OS_IOS -/** @fn internalUpdatePhoneNumberCredential:completion: +/** @fn internalUpdateOrLinkPhoneNumberCredential:completion: @brief Updates the phone number for the user. On success, the cached user profile data is updated. @param phoneAuthCredential The new phone number credential corresponding to the phone number to be added to the firebaes account, if a phone number is already linked to the account this new phone number will replace it. + @param isLinkOperation Boolean value indicating whether or not this is a link operation. @param completion Optionally; the block invoked when the user profile change has finished. Invoked asynchronously on the global work queue in the future. */ -- (void)internalUpdatePhoneNumberCredential:(FIRPhoneAuthCredential *)phoneAuthCredential - completion:(FIRUserProfileChangeCallback)completion { +- (void)internalUpdateOrLinkPhoneNumberCredential:(FIRPhoneAuthCredential *)phoneAuthCredential + isLinkOperation:(BOOL)isLinkOperation + completion:(FIRUserProfileChangeCallback)completion { [self internalGetTokenWithCallback:^(NSString *_Nullable accessToken, NSError *_Nullable error) { if (error) { completion(error); return; } + FIRAuthOperationType operation = + isLinkOperation ? FIRAuthOperationTypeLink : FIRAuthOperationTypeUpdate; FIRVerifyPhoneNumberRequest *request = [[FIRVerifyPhoneNumberRequest alloc] initWithVerificationID:phoneAuthCredential.verificationID verificationCode:phoneAuthCredential.verificationCode + operation:operation requestConfiguration:_auth.requestConfiguration]; request.accessToken = accessToken; [FIRAuthBackend verifyPhoneNumber:request @@ -661,8 +667,9 @@ static void callInMainThreadWithAuthDataResultAndError( - (void)updatePhoneNumberCredential:(FIRPhoneAuthCredential *)phoneAuthCredential completion:(nullable FIRUserProfileChangeCallback)completion { dispatch_async(FIRAuthGlobalWorkQueue(), ^{ - [self internalUpdatePhoneNumberCredential:phoneAuthCredential - completion:^(NSError *_Nullable error) { + [self internalUpdateOrLinkPhoneNumberCredential:phoneAuthCredential + isLinkOperation:NO + completion:^(NSError *_Nullable error) { callInMainThreadWithError(completion, error); }]; }); @@ -856,8 +863,9 @@ static void callInMainThreadWithAuthDataResultAndError( #if TARGET_OS_IOS if ([credential isKindOfClass:[FIRPhoneAuthCredential class]]) { FIRPhoneAuthCredential *phoneAuthCredential = (FIRPhoneAuthCredential *)credential; - [self internalUpdatePhoneNumberCredential:phoneAuthCredential - completion:^(NSError *_Nullable error) { + [self internalUpdateOrLinkPhoneNumberCredential:phoneAuthCredential + isLinkOperation:YES + completion:^(NSError *_Nullable error) { if (error){ callInMainThreadWithAuthDataResultAndError(completion, nil, error); } else { diff --git a/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.h b/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.h index b091d62..07988f1 100644 --- a/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.h +++ b/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.h @@ -16,6 +16,7 @@ #import "FIRIdentityToolkitRequest.h" +#import "FIRAuthOperationType.h" #import "FIRAuthRPCRequest.h" NS_ASSUME_NONNULL_BEGIN @@ -38,15 +39,20 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy, nullable) NSString *accessToken; /** @var temporaryProof - @brief The a temporary proof code pertaining to this credentil, returned from the backend. + @brief The temporary proof code, previously returned from the backend. */ @property(nonatomic, readonly, nonnull) NSString *temporaryProof; /** @var phoneNumber - @brief The a phone number pertaining to this credential, returned from the backend. + @brief The phone number to be verified in the request. */ @property(nonatomic, readonly, nonnull) NSString *phoneNumber; +/** @var operation + @brief The type of operation triggering this verify phone number request. + */ +@property(nonatomic, assign, readonly) FIRAuthOperationType operation; + /** @fn initWithEndpoint:requestConfiguration: @brief Please use initWithVerificationID:verificationCode:requestConfiguration */ @@ -58,10 +64,12 @@ NS_ASSUME_NONNULL_BEGIN @brief Designated initializer. @param temporaryProof The temporary proof sent by the backed. @param phoneNumber The phone number associated with the credential to be signed in. + @param operation Indicates what operation triggered the verify phone number request. @param requestConfiguration An object containing configurations to be added to the request. */ - (nullable instancetype)initWithTemporaryProof:(NSString *)temporaryProof phoneNumber:(NSString *)phoneNumber + operation:(FIRAuthOperationType)operation requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration NS_DESIGNATED_INITIALIZER; @@ -69,10 +77,12 @@ NS_ASSUME_NONNULL_BEGIN @brief Designated initializer. @param verificationID The verification ID obtained from the response of @c sendVerificationCode. @param verificationCode The verification code provided by the user. + @param operation Indicates what operation triggered the verify phone number request. @param requestConfiguration An object containing configurations to be added to the request. */ - (nullable instancetype)initWithVerificationID:(NSString *)verificationID verificationCode:(NSString *)verificationCode + operation:(FIRAuthOperationType)operation requestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration NS_DESIGNATED_INITIALIZER; diff --git a/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.m b/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.m index b859693..8af4c4e 100644 --- a/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.m +++ b/Firebase/Auth/Source/RPCs/FIRVerifyPhoneNumberRequest.m @@ -48,10 +48,16 @@ static NSString *const kTemporaryProofKey = @"temporaryProof"; */ static NSString *const kPhoneNumberKey = @"phoneNumber"; +/** @var kOperationKey + @brief The key for the operation value in the request. + */ +static NSString *const kOperationKey = @"operation"; + @implementation FIRVerifyPhoneNumberRequest - (nullable instancetype)initWithTemporaryProof:(NSString *)temporaryProof phoneNumber:(NSString *)phoneNumber + operation:(FIRAuthOperationType)operation requestConfiguration: (FIRAuthRequestConfiguration *)requestConfiguration { self = [super initWithEndpoint:kVerifyPhoneNumberEndPoint @@ -59,12 +65,14 @@ static NSString *const kPhoneNumberKey = @"phoneNumber"; if (self) { _temporaryProof = [temporaryProof copy]; _phoneNumber = [phoneNumber copy]; + _operation = operation; } return self; } - (nullable instancetype)initWithVerificationID:(NSString *)verificationID verificationCode:(NSString *)verificationCode + operation:(FIRAuthOperationType)operation requestConfiguration: (FIRAuthRequestConfiguration *)requestConfiguration { self = [super initWithEndpoint:kVerifyPhoneNumberEndPoint @@ -72,10 +80,32 @@ static NSString *const kPhoneNumberKey = @"phoneNumber"; if (self) { _verificationID = verificationID; _verificationCode = verificationCode; + _operation = operation; } return self; } +/** @fn FIRAuthOperationString + @brief Returns a string object corresponding to the provided FIRAuthOperationType value. + @param operationType The value of the FIRAuthOperationType enum which will be translated to its + corresponding string value. + @return The string value corresponding to the FIRAuthOperationType argument. + */ +NSString *const FIRAuthOperationString(FIRAuthOperationType operationType) { + switch(operationType){ + case FIRAuthOperationTypeUnspecified: + return @"VERIFY_OP_UNSPECIFIED"; + case FIRAuthOperationTypeSignUpOrSignIn: + return @"SIGN_UP_OR_IN"; + case FIRAuthOperationTypeReauth: + return @"REAUTH"; + case FIRAuthOperationTypeLink: + return @"LINK"; + case FIRAuthOperationTypeUpdate: + return @"UPDATE"; + } +} + - (nullable id)unencodedHTTPRequestBodyWithError:(NSError *__autoreleasing _Nullable *)error { NSMutableDictionary *postBody = [NSMutableDictionary dictionary]; if (_verificationID) { @@ -93,6 +123,8 @@ static NSString *const kPhoneNumberKey = @"phoneNumber"; if (_phoneNumber) { postBody[kPhoneNumberKey] = _phoneNumber; } + NSString *operation = FIRAuthOperationString(_operation); + postBody[kOperationKey] = operation; return postBody; } -- cgit v1.2.3