Skip to content

Commit 91a6974

Browse files
pragatimodirenkelvin
andauthored
custom auth domain changes (#11619)
Co-authored-by: renkelvin <[email protected]>
1 parent 681e740 commit 91a6974

File tree

7 files changed

+170
-15
lines changed

7 files changed

+170
-15
lines changed

FirebaseAuth/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# 10.16.0
2+
- [added] Added custom auth domain support in recaptcha v2 authentication flows. (#7553)
3+
14
# 10.14.0
25
- [added] Added reCAPTCHA verification support in email authentication flows. (#11231)
36

FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuth.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,13 @@ NS_SWIFT_NAME(Auth)
355355
*/
356356
@property(nonatomic, strong, nullable) NSData *APNSToken API_UNAVAILABLE(macos, tvos, watchos);
357357

358+
/**
359+
* @property customAuthDomain
360+
* @brief The custom authentication domain used to handle all sign-in redirects. End-users will see
361+
* this domain when signing in. This domain must be allowlisted in the Firebase Console.
362+
*/
363+
@property(nonatomic, copy, nullable) NSString *customAuthDomain;
364+
358365
/** @fn init
359366
@brief Please access auth instances using `Auth.auth()` and `Auth.auth(app:)`.
360367
*/

FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ typedef void (^FIRFetchAuthDomainCallback)(NSString *_Nullable authDomain,
5959
authType:(NSString *)authType
6060
callbackScheme:(NSString *)callbackScheme;
6161

62+
/** @fn extractDomain:urlString
63+
@brief Strips url of scheme and path string to extract domain name
64+
@param urlString URL string for domain
65+
*/
66+
+ (NSString *)extractDomain:(NSString *)urlString;
67+
6268
/** @fn fetchAuthDomainWithCompletion:completion:
6369
@brief Fetches the auth domain associated with the Firebase Project.
6470
@param completion The callback invoked after the auth domain has been constructed or an error

FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.m

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,31 @@ + (BOOL)isExpectedCallbackURL:(nullable NSURL *)URL
8484
return NO;
8585
}
8686

87+
+ (NSString *)extractDomain:(NSString *)urlString {
88+
// Remove trailing slashes
89+
urlString = [urlString
90+
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"/"]];
91+
92+
// Check for the presence of a scheme (e.g., http:// or https://)
93+
NSRange range = [urlString rangeOfString:@"http://" options:NSCaseInsensitiveSearch];
94+
if (range.location != NSNotFound) {
95+
urlString = [urlString stringByReplacingCharactersInRange:range withString:@""];
96+
} else {
97+
range = [urlString rangeOfString:@"https://" options:NSCaseInsensitiveSearch];
98+
if (range.location != NSNotFound) {
99+
urlString = [urlString stringByReplacingCharactersInRange:range withString:@""];
100+
}
101+
}
102+
103+
// Split the URL by "/"
104+
NSArray *urlComponents = [urlString componentsSeparatedByString:@"/"];
105+
106+
// The domain is the first component after removing the scheme
107+
NSString *domain = urlComponents[0];
108+
109+
return domain;
110+
}
111+
87112
+ (void)fetchAuthDomainWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
88113
completion:(FIRFetchAuthDomainCallback)completion {
89114
if (requestConfiguration.emulatorHostAndPort) {
@@ -104,22 +129,42 @@ + (void)fetchAuthDomainWithRequestConfiguration:(FIRAuthRequestConfiguration *)r
104129
return;
105130
}
106131
// Look up an authorized domain ends with one of the supportedAuthDomains.
107-
// The sequence of supportedAuthDomains matters. ("firebaseapp.com", "web.app")
108-
// The searching ends once the first valid suportedAuthDomain is found.
132+
// The searching ends once the first valid supportedAuthDomain is found.
109133
NSString *authDomain;
110-
for (NSString *domain in response.authorizedDomains) {
111-
for (NSString *suportedAuthDomain in [self supportedAuthDomains]) {
112-
NSInteger index = domain.length - suportedAuthDomain.length;
113-
if (index >= 2) {
114-
if ([domain hasSuffix:suportedAuthDomain] &&
115-
domain.length >= suportedAuthDomain.length + 2) {
116-
authDomain = domain;
117-
break;
118-
}
134+
NSString *customAuthDomain = requestConfiguration.auth.customAuthDomain;
135+
if (customAuthDomain) {
136+
customAuthDomain = [FIRAuthWebUtils extractDomain:customAuthDomain];
137+
BOOL isCustomAuthDomainAuthorized = NO;
138+
for (NSString *domain in response.authorizedDomains) {
139+
if ([customAuthDomain isEqualToString:domain]) {
140+
authDomain = customAuthDomain;
141+
isCustomAuthDomainAuthorized = YES;
142+
break;
119143
}
120144
}
121-
if (authDomain != nil) {
122-
break;
145+
if (!isCustomAuthDomainAuthorized) {
146+
NSError *customDomainError =
147+
[FIRAuthErrorUtils unauthorizedDomainErrorWithMessage:
148+
@"Error while validating application identity: The "
149+
@"configured custom domain is not allowlisted."];
150+
completion(nil, customDomainError);
151+
return;
152+
}
153+
} else {
154+
for (NSString *domain in response.authorizedDomains) {
155+
for (NSString *supportedAuthDomain in [self supportedAuthDomains]) {
156+
NSInteger index = domain.length - supportedAuthDomain.length;
157+
if (index >= 2) {
158+
if ([domain hasSuffix:supportedAuthDomain] &&
159+
domain.length >= supportedAuthDomain.length + 2) {
160+
authDomain = domain;
161+
break;
162+
}
163+
}
164+
}
165+
if (authDomain != nil) {
166+
break;
167+
}
123168
}
124169
}
125170
if (!authDomain.length) {

FirebaseAuth/Tests/Sample/Sample/MainViewController+Auth.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN
2929

3030
- (void)signInAnonymouslyWithCallback:(nullable FIRAuthDataResultCallback)callback;
3131

32+
- (void)setAuthDomain;
33+
3234
@end
3335

3436
NS_ASSUME_NONNULL_END

FirebaseAuth/Tests/Sample/Sample/MainViewController+Auth.m

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ - (StaticContentTableViewSection *)authSection {
3131
[StaticContentTableViewCell cellWithTitle:@"Sign out"
3232
action:^{ [weakSelf signOut]; }],
3333
[StaticContentTableViewCell cellWithTitle:@"Initialize Recaptcha Config"
34-
action:^{ [weakSelf initializeRecaptchaConfig]; }]
35-
]];
34+
action:^{ [weakSelf initializeRecaptchaConfig]; }],
35+
[StaticContentTableViewCell cellWithTitle:@"Set Auth Domain"
36+
action:^{ [weakSelf setAuthDomain]; }]
37+
]];
3638
}
3739

3840
- (void)signInAnonymously {
@@ -84,6 +86,23 @@ - (void)initializeRecaptchaConfig {
8486
}];
8587
}
8688

89+
- (void)setAuthDomain {
90+
[self showTextInputPromptWithMessage:@"Auth Domain:"
91+
completionBlock:^(BOOL userPressedOK, NSString *_Nullable customAuthDomain) {
92+
if (userPressedOK && customAuthDomain.length) {
93+
FIRAuth *auth = [AppManager auth];
94+
if(!auth) {
95+
[self logFailedTest:@"Could not obtain auth object."];
96+
return;
97+
}
98+
auth.customAuthDomain = customAuthDomain;
99+
[self logSuccess:[NSString stringWithFormat:@"Successfully set auth domain to: %@", customAuthDomain]];
100+
}
101+
return;
102+
}];
103+
}
104+
105+
87106
@end
88107

89108
NS_ASSUME_NONNULL_END
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2023 Google LLC
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 <XCTest/XCTest.h>
18+
#import "FirebaseAuth/Sources/Utilities/FIRAuthWebUtils.h"
19+
20+
/** @class FIRAuthWebUtilsTests
21+
@brief Tests for the FIRAuthWebUtils class.
22+
*/
23+
@interface FIRAuthWebUtilsTests : XCTestCase
24+
@end
25+
26+
@implementation FIRAuthWebUtilsTests
27+
28+
/** @fn testExtractDomainWithHTTP
29+
@brief Test case for extracting the domain from a URL with "http://" scheme.
30+
*/
31+
- (void)testExtractDomainWithHTTP {
32+
NSString *urlString = @"http://www.example.com/path/to/resource";
33+
NSString *domain = [FIRAuthWebUtils extractDomain:urlString];
34+
XCTAssertEqualObjects(domain, @"www.example.com");
35+
}
36+
37+
/** @fn testExtractDomainWithHTTPS
38+
@brief Test case for extracting the domain from a URL with "https://" scheme.
39+
*/
40+
- (void)testExtractDomainWithHTTPS {
41+
NSString *urlString = @"https://www.example.com/path/to/resource";
42+
NSString *domain = [FIRAuthWebUtils extractDomain:urlString];
43+
XCTAssertEqualObjects(domain, @"www.example.com");
44+
}
45+
46+
/** @fn testExtractDomainWithoutScheme
47+
@brief Test case for extracting the domain from a URL without a scheme (assumes HTTP by default).
48+
*/
49+
- (void)testExtractDomainWithoutScheme {
50+
NSString *urlString = @"www.example.com/path/to/resource";
51+
NSString *domain = [FIRAuthWebUtils extractDomain:urlString];
52+
XCTAssertEqualObjects(domain, @"www.example.com");
53+
}
54+
55+
/** @fn testExtractDomainWithTrailingSlashes
56+
@brief Test case for extracting the domain from a URL with trailing slashes.
57+
*/
58+
- (void)testExtractDomainWithTrailingSlashes {
59+
NSString *urlString = @"http://www.example.com/////";
60+
NSString *domain = [FIRAuthWebUtils extractDomain:urlString];
61+
XCTAssertEqualObjects(domain, @"www.example.com");
62+
}
63+
64+
/** @fn testExtractDomainWithStringDomain
65+
@brief Test case for extracting the domain from a string that represents just the domain itself.
66+
*/
67+
- (void)testExtractDomainWithStringDomain {
68+
NSString *urlString = @"example.com";
69+
NSString *domain = [FIRAuthWebUtils extractDomain:urlString];
70+
XCTAssertEqualObjects(domain, @"example.com");
71+
}
72+
73+
@end

0 commit comments

Comments
 (0)