Skip to content

Commit 5dac6a1

Browse files
authored
Merge pull request #334 from firebase/default_phone
Add default phone number to the Phone Auth number flow.
2 parents 7bffef3 + 6608ec1 commit 5dac6a1

20 files changed

+375
-24
lines changed

FirebaseAuthUI/AccountManagement/FUIAccountSettingsOperation.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ - (void)reauthenticateWithProvider:(NSString *)providerID
165165
[self.delegate incrementActivity];
166166
// Sign out first to make sure sign in starts with a clean state.
167167
[providerUI signOut];
168-
[providerUI signInWithEmail:self.delegate.auth.currentUser.email
168+
[providerUI signInWithDefaultValue:self.delegate.auth.currentUser.email
169169
presentingViewController:[self.delegate presentingController]
170170
completion:^(FIRAuthCredential *_Nullable credential,
171171
NSError *_Nullable error,

FirebaseAuthUI/FUIAuth.m

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,12 @@ - (BOOL)signOutWithError:(NSError *_Nullable *_Nullable)error {
128128
}
129129

130130
- (void)signInWithProviderUI:(id<FUIAuthProvider>)providerUI
131-
presentingViewController:(UIViewController *)presentingViewController {
131+
presentingViewController:(UIViewController *)presentingViewController
132+
defaultValue:(nullable NSString *)defaultValue {
132133

133134
// Sign out first to make sure sign in starts with a clean state.
134135
[providerUI signOut];
135-
[providerUI signInWithEmail:nil
136+
[providerUI signInWithDefaultValue:defaultValue
136137
presentingViewController:presentingViewController
137138
completion:^(FIRAuthCredential *_Nullable credential,
138139
NSError *_Nullable error,
@@ -247,7 +248,7 @@ - (void)handleAccountLinkingForEmail:(NSString *)email
247248
signinHandler:^{
248249
// Sign out first to make sure sign in starts with a clean state.
249250
[bestProvider signOut];
250-
[bestProvider signInWithEmail:email
251+
[bestProvider signInWithDefaultValue:email
251252
presentingViewController:presentingViewController
252253
completion:^(FIRAuthCredential *_Nullable credential,
253254
NSError *_Nullable error,

FirebaseAuthUI/FUIAuthPickerViewController.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ - (void)signInWithEmail {
152152
}
153153

154154
- (void)didTapSignInButton:(FUIAuthSignInButton *)button {
155-
[self.authUI signInWithProviderUI:button.providerUI presentingViewController:self];
155+
[self.authUI signInWithProviderUI:button.providerUI
156+
presentingViewController:self
157+
defaultValue:nil];
156158
}
157159

158160
@end

FirebaseAuthUI/FUIAuthProvider.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
2525

2626
/** @typedef FIRAuthProviderSignInCompletionBlock
2727
@brief The type of block used to notify the auth system of the result of a sign-in flow.
28-
@see FUIAuthProvider.signInWithEmail:presentingViewController:completion:
28+
@see FUIAuthProvider.signInWithDefaultValue:presentingViewController:completion:
2929
@param credential The @c FIRAuthCredential object created after user interaction with third
3030
party provider.
3131
@param error The error which may happen during creation of The @c FIRAuthCredential object.
@@ -90,7 +90,26 @@ typedef void (^FIRAuthProviderSignInCompletionBlock) (
9090
*/
9191
- (void)signInWithEmail:(nullable NSString *)email
9292
presentingViewController:(nullable UIViewController *)presentingViewController
93-
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion;
93+
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion
94+
__attribute__((deprecated("This is deprecated API and will be removed in a future release."
95+
"Use signInWithDefaultValue:presentingViewController:completion:")));
96+
97+
/** @fn signInWithDefaultValue:presentingViewController:completion:
98+
@brief Called when the user wants to sign in using this auth provider.
99+
@remarks Implementors should invoke the completion block when the sign-in process has terminated
100+
or is canceled. There are two valid combinations of parameters; either @c credentials and
101+
@c userInfo are both non-nil, or @c error is non-nil. Errors must specify an error code
102+
which is one of the @c FIRAuthErrorCode codes. It is very important that all possible code
103+
paths eventually call this method to inform the auth system of the result of the sign-in
104+
flow.
105+
@param defaultValue The default initialization value of the provider (email, phone number etc.).
106+
@param presentingViewController The view controller used to present the UI.
107+
@param completion See remarks. A block which should be invoked when the sign-in process
108+
(using @c FIRAuthCredential) completes.
109+
*/
110+
- (void)signInWithDefaultValue:(nullable NSString *)defaultValue
111+
presentingViewController:(nullable UIViewController *)presentingViewController
112+
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion;
94113

95114
/** @fn signOut
96115
@brief Called when the user wants to sign out.

FirebaseAuthUI/FUIAuth_Internal.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,17 @@ NS_ASSUME_NONNULL_BEGIN
4242
*/
4343
- (nullable id<FUIAuthProvider>)providerWithID:(NSString *)providerID;
4444

45-
/** @fn signInWithProviderUI:presentingViewController:
45+
/** @fn signInWithProviderUI:presentingViewController:defaultValue:
4646
@brief Signs in with specified provider. @see FUIAuthDelegate.authUI:didSignInWithUser:error:
4747
for method callback.
4848
@param providerUI The authentication provider used for signing in.
4949
@param presentingViewController The view controller used to present the UI.
50+
@param defaultValue The provider default initialization value (e g email or phone number)
51+
used for signing in.
5052
*/
5153
- (void)signInWithProviderUI:(id<FUIAuthProvider>)providerUI
52-
presentingViewController:(UIViewController *)presentingViewController;
54+
presentingViewController:(UIViewController *)presentingViewController
55+
defaultValue:(nullable NSString *)defaultValue;
5356

5457
@end
5558

FirebaseAuthUI/FUIEmailEntryViewController.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ - (void)signInWithProvider:(id<FUIAuthProvider>)provider email:(NSString *)email
255255

256256
// Sign out first to make sure sign in starts with a clean state.
257257
[provider signOut];
258-
[provider signInWithEmail:email
258+
[provider signInWithDefaultValue:email
259259
presentingViewController:self
260260
completion:^(FIRAuthCredential *_Nullable credential,
261261
NSError *_Nullable error,

FirebaseAuthUI/FUIPasswordSignInViewController.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ NS_ASSUME_NONNULL_BEGIN
7171
*/
7272
- (void)didChangeEmail:(NSString *)email andPassword:(NSString *)password;
7373

74-
/** @fn signInWithEmail:andPassword:
74+
/** @fn signInWithDefaultValue:andPassword:
7575
@brief Should be called when user entered credentials. Sends authorization request
7676
@param email The email address of the user.
7777
@param password The password which user uses.
7878
*/
79-
- (void)signInWithEmail:(NSString *)email andPassword:(NSString *)password;
79+
- (void)signInWithDefaultValue:(NSString *)email andPassword:(NSString *)password;
8080

8181
@end
8282

FirebaseAuthUI/FUIPasswordSignInViewController.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ - (void)viewDidLoad {
9797

9898
#pragma mark - Actions
9999

100-
- (void)signInWithEmail:(NSString *)email andPassword:(NSString *)password {
100+
- (void)signInWithDefaultValue:(NSString *)email andPassword:(NSString *)password {
101101
if (![[self class] isValidEmail:email]) {
102102
[self showAlertWithMessage:FUILocalizedString(kStr_InvalidEmailError)];
103103
return;
@@ -138,7 +138,7 @@ - (void)signInWithEmail:(NSString *)email andPassword:(NSString *)password {
138138
}
139139

140140
- (void)signIn {
141-
[self signInWithEmail:_emailField.text andPassword:_passwordField.text];
141+
[self signInWithDefaultValue:_emailField.text andPassword:_passwordField.text];
142142
}
143143

144144
- (void)forgotPasswordForEmail:(NSString *)email {

FirebaseFacebookAuthUI/FUIFacebookAuth.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ - (UIColor *)buttonTextColor {
117117
- (void)signInWithEmail:(nullable NSString *)email
118118
presentingViewController:(nullable UIViewController *)presentingViewController
119119
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
120+
[self signInWithDefaultValue:email
121+
presentingViewController:presentingViewController
122+
completion:completion];
123+
}
124+
125+
- (void)signInWithDefaultValue:(nullable NSString *)defaultValue
126+
presentingViewController:(nullable UIViewController *)presentingViewController
127+
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
120128
_pendingSignInCallback = completion;
121129
_presentingViewController = presentingViewController;
122130

FirebaseGoogleAuthUI/FUIGoogleAuth.m

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ - (UIColor *)buttonTextColor {
106106
- (void)signInWithEmail:(nullable NSString *)email
107107
presentingViewController:(nullable UIViewController *)presentingViewController
108108
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
109+
[self signInWithDefaultValue:email
110+
presentingViewController:presentingViewController
111+
completion:completion];
112+
}
113+
114+
- (void)signInWithDefaultValue:(nullable NSString *)defaultValue
115+
presentingViewController:(nullable UIViewController *)presentingViewController
116+
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
109117
_presentingViewController = presentingViewController;
110118

111119
GIDSignIn *signIn = [self configuredGoogleSignIn];
@@ -118,7 +126,7 @@ - (void)signInWithEmail:(nullable NSString *)email
118126
}
119127
};
120128

121-
signIn.loginHint = email;
129+
signIn.loginHint = defaultValue;
122130
[signIn signIn];
123131
}
124132

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// Copyright (c) 2016 Google Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
#import <Foundation/Foundation.h>
18+
#import "FUICountryCodes.h"
19+
20+
NS_ASSUME_NONNULL_BEGIN
21+
22+
FOUNDATION_EXPORT NSString * const FUIPhoneNumberValidationErrorDomain;
23+
24+
typedef NS_ENUM(NSInteger, FUIPhoneNumberValidationError) {
25+
FUIPhoneNumberValidationErrorMissingPlus = 0,
26+
FUIPhoneNumberValidationErrorMissingDialCode = 1,
27+
FUIPhoneNumberValidationErrorMissingNumber = 2,
28+
};
29+
30+
/** Encapsulates a phone number with the raw and the normalized representations */
31+
@interface FUIPhoneNumber : NSObject
32+
33+
@property (nonatomic, readonly) FUICountryCodeInfo *countryCode;
34+
@property (nonatomic, copy, readonly) NSString *rawPhoneNumber;
35+
@property (nonatomic, copy, readonly) NSString *normalizedPhoneNumber;
36+
37+
/** @fn initWithNormalizedPhoneNumber:
38+
@brief Attempts to parse the given phone number into a raw phone number and country code.
39+
Parse behavior:
40+
If given phone number starts with a '+' character, then look for the country code matching
41+
the prefix of the number.
42+
Otherwise use the normalized number as the raw number, and find the country code using the
43+
device locale.
44+
@param normalizedPhoneNumber (required) A phone number string that will be parsed into
45+
a raw phone number and country code.
46+
@return object or nil if any of the required parameters is nil.
47+
*/
48+
- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber;
49+
50+
/** @fn initWithRawPhoneNumber:countryCode:
51+
@param rawPhoneNumber (required) The raw phone number without country code
52+
@param countryCode (required) The country code information
53+
@return object or nil if any of the required parameters is nil.
54+
*/
55+
- (instancetype)initWithRawPhoneNumber:(NSString *)rawPhoneNumber
56+
countryCode:(FUICountryCodeInfo *)countryCode;
57+
58+
/** @fn initWithNormalizedPhoneNumber:rawPhoneNumber:countryCode:
59+
@param normalizedPhoneNumber (optional) The phone number returned from the endpoint;
60+
if null or empty it will be computed ('+' + rawCountryCode + rawPhoneNumber)
61+
@param rawPhoneNumber (required) The raw phone number without country code
62+
@param countryCode (required) The country code information
63+
@return object or nil if any of the required parameters is nil.
64+
*/
65+
- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber
66+
rawPhoneNumber:(NSString *)rawPhoneNumber
67+
countryCode:(FUICountryCodeInfo *)countryCode;
68+
69+
- (instancetype)init NS_UNAVAILABLE;
70+
71+
/** @fn validate:
72+
@brief Checks if current phone number has valid international format.
73+
@param errorRef The error which occurred, if any.
74+
@return True if phone number format is valid.
75+
*/
76+
- (BOOL)validate:(NSError *__autoreleasing _Nullable *_Nullable)errorRef;
77+
@end
78+
79+
NS_ASSUME_NONNULL_END
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//
2+
// Copyright (c) 2016 Google Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
#import "FUIPhoneNumber.h"
18+
19+
NS_ASSUME_NONNULL_BEGIN
20+
21+
NSString * const FUIPhoneNumberValidationErrorDomain = @"FUIPhoneNumberValidationErrorDomain";
22+
23+
@implementation FUIPhoneNumber
24+
25+
- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber {
26+
NSAssert(normalizedPhoneNumber, @"normalizedPhoneNumber can't be nil");
27+
NSString *rawPhoneNumber;
28+
FUICountryCodes *codes = [[FUICountryCodes alloc] init];
29+
FUICountryCodeInfo *countryCode = [codes countryCodeInfoForPhoneNumber:normalizedPhoneNumber];
30+
31+
if (countryCode) {
32+
// Add 1 for the '+' character
33+
NSInteger countryCodeLength = countryCode.dialCode.length + 1;
34+
if (normalizedPhoneNumber.length >= countryCodeLength) {
35+
rawPhoneNumber = [normalizedPhoneNumber substringFromIndex:countryCodeLength];
36+
}
37+
}
38+
if (!rawPhoneNumber) {
39+
rawPhoneNumber = normalizedPhoneNumber;
40+
countryCode = [codes countryCodeInfoFromDeviceLocale];
41+
}
42+
return [self initWithRawPhoneNumber:rawPhoneNumber countryCode:countryCode];
43+
}
44+
45+
- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber
46+
rawPhoneNumber:(NSString *)rawPhoneNumber
47+
countryCode:(FUICountryCodeInfo *)countryCode {
48+
NSAssert(normalizedPhoneNumber, @"normalizedPhoneNumber can't be nil");
49+
NSAssert(rawPhoneNumber, @"rawPhoneNumber can't be nil");
50+
NSAssert(countryCode, @"countryCode can't be nil");
51+
if (self = [super init]) {
52+
_countryCode = countryCode;
53+
_rawPhoneNumber = rawPhoneNumber;
54+
_normalizedPhoneNumber = normalizedPhoneNumber;
55+
}
56+
return self;
57+
}
58+
59+
- (instancetype)initWithRawPhoneNumber:(NSString *)rawPhoneNumber
60+
countryCode:(FUICountryCodeInfo *)countryCode {
61+
NSAssert(rawPhoneNumber, @"rawPhoneNumber can't be nil");
62+
NSAssert(countryCode, @"countryCode can't be nil");
63+
NSString *dialCode = countryCode.dialCode;
64+
NSAssert(dialCode.length, @"dialCode can't be empty");
65+
if ([dialCode characterAtIndex:0] != '+') {
66+
dialCode = [@"+" stringByAppendingString:dialCode];
67+
}
68+
NSString *normalizedPhoneNumber = [NSString stringWithFormat:@"%@%@", dialCode, rawPhoneNumber];
69+
70+
return [self initWithNormalizedPhoneNumber:normalizedPhoneNumber
71+
rawPhoneNumber:rawPhoneNumber
72+
countryCode:countryCode];
73+
}
74+
75+
- (BOOL)validate:(NSError *__autoreleasing _Nullable *_Nullable)errorRef {
76+
// The first character is always the '+'
77+
BOOL firstCharacterIsPlus = [_normalizedPhoneNumber characterAtIndex:0] == '+';
78+
if (!firstCharacterIsPlus) {
79+
if (errorRef) {
80+
NSString *message = [NSString stringWithFormat:@"Phone number %@ should start with '+'",
81+
_normalizedPhoneNumber];
82+
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : message };
83+
*errorRef = [NSError errorWithDomain:FUIPhoneNumberValidationErrorDomain
84+
code:FUIPhoneNumberValidationErrorMissingPlus
85+
userInfo:userInfo];
86+
}
87+
return false;
88+
}
89+
BOOL containsMoreThanThePlus = self.normalizedPhoneNumber.length > 1;
90+
if (!containsMoreThanThePlus) {
91+
if (errorRef) {
92+
NSString *message = [NSString stringWithFormat:@"Phone number %@ should have only one '+'",
93+
_normalizedPhoneNumber];
94+
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : message };
95+
*errorRef = [NSError errorWithDomain:FUIPhoneNumberValidationErrorDomain
96+
code:FUIPhoneNumberValidationErrorMissingDialCode
97+
userInfo:userInfo];
98+
}
99+
return false;
100+
}
101+
BOOL containsMoreThanTheCountryCode =
102+
self.normalizedPhoneNumber.length > 1 + self.countryCode.dialCode.length;
103+
if (!containsMoreThanTheCountryCode) {
104+
if (errorRef) {
105+
NSString *message =
106+
[NSString stringWithFormat:@"Phone number %@ should have only one country code",
107+
_normalizedPhoneNumber];
108+
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : message };
109+
*errorRef = [NSError errorWithDomain:FUIPhoneNumberValidationErrorDomain
110+
code:FUIPhoneNumberValidationErrorMissingNumber
111+
userInfo:userInfo];
112+
}
113+
return false;
114+
}
115+
return true;
116+
}
117+
118+
@end
119+
120+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)