Skip to content

Commit e129780

Browse files
feat(firebase_auth): add custom auth domain setter to Firebase Auth (#12218)
Co-authored-by: russellwheatley <[email protected]>
1 parent b12d850 commit e129780

File tree

15 files changed

+161
-9
lines changed

15 files changed

+161
-9
lines changed

packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ static FirebaseAuth getAuthFromPigeon(
142142
auth.setCustomAuthDomain(customDomain);
143143
}
144144

145+
// Auth's `getCustomAuthDomain` supersedes value from `customAuthDomain` map set by `initializeApp`
146+
if (pigeonApp.getCustomAuthDomain() != null) {
147+
auth.setCustomAuthDomain(pigeonApp.getCustomAuthDomain());
148+
}
149+
145150
return auth;
146151
}
147152

packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,16 @@ public void setTenantId(@Nullable String setterArg) {
363363
this.tenantId = setterArg;
364364
}
365365

366+
private @Nullable String customAuthDomain;
367+
368+
public @Nullable String getCustomAuthDomain() {
369+
return customAuthDomain;
370+
}
371+
372+
public void setCustomAuthDomain(@Nullable String setterArg) {
373+
this.customAuthDomain = setterArg;
374+
}
375+
366376
/** Constructor is non-public to enforce null safety; use Builder. */
367377
AuthPigeonFirebaseApp() {}
368378

@@ -382,19 +392,28 @@ public static final class Builder {
382392
return this;
383393
}
384394

395+
private @Nullable String customAuthDomain;
396+
397+
public @NonNull Builder setCustomAuthDomain(@Nullable String setterArg) {
398+
this.customAuthDomain = setterArg;
399+
return this;
400+
}
401+
385402
public @NonNull AuthPigeonFirebaseApp build() {
386403
AuthPigeonFirebaseApp pigeonReturn = new AuthPigeonFirebaseApp();
387404
pigeonReturn.setAppName(appName);
388405
pigeonReturn.setTenantId(tenantId);
406+
pigeonReturn.setCustomAuthDomain(customAuthDomain);
389407
return pigeonReturn;
390408
}
391409
}
392410

393411
@NonNull
394412
ArrayList<Object> toList() {
395-
ArrayList<Object> toListResult = new ArrayList<Object>(2);
413+
ArrayList<Object> toListResult = new ArrayList<Object>(3);
396414
toListResult.add(appName);
397415
toListResult.add(tenantId);
416+
toListResult.add(customAuthDomain);
398417
return toListResult;
399418
}
400419

@@ -404,6 +423,8 @@ ArrayList<Object> toList() {
404423
pigeonResult.setAppName((String) appName);
405424
Object tenantId = list.get(1);
406425
pigeonResult.setTenantId((String) tenantId);
426+
Object customAuthDomain = list.get(2);
427+
pigeonResult.setCustomAuthDomain((String) customAuthDomain);
407428
return pigeonResult;
408429
}
409430
}

packages/firebase_auth/firebase_auth/ios/Classes/FLTFirebaseAuthPlugin.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,10 @@ - (FIRAuth *_Nullable)getFIRAuthFromAppNameFromPigeon:(AuthPigeonFirebaseApp *)p
635635

636636
auth.tenantID = pigeonApp.tenantId;
637637
auth.customAuthDomain = [FLTFirebaseCorePlugin getCustomDomain:app.name];
638+
// Auth's `customAuthDomain` supersedes value from `getCustomDomain` set by `initializeApp`
639+
if (pigeonApp.customAuthDomain != nil) {
640+
auth.customAuthDomain = pigeonApp.customAuthDomain;
641+
}
638642

639643
return auth;
640644
}

packages/firebase_auth/firebase_auth/ios/Classes/Public/firebase_auth_messages.g.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,12 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) {
9191
@interface AuthPigeonFirebaseApp : NSObject
9292
/// `init` unavailable to enforce nonnull fields, see the `make` class method.
9393
- (instancetype)init NS_UNAVAILABLE;
94-
+ (instancetype)makeWithAppName:(NSString *)appName tenantId:(nullable NSString *)tenantId;
94+
+ (instancetype)makeWithAppName:(NSString *)appName
95+
tenantId:(nullable NSString *)tenantId
96+
customAuthDomain:(nullable NSString *)customAuthDomain;
9597
@property(nonatomic, copy) NSString *appName;
9698
@property(nonatomic, copy, nullable) NSString *tenantId;
99+
@property(nonatomic, copy, nullable) NSString *customAuthDomain;
97100
@end
98101

99102
@interface PigeonActionCodeInfoData : NSObject

packages/firebase_auth/firebase_auth/ios/Classes/firebase_auth_messages.g.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,17 +238,21 @@ - (NSArray *)toList {
238238
@end
239239

240240
@implementation AuthPigeonFirebaseApp
241-
+ (instancetype)makeWithAppName:(NSString *)appName tenantId:(nullable NSString *)tenantId {
241+
+ (instancetype)makeWithAppName:(NSString *)appName
242+
tenantId:(nullable NSString *)tenantId
243+
customAuthDomain:(nullable NSString *)customAuthDomain {
242244
AuthPigeonFirebaseApp *pigeonResult = [[AuthPigeonFirebaseApp alloc] init];
243245
pigeonResult.appName = appName;
244246
pigeonResult.tenantId = tenantId;
247+
pigeonResult.customAuthDomain = customAuthDomain;
245248
return pigeonResult;
246249
}
247250
+ (AuthPigeonFirebaseApp *)fromList:(NSArray *)list {
248251
AuthPigeonFirebaseApp *pigeonResult = [[AuthPigeonFirebaseApp alloc] init];
249252
pigeonResult.appName = GetNullableObjectAtIndex(list, 0);
250253
NSAssert(pigeonResult.appName != nil, @"");
251254
pigeonResult.tenantId = GetNullableObjectAtIndex(list, 1);
255+
pigeonResult.customAuthDomain = GetNullableObjectAtIndex(list, 2);
252256
return pigeonResult;
253257
}
254258
+ (nullable AuthPigeonFirebaseApp *)nullableFromList:(NSArray *)list {
@@ -258,6 +262,7 @@ - (NSArray *)toList {
258262
return @[
259263
(self.appName ?: [NSNull null]),
260264
(self.tenantId ?: [NSNull null]),
265+
(self.customAuthDomain ?: [NSNull null]),
261266
];
262267
}
263268
@end

packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,35 @@ class FirebaseAuth extends FirebasePluginPlatform {
157157
_delegate.tenantId = tenantId;
158158
}
159159

160+
/// The current Auth instance's custom auth domain.
161+
/// The auth domain used to handle redirects from OAuth provides, for example
162+
/// "my-awesome-app.firebaseapp.com". By default, this is set to `null` and
163+
/// default auth domain is used.
164+
///
165+
/// If not `null`, this value will supersede `authDomain` property set in `initializeApp`.
166+
String? get customAuthDomain {
167+
return _delegate.customAuthDomain;
168+
}
169+
170+
/// Set the current Auth instance's auth domain for apple and android platforms.
171+
/// The auth domain used to handle redirects from OAuth provides, for example
172+
/// "my-awesome-app.firebaseapp.com". By default, this is set to `null` and
173+
/// default auth domain is used.
174+
///
175+
/// If not `null`, this value will supersede `authDomain` property set in `initializeApp`.
176+
set customAuthDomain(String? customAuthDomain) {
177+
// Web and windows do not support setting custom auth domains on the auth instance
178+
if (defaultTargetPlatform == TargetPlatform.windows || kIsWeb) {
179+
final message = defaultTargetPlatform == TargetPlatform.windows
180+
? 'Cannot set custom auth domain on a FirebaseAuth instance for windows platform'
181+
: 'Cannot set custom auth domain on a FirebaseAuth instance. Set the custom auth domain on `FirebaseOptions.authDomain` instance and pass into `Firebase.initializeApp()` instead.';
182+
throw UnimplementedError(
183+
message,
184+
);
185+
}
186+
_delegate.customAuthDomain = customAuthDomain;
187+
}
188+
160189
/// Applies a verification code sent to the user by email or other out-of-band
161190
/// mechanism.
162191
///

packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:firebase_auth/firebase_auth.dart';
1010
import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart';
1111
import 'package:firebase_auth_platform_interface/src/method_channel/method_channel_firebase_auth.dart';
1212
import 'package:firebase_core/firebase_core.dart';
13+
import 'package:flutter/foundation.dart';
1314
import 'package:flutter_test/flutter_test.dart';
1415
import 'package:mockito/mockito.dart';
1516
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
@@ -230,6 +231,37 @@ void main() {
230231
});
231232
});
232233

234+
group('customAuthDomain', () {
235+
test('set customAuthDomain should call delegate method', () async {
236+
// Each test uses a unique FirebaseApp instance to avoid sharing state
237+
final app = await Firebase.initializeApp(
238+
name: 'customAuthDomainTest',
239+
options: const FirebaseOptions(
240+
apiKey: 'apiKey',
241+
appId: 'appId',
242+
messagingSenderId: 'messagingSenderId',
243+
projectId: 'projectId'));
244+
245+
FirebaseAuthPlatform.instance =
246+
FakeFirebaseAuthPlatform(customAuthDomain: 'foo');
247+
auth = FirebaseAuth.instanceFor(app: app);
248+
249+
expect(auth.customAuthDomain, 'foo');
250+
if (defaultTargetPlatform == TargetPlatform.windows || kIsWeb) {
251+
try {
252+
auth.customAuthDomain = 'bar';
253+
} on UnimplementedError catch (e) {
254+
expect(e.message, contains('Cannot set auth domain'));
255+
}
256+
} else {
257+
auth.customAuthDomain = 'bar';
258+
259+
expect(auth.customAuthDomain, 'bar');
260+
expect(FirebaseAuthPlatform.instance.customAuthDomain, 'bar');
261+
}
262+
});
263+
});
264+
233265
group('languageCode', () {
234266
test('.languageCode should call delegate method', () {
235267
auth.languageCode;
@@ -1026,11 +1058,14 @@ class MockFirebaseAuth extends Mock
10261058
class FakeFirebaseAuthPlatform extends Fake
10271059
with MockPlatformInterfaceMixin
10281060
implements FirebaseAuthPlatform {
1029-
FakeFirebaseAuthPlatform({this.tenantId});
1061+
FakeFirebaseAuthPlatform({this.tenantId, this.customAuthDomain});
10301062

10311063
@override
10321064
String? tenantId;
10331065

1066+
@override
1067+
String? customAuthDomain;
1068+
10341069
@override
10351070
FirebaseAuthPlatform delegateFor(
10361071
{required FirebaseApp app, Persistence? persistence}) {

packages/firebase_auth/firebase_auth/windows/messages.g.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,15 @@ PigeonMultiFactorInfo PigeonMultiFactorInfo::FromEncodableList(
200200
AuthPigeonFirebaseApp::AuthPigeonFirebaseApp(const std::string& app_name)
201201
: app_name_(app_name) {}
202202

203-
AuthPigeonFirebaseApp::AuthPigeonFirebaseApp(const std::string& app_name,
204-
const std::string* tenant_id)
203+
AuthPigeonFirebaseApp::AuthPigeonFirebaseApp(
204+
const std::string& app_name, const std::string* tenant_id,
205+
const std::string* custom_auth_domain)
205206
: app_name_(app_name),
206207
tenant_id_(tenant_id ? std::optional<std::string>(*tenant_id)
207-
: std::nullopt) {}
208+
: std::nullopt),
209+
custom_auth_domain_(custom_auth_domain
210+
? std::optional<std::string>(*custom_auth_domain)
211+
: std::nullopt) {}
208212

209213
const std::string& AuthPigeonFirebaseApp::app_name() const { return app_name_; }
210214

@@ -225,11 +229,27 @@ void AuthPigeonFirebaseApp::set_tenant_id(std::string_view value_arg) {
225229
tenant_id_ = value_arg;
226230
}
227231

232+
const std::string* AuthPigeonFirebaseApp::custom_auth_domain() const {
233+
return custom_auth_domain_ ? &(*custom_auth_domain_) : nullptr;
234+
}
235+
236+
void AuthPigeonFirebaseApp::set_custom_auth_domain(
237+
const std::string_view* value_arg) {
238+
custom_auth_domain_ =
239+
value_arg ? std::optional<std::string>(*value_arg) : std::nullopt;
240+
}
241+
242+
void AuthPigeonFirebaseApp::set_custom_auth_domain(std::string_view value_arg) {
243+
custom_auth_domain_ = value_arg;
244+
}
245+
228246
EncodableList AuthPigeonFirebaseApp::ToEncodableList() const {
229247
EncodableList list;
230-
list.reserve(2);
248+
list.reserve(3);
231249
list.push_back(EncodableValue(app_name_));
232250
list.push_back(tenant_id_ ? EncodableValue(*tenant_id_) : EncodableValue());
251+
list.push_back(custom_auth_domain_ ? EncodableValue(*custom_auth_domain_)
252+
: EncodableValue());
233253
return list;
234254
}
235255

@@ -240,6 +260,11 @@ AuthPigeonFirebaseApp AuthPigeonFirebaseApp::FromEncodableList(
240260
if (!encodable_tenant_id.IsNull()) {
241261
decoded.set_tenant_id(std::get<std::string>(encodable_tenant_id));
242262
}
263+
auto& encodable_custom_auth_domain = list[2];
264+
if (!encodable_custom_auth_domain.IsNull()) {
265+
decoded.set_custom_auth_domain(
266+
std::get<std::string>(encodable_custom_auth_domain));
267+
}
243268
return decoded;
244269
}
245270

packages/firebase_auth/firebase_auth/windows/messages.g.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ class AuthPigeonFirebaseApp {
213213

214214
// Constructs an object setting all fields.
215215
explicit AuthPigeonFirebaseApp(const std::string& app_name,
216-
const std::string* tenant_id);
216+
const std::string* tenant_id,
217+
const std::string* custom_auth_domain);
217218

218219
const std::string& app_name() const;
219220
void set_app_name(std::string_view value_arg);
@@ -222,6 +223,10 @@ class AuthPigeonFirebaseApp {
222223
void set_tenant_id(const std::string_view* value_arg);
223224
void set_tenant_id(std::string_view value_arg);
224225

226+
const std::string* custom_auth_domain() const;
227+
void set_custom_auth_domain(const std::string_view* value_arg);
228+
void set_custom_auth_domain(std::string_view value_arg);
229+
225230
private:
226231
static AuthPigeonFirebaseApp FromEncodableList(
227232
const flutter::EncodableList& list);
@@ -242,6 +247,7 @@ class AuthPigeonFirebaseApp {
242247
friend class GenerateInterfacesCodecSerializer;
243248
std::string app_name_;
244249
std::optional<std::string> tenant_id_;
250+
std::optional<std::string> custom_auth_domain_;
245251
};
246252

247253
// Generated class from Pigeon that represents data sent in messages.
@@ -535,6 +541,7 @@ class PigeonUserDetails {
535541

536542
const flutter::EncodableList& provider_data() const;
537543
void set_provider_data(const flutter::EncodableList& value_arg);
544+
538545
static PigeonUserDetails FromEncodableList(
539546
const flutter::EncodableList& list);
540547
flutter::EncodableList ToEncodableList() const;

packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform {
6262
return AuthPigeonFirebaseApp(
6363
appName: app.name,
6464
tenantId: tenantId,
65+
customAuthDomain: customAuthDomain,
6566
);
6667
}
6768

packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class MethodChannelMultiFactor extends MultiFactorPlatform {
1919
return AuthPigeonFirebaseApp(
2020
appName: auth.app.name,
2121
tenantId: auth.tenantId,
22+
customAuthDomain: auth.customAuthDomain,
2223
);
2324
}
2425

packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class MethodChannelUser extends UserPlatform {
2525
return AuthPigeonFirebaseApp(
2626
appName: auth.app.name,
2727
tenantId: auth.tenantId,
28+
customAuthDomain: auth.customAuthDomain,
2829
);
2930
}
3031

packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,20 @@ class AuthPigeonFirebaseApp {
128128
AuthPigeonFirebaseApp({
129129
required this.appName,
130130
this.tenantId,
131+
this.customAuthDomain,
131132
});
132133

133134
String appName;
134135

135136
String? tenantId;
136137

138+
String? customAuthDomain;
139+
137140
Object encode() {
138141
return <Object?>[
139142
appName,
140143
tenantId,
144+
customAuthDomain,
141145
];
142146
}
143147

@@ -146,6 +150,7 @@ class AuthPigeonFirebaseApp {
146150
return AuthPigeonFirebaseApp(
147151
appName: result[0]! as String,
148152
tenantId: result[1] as String?,
153+
customAuthDomain: result[2] as String?,
149154
);
150155
}
151156
}

packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ abstract class FirebaseAuthPlatform extends PlatformInterface {
3333
/// parent project. By default, this is set to `null`.
3434
String? tenantId;
3535

36+
/// Set the current Auth instance's auth domain for apple and android platforms.
37+
/// The auth domain used to handle redirects from OAuth provides, for example
38+
/// "my-awesome-app.firebaseapp.com". By default, this is set to `null` and
39+
/// default auth domain is used.
40+
///
41+
/// If not `null`, this value will supersede `authDomain` property set in `initializeApp`.
42+
String? customAuthDomain;
43+
3644
/// Create an instance using [app]
3745
FirebaseAuthPlatform({this.appInstance}) : super(token: _token);
3846

packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ class AuthPigeonFirebaseApp {
6666
const AuthPigeonFirebaseApp({
6767
required this.appName,
6868
required this.tenantId,
69+
required this.customAuthDomain,
6970
});
7071

7172
final String appName;
7273
final String? tenantId;
74+
final String? customAuthDomain;
7375
}
7476

7577
/// The type of operation that generated the action code from calling

0 commit comments

Comments
 (0)