aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Auth/Source/AuthProviders/Phone
diff options
context:
space:
mode:
Diffstat (limited to 'Firebase/Auth/Source/AuthProviders/Phone')
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.h37
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.m65
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential_Internal.h70
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.h90
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m213
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.h36
-rw-r--r--Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.m36
7 files changed, 547 insertions, 0 deletions
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.h b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.h
new file mode 100644
index 0000000..d951564
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.h
@@ -0,0 +1,37 @@
+/*
+ * 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 <Foundation/Foundation.h>
+
+#import "FIRAuthCredential.h"
+#import "FIRAuthSwiftNameSupport.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @class FIRPhoneAuthCredential
+ @brief Implementation of FIRAuthCredential for Phone Auth credentials.
+ */
+FIR_SWIFT_NAME(PhoneAuthCredential)
+@interface FIRPhoneAuthCredential : FIRAuthCredential
+
+/** @fn init
+ @brief This class is not supposed to be instantiated directly.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.m b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.m
new file mode 100644
index 0000000..b9bf577
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential.m
@@ -0,0 +1,65 @@
+/*
+ * 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 "FIRPhoneAuthCredential.h"
+
+#import "FIRPhoneAuthProvider.h"
+#import "FIRPhoneAuthCredential_Internal.h"
+#import "FIRAuthCredential_Internal.h"
+#import "FIRAuthExceptionUtils.h"
+#import "FIRVerifyAssertionRequest.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FIRPhoneAuthCredential ()
+
+- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
+
+@end
+
+@implementation FIRPhoneAuthCredential
+
+- (instancetype)initWithTemporaryProof:(NSString *)temporaryProof
+ phoneNumber:(NSString *)phoneNumber
+ providerID:(NSString *)providerID {
+ self = [super initWithProvider:providerID];
+ if (self) {
+ _temporaryProof = [temporaryProof copy];
+ _phoneNumber = [phoneNumber copy];
+ }
+ return self;
+}
+
+- (nullable instancetype)initWithProvider:(NSString *)provider {
+ [FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
+ @"Please call the designated initializer."];
+ return nil;
+}
+
+- (instancetype)initWithProviderID:(NSString *)providerID
+ verificationID:(NSString *)verificationID
+ verificationCode:(NSString *)verificationCode {
+ self = [super initWithProvider:providerID];
+ if (self) {
+ _verificationID = [verificationID copy];
+ _verificationCode = [verificationCode copy];
+ }
+ return self;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential_Internal.h b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential_Internal.h
new file mode 100644
index 0000000..f260b89
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthCredential_Internal.h
@@ -0,0 +1,70 @@
+/*
+ * 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 <Foundation/Foundation.h>
+
+#import "FIRPhoneAuthCredential.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @extension FIRPhoneAuthCredential
+ @brief Internal implementation of FIRAuthCredential for Phone Auth credentials.
+ */
+@interface FIRPhoneAuthCredential ()
+
+/** @var verificationID
+ @brief The verification ID obtained from invoking @c verifyPhoneNumber:completion:
+ */
+@property(nonatomic, readonly, nonnull) NSString *verificationID;
+
+/** @var verificationCode
+ @brief The verification code provided by the user.
+ */
+@property(nonatomic, readonly, nonnull) NSString *verificationCode;
+
+/** @var temporaryProof
+ @brief The a temporary proof code perftaining to this credential, 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.
+ */
+@property(nonatomic, readonly, nonnull) NSString *phoneNumber;
+
+/** @var initWithTemporaryProof:phoneNumber:
+ @brief Designated Initializer.
+ @param providerID The provider ID associated with the phone auth credential being created.
+ */
+- (instancetype)initWithTemporaryProof:(NSString *)temporaryProof
+ phoneNumber:(NSString *)phoneNumber
+ providerID:(NSString *)providerID NS_DESIGNATED_INITIALIZER;
+
+/** @var initWithProviderID:verificationID:verificationCode:
+ @brief Designated Initializer.
+ @param providerID The provider ID associated with the phone auth credential being created.
+ @param verificationID The verification ID associated witht Phone Auth credential being created.
+ @param verificationCode The verification code associated witht Phone Auth credential being
+ created.
+ */
+- (instancetype)initWithProviderID:(NSString *)providerID
+ verificationID:(NSString *)verificationID
+ verificationCode:(NSString *)verificationCode NS_DESIGNATED_INITIALIZER;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.h b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.h
new file mode 100644
index 0000000..bc12b43
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.h
@@ -0,0 +1,90 @@
+/*
+ * 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 <Foundation/Foundation.h>
+
+#import "FIRAuth.h"
+#import "FIRAuthSwiftNameSupport.h"
+
+@class FIRPhoneAuthCredential;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @var FIRPhoneAuthProviderID
+ @brief A string constant identifying the phone identity provider.
+ */
+extern NSString *const FIRPhoneAuthProviderID FIR_SWIFT_NAME(PhoneAuthProviderID);
+
+/** @typedef FIRVerificationResultCallback
+ @brief The type of block invoked when a request to send a verification code has finished.
+
+ @param verificationID On success, the verification ID provided, nil otherwise.
+ @param error On error, the error that occured, nil otherwise.
+ */
+typedef void (^FIRVerificationResultCallback)(NSString *_Nullable verificationID,
+ NSError *_Nullable error)
+ FIR_SWIFT_NAME(VerificationResultCallback);
+
+/** @class FIRPhoneNumberProvider
+ @brief A concrete implementation of @c FIRAuthProvider for Phone Auth Providers.
+ */
+FIR_SWIFT_NAME(PhoneAuthProvider)
+@interface FIRPhoneAuthProvider : NSObject
+
+/** @fn provider
+ @brief Returns an instance of @c FIRPhoneAuthProvider for the default @c FIRAuth object.
+ */
++ (instancetype)provider FIR_SWIFT_NAME(provider());
+
+/** @fn providerWithAuth:
+ @brief Returns an instance of @c FIRPhoneAuthProvider for the provided @c FIRAuth object.
+
+ @param auth The auth object to associate with the @c PhoneauthProvider instance.
+ */
++ (instancetype)providerWithAuth:(FIRAuth *)auth FIR_SWIFT_NAME(provider(auth:));
+
+/** @fn verifyPhoneNumber:completion:
+ @brief Starts the phone number authentication flow by sending a verifcation code to the
+ specified phone number.
+
+ @param phoneNumber The phone number to be verified.
+ @param completion The callback to be invoked when the verification flow is finished.
+ */
+- (void)verifyPhoneNumber:(NSString *)phoneNumber
+ completion:(nullable FIRVerificationResultCallback)completion;
+
+/** @fn credentialWithVerificationID:verificationCode:
+ @brief Creates an @c FIRAuthCredential for the phone number provider identified by the
+ verification ID and verification code.
+
+ @param verificationID The verification ID obtained from invoking @c
+ verifyPhoneNumber:completion:
+ @param verificationCode The verification code obtained from the user.
+ @return The corresponding @c FIRAuthCredential for the verification ID and verification code
+ provided.
+ */
+- (FIRPhoneAuthCredential *)credentialWithVerificationID:(NSString *)verificationID
+ verificationCode:(NSString *)verificationCode;
+
+/** @fn init
+ @brief Please use the @c provider or @providerWithAuth: methods to obtain an instance of @c
+ FIRPhoneAuthProvider.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m
new file mode 100644
index 0000000..423b2b6
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/FIRPhoneAuthProvider.m
@@ -0,0 +1,213 @@
+/*
+ * 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 "FIRPhoneAuthProvider.h"
+
+#import "FIRLogger.h"
+#import "FIRPhoneAuthCredential_Internal.h"
+#import "NSString+FIRAuth.h"
+#import "../../Private/FIRAuthAPNSToken.h"
+#import "../../Private/FIRAuthAPNSTokenManager.h"
+#import "../../Private/FIRAuthAppCredential.h"
+#import "../../Private/FIRAuthAppCredentialManager.h"
+#import "../../Private/FIRAuthGlobalWorkQueue.h"
+#import "../../Private/FIRAuth_Internal.h"
+#import "../../Private/FIRAuthNotificationManager.h"
+#import "../../Private/FIRAuthErrorUtils.h"
+#import "FIRAuthBackend.h"
+#import "FIRSendVerificationCodeRequest.h"
+#import "FIRSendVerificationCodeResponse.h"
+#import "FIRVerifyClientRequest.h"
+#import "FIRVerifyClientResponse.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @typedef FIRVerifyClientCallback
+ @brief The callback invoked at the end of a client verification flow.
+ @param appCredential credential that proves the identity of the app during a phone
+ authentication flow.
+ @param error The error that occured while verifying the app, if any.
+ */
+typedef void (^FIRVerifyClientCallback)(FIRAuthAppCredential *_Nullable appCredential,
+ NSError *_Nullable error);
+
+@implementation FIRPhoneAuthProvider {
+
+ /** @var _auth
+ @brief The auth instance used to for verifying the phone number.
+ */
+ FIRAuth *_auth;
+}
+
+/** @fn initWithAuth:
+ @brief returns an instance of @c FIRPhoneAuthProvider assocaited with the provided auth
+ instance.
+ @return An Instance of @c FIRPhoneAuthProvider.
+ */
+- (nullable instancetype)initWithAuth:(FIRAuth *)auth {
+ self = [super init];
+ if (self) {
+ _auth = auth;
+ }
+ return self;
+}
+
+- (void)verifyPhoneNumber:(NSString *)phoneNumber
+ completion:(nullable FIRVerificationResultCallback)completion {
+ dispatch_async(FIRAuthGlobalWorkQueue(), ^{
+ FIRVerificationResultCallback callBackOnMainThread = ^(NSString *_Nullable verificationID,
+ NSError *_Nullable error) {
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(verificationID, error);
+ });
+ }
+ };
+
+ if (!phoneNumber.length) {
+ callBackOnMainThread(nil,
+ [FIRAuthErrorUtils missingPhoneNumberErrorWithMessage:nil]);
+ return;
+ }
+ [_auth.notificationManager checkNotificationForwardingWithCallback:
+ ^(BOOL isNotificationBeingForwarded) {
+ if (!isNotificationBeingForwarded) {
+ callBackOnMainThread(nil, [FIRAuthErrorUtils notificationNotForwardedError]);
+ return;
+ }
+ [self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber
+ retryOnInvalidAppCredential:YES
+ callback:callBackOnMainThread];
+ }];
+ });
+}
+
+- (FIRPhoneAuthCredential *)credentialWithVerificationID:(NSString *)verificationID
+ verificationCode:(NSString *)verificationCode {
+ return [[FIRPhoneAuthCredential alloc] initWithProviderID:FIRPhoneAuthProviderID
+ verificationID:verificationID
+ verificationCode:verificationCode];
+}
+
++ (instancetype)provider {
+ return [[self alloc]initWithAuth:[FIRAuth auth]];
+}
+
++ (instancetype)providerWithAuth:(FIRAuth *)auth {
+ return [[self alloc]initWithAuth:auth];
+}
+
+#pragma mark - Internal Methods
+
+/** @fn verifyClientAndSendVerificationCodeToPhoneNumber:retryOnInvalidAppCredential:callback:
+ @brief Starts the flow to verify the client via silent push notification.
+ @param retryOnInvalidAppCredential Whether of not the flow should be retried if an
+ FIRAuthErrorCodeInvalidAppCredential error is returned from the backend.
+ @param phoneNumber The phone number to be verified.
+ @param callback The callback to be invoked on the global work queue when the flow is
+ finished.
+ */
+- (void)verifyClientAndSendVerificationCodeToPhoneNumber:(NSString *)phoneNumber
+ retryOnInvalidAppCredential:(BOOL)retryOnInvalidAppCredential
+ callback:(FIRVerificationResultCallback)callback {
+ [self verifyClientWithCompletion:^(FIRAuthAppCredential *_Nullable appCredential,
+ NSError *_Nullable error) {
+ if (error) {
+ callback(nil, error);
+ return;
+ }
+ FIRSendVerificationCodeRequest *request =
+ [[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber
+ appCredential:appCredential
+ APIKey:_auth.APIKey];
+ [FIRAuthBackend sendVerificationCode:request
+ callback:^(FIRSendVerificationCodeResponse *_Nullable response,
+ NSError *_Nullable error) {
+ if (error) {
+ if (error.code == FIRAuthErrorCodeInvalidAppCredential) {
+ if (retryOnInvalidAppCredential) {
+ [_auth.appCredentialManager clearCredential];
+ [self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber
+ retryOnInvalidAppCredential:NO
+ callback:callback];
+ return;
+ }
+ callback(nil, [FIRAuthErrorUtils unexpectedResponseWithDeserializedResponse:nil
+ underlyingError:error]);
+ return;
+ }
+ callback(nil, error);
+ return;
+ }
+ // Associate the phone number with the verification ID.
+ response.verificationID.fir_authPhoneNumber = phoneNumber;
+ callback(response.verificationID, nil);
+ }];
+ }];
+}
+
+/** @fn verifyClientWithCompletion:completion:
+ @brief Continues the flow to verify the client via silent push notification.
+ @param completion The callback to be invoked when the client verification flow is finished.
+ */
+- (void)verifyClientWithCompletion:(FIRVerifyClientCallback)completion {
+ if (_auth.appCredentialManager.credential) {
+ completion(_auth.appCredentialManager.credential, nil);
+ return;
+ }
+ [_auth.tokenManager getTokenWithCallback:^(FIRAuthAPNSToken * _Nullable token) {
+ if (!token) {
+ completion(nil, [FIRAuthErrorUtils missingAppTokenError]);
+ return;
+ }
+
+ // Convert token data to hex string.
+ NSUInteger capacity = token.data.length * 2;
+ NSMutableString *tokenString = [NSMutableString stringWithCapacity:capacity];
+ const unsigned char *tokenData = token.data.bytes;
+ for (int idx = 0; idx < token.data.length; ++idx) {
+ [tokenString appendFormat:@"%02X", (int)tokenData[idx]];
+ }
+
+ FIRVerifyClientRequest *request =
+ [[FIRVerifyClientRequest alloc] initWithAppToken:tokenString
+ isSandbox:token.type == FIRAuthAPNSTokenTypeSandbox
+ APIKey:_auth.APIKey];
+ [FIRAuthBackend verifyClient:request callback:^(FIRVerifyClientResponse *_Nullable response,
+ NSError *_Nullable error) {
+ if (error) {
+ completion(nil, error);
+ return;
+ }
+ NSTimeInterval timeout = [response.suggestedTimeOutDate timeIntervalSinceNow];
+ [_auth.appCredentialManager
+ didStartVerificationWithReceipt:response.receipt
+ timeout:timeout
+ callback:^(FIRAuthAppCredential *credential) {
+ if (!credential.secret) {
+ FIRLogError(kFIRLoggerAuth, @"I-AUT000014",
+ @"Failed to receive remote notification to verify app identity within "
+ @"%.0f second(s)", timeout);
+ }
+ completion(credential, nil);
+ }];
+ }];
+ }];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.h b/Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.h
new file mode 100644
index 0000000..ba123fa
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.h
@@ -0,0 +1,36 @@
+/*
+ * 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 <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @category NSString(FIRAuth)
+ @brief A FIRAuth category for extending the functionality of NSString for specific Firebase Auth
+ use cases.
+ */
+@interface NSString (FIRAuth)
+
+/** @property fir_authPhoneNumber
+ @brief A phone number associated with the verification ID (NSString instance).
+ @remarks Allows an instance on NSString to be associated with a phone number in order to link
+ phone number with the verificationID returned from verifyPhoneNumber:completion:
+ */
+@property(nonatomic, strong) NSString *fir_authPhoneNumber;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.m b/Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.m
new file mode 100644
index 0000000..87f3b1c
--- /dev/null
+++ b/Firebase/Auth/Source/AuthProviders/Phone/NSString+FIRAuth.m
@@ -0,0 +1,36 @@
+/*
+ * 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 "NSString+FIRAuth.h"
+
+#import <objc/runtime.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation NSString (FIRAuth)
+
+- (void)setFir_authPhoneNumber:(NSString *)phoneNumber {
+ objc_setAssociatedObject(self, @selector(fir_authPhoneNumber), phoneNumber,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSString *)fir_authPhoneNumber {
+ return objc_getAssociatedObject(self, @selector(fir_authPhoneNumber));
+}
+
+@end
+
+NS_ASSUME_NONNULL_END