Skip to content

Commit a1f4710

Browse files
committed
feat(auth, authDomain): implement FirebaseOptions.authDomain on Auth
JS SDK has FirebaseOptions.authDomain, and while the native SDKs do not directly have this FirebaseOptions key, they do have Auth.customAuthDomain - so take the key if it is set during initializeApp, store it, then as Auth instances are initialized, set it in if it exists
1 parent d7589ea commit a1f4710

File tree

11 files changed

+143
-1
lines changed

11 files changed

+143
-1
lines changed

jest.setup.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jest.doMock('react-native', () => {
4646
addIdTokenListener: jest.fn(),
4747
setTenantId: jest.fn(),
4848
useEmulator: jest.fn(),
49+
configureAuthDomain: jest.fn(),
4950
},
5051
RNFBCrashlyticsModule: {},
5152
RNFBDatabaseModule: {

packages/app/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppModule.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*
1818
*/
1919

20+
import android.util.Log;
2021
import com.facebook.react.bridge.Promise;
2122
import com.facebook.react.bridge.ReactApplicationContext;
2223
import com.facebook.react.bridge.ReactMethod;
@@ -38,6 +39,8 @@
3839
public class ReactNativeFirebaseAppModule extends ReactNativeFirebaseModule {
3940
private static final String TAG = "App";
4041

42+
public static Map<String, String> authDomains = new HashMap<>();
43+
4144
ReactNativeFirebaseAppModule(ReactApplicationContext reactContext) {
4245
super(reactContext, TAG);
4346
}
@@ -52,11 +55,22 @@ public void initialize() {
5255
public void initializeApp(ReadableMap options, ReadableMap appConfig, Promise promise) {
5356
FirebaseApp firebaseApp =
5457
RCTConvertFirebase.readableMapToFirebaseApp(options, appConfig, getContext());
58+
ReactNativeFirebaseAppModule.configureAuthDomain(
59+
appConfig.getString("name"), options.getString("authDomain"));
5560

5661
WritableMap firebaseAppMap = RCTConvertFirebase.firebaseAppToWritableMap(firebaseApp);
5762
promise.resolve(firebaseAppMap);
5863
}
5964

65+
public static void configureAuthDomain(String name, String authDomain) {
66+
if (authDomain != null) {
67+
Log.d(TAG, name + " custom authDomain " + authDomain);
68+
authDomains.put(name, authDomain);
69+
} else {
70+
authDomains.remove(name);
71+
}
72+
}
73+
6074
@ReactMethod
6175
public void setAutomaticDataCollectionEnabled(String appName, Boolean enabled) {
6276
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);

packages/app/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.facebook.react.bridge.WritableMap;
2626
import com.google.firebase.FirebaseApp;
2727
import com.google.firebase.FirebaseOptions;
28+
import io.invertase.firebase.app.ReactNativeFirebaseAppModule;
2829
import java.util.HashMap;
2930
import java.util.List;
3031
import java.util.Map;
@@ -56,6 +57,10 @@ public static Map<String, Object> firebaseAppToMap(FirebaseApp firebaseApp) {
5657
options.put("messagingSenderId", appOptions.getGcmSenderId());
5758
options.put("storageBucket", appOptions.getStorageBucket());
5859

60+
if (ReactNativeFirebaseAppModule.authDomains.get(name) != null) {
61+
options.put("authDomain", ReactNativeFirebaseAppModule.authDomains.get(name));
62+
}
63+
5964
root.put("options", options);
6065
root.put("appConfig", appConfig);
6166

packages/app/ios/RNFBApp/RNFBAppModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
@interface RNFBAppModule : NSObject <RCTBridgeModule>
2323

24+
+ (NSString *)getCustomDomain:(NSString *)appName;
25+
2426
- (void)setLogLevel:(NSString *)logLevel;
2527

2628
@end

packages/app/ios/RNFBApp/RNFBAppModule.m

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,52 @@ - (void)invalidate {
168168
#pragma mark Firebase App Methods
169169

170170
RCT_EXPORT_METHOD(initializeApp
171-
: (FIROptions *)firOptions appConfig
171+
: (NSDictionary *)options appConfig
172172
: (NSDictionary *)appConfig resolver
173173
: (RCTPromiseResolveBlock)resolve rejecter
174174
: (RCTPromiseRejectBlock)reject) {
175175
RCTUnsafeExecuteOnMainQueueSync(^{
176176
FIRApp *firApp;
177177
NSString *appName = [appConfig valueForKey:@"name"];
178178

179+
NSString *appId = [options valueForKey:@"appId"];
180+
NSString *messagingSenderId = [options valueForKey:@"messagingSenderId"];
181+
FIROptions *firOptions = [[FIROptions alloc] initWithGoogleAppID:appId
182+
GCMSenderID:messagingSenderId];
183+
firOptions.APIKey = [options valueForKey:@"apiKey"];
184+
firOptions.projectID = [options valueForKey:@"projectId"];
185+
// kFirebaseOptionsDatabaseUrl
186+
if (![[options valueForKey:@"databaseURL"] isEqual:[NSNull null]]) {
187+
firOptions.databaseURL = [options valueForKey:@"databaseURL"];
188+
}
189+
// kFirebaseOptionsStorageBucket
190+
if (![[options valueForKey:@"storageBucket"] isEqual:[NSNull null]]) {
191+
firOptions.storageBucket = [options valueForKey:@"storageBucket"];
192+
}
193+
// kFirebaseOptionsDeepLinkURLScheme
194+
if (![[options valueForKey:@"deepLinkURLScheme"] isEqual:[NSNull null]]) {
195+
firOptions.deepLinkURLScheme = [options valueForKey:@"deepLinkURLScheme"];
196+
}
197+
// kFirebaseOptionsIosBundleId
198+
if (![[options valueForKey:@"iosBundleId"] isEqual:[NSNull null]]) {
199+
firOptions.bundleID = [options valueForKey:@"iosBundleId"];
200+
}
201+
// kFirebaseOptionsIosClientId
202+
if (![[options valueForKey:@"iosClientId"] isEqual:[NSNull null]]) {
203+
firOptions.clientID = [options valueForKey:@"iosClientId"];
204+
}
205+
// kFirebaseOptionsAppGroupId
206+
if (![[options valueForKey:@"appGroupId"] isEqual:[NSNull null]]) {
207+
firOptions.appGroupID = [options valueForKey:@"appGroupId"];
208+
}
209+
210+
if ([options valueForKey:@"authDomain"] != nil) {
211+
DLog(@"RNFBAuth app: %@ customAuthDomain: %@", appName, [options valueForKey:@"authDomain"]);
212+
if (customAuthDomains == nil) {
213+
customAuthDomains = [[NSMutableDictionary alloc] init];
214+
}
215+
customAuthDomains[appName] = [options valueForKey:@"authDomain"];
216+
}
179217
@try {
180218
if (!appName || [appName isEqualToString:DEFAULT_APP_DISPLAY_NAME]) {
181219
[FIRApp configureWithOptions:firOptions];
@@ -195,6 +233,13 @@ - (void)invalidate {
195233
});
196234
}
197235

236+
static NSMutableDictionary<NSString *, NSString *> *customAuthDomains;
237+
238+
+ (NSString *)getCustomDomain:(NSString *)appName {
239+
DLog(@"authDomains: %@", customAuthDomains);
240+
return customAuthDomains[appName];
241+
}
242+
198243
RCT_EXPORT_METHOD(setLogLevel : (NSString *)logLevel) {
199244
int level = FIRLoggerLevelError;
200245
if ([logLevel isEqualToString:@"verbose"]) {

packages/app/ios/RNFBApp/RNFBSharedUtils.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
#import "RNFBSharedUtils.h"
19+
#import "RNFBAppModule.h"
1920
#import "RNFBJSON.h"
2021
#import "RNFBMeta.h"
2122
#import "RNFBPreferences.h"
@@ -65,6 +66,10 @@ + (NSDictionary *)firAppToDictionary:(FIRApp *)firApp {
6566
firAppOptions[@"clientId"] = firOptions.clientID;
6667
firAppOptions[@"androidClientID"] = firOptions.androidClientID;
6768
firAppOptions[@"deepLinkUrlScheme"] = firOptions.deepLinkURLScheme;
69+
// not in FIROptions API but in JS SDK and project config JSON
70+
if ([RNFBAppModule getCustomDomain:name] != nil) {
71+
firAppOptions[@"authDomain"] = [RNFBAppModule getCustomDomain:name];
72+
}
6873

6974
firAppDictionary[@"options"] = firAppOptions;
7075
firAppDictionary[@"appConfig"] = firAppConfig;

packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import com.google.firebase.auth.TwitterAuthProvider;
6969
import com.google.firebase.auth.UserInfo;
7070
import com.google.firebase.auth.UserProfileChangeRequest;
71+
import io.invertase.firebase.app.ReactNativeFirebaseAppModule;
7172
import io.invertase.firebase.common.ReactNativeFirebaseEvent;
7273
import io.invertase.firebase.common.ReactNativeFirebaseEventEmitter;
7374
import io.invertase.firebase.common.ReactNativeFirebaseModule;
@@ -150,6 +151,26 @@ public void onCatalystInstanceDestroy() {
150151
mMultiFactorSessions.clear();
151152
}
152153

154+
@ReactMethod
155+
public void configureAuthDomain(final String appName) {
156+
Log.d(TAG, "configureAuthDomain");
157+
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
158+
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
159+
String authDomain = ReactNativeFirebaseAppModule.authDomains.get(appName);
160+
Log.d(TAG, "configureAuthDomain - app " + appName + " domain? " + authDomain);
161+
if (authDomain != null) {
162+
firebaseAuth.setCustomAuthDomain(authDomain);
163+
}
164+
}
165+
166+
@ReactMethod
167+
public void getCustomAuthDomain(final String appName, final Promise promise) {
168+
Log.d(TAG, "configureAuthDomain");
169+
FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
170+
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
171+
promise.resolve(firebaseAuth.getCustomAuthDomain());
172+
}
173+
153174
/** Add a new auth state listener - if one doesn't exist already */
154175
@ReactMethod
155176
public void addAuthStateListener(final String appName) {

packages/auth/e2e/auth.e2e.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,23 @@ describe('auth() modular', function () {
11391139

11401140
secondaryApp.auth().app.name.should.equal('secondaryFromNative');
11411141
});
1142+
1143+
it('supports an app initialized with custom authDomain', async function () {
1144+
const { getAuth, getCustomAuthDomain } = authModular;
1145+
const { initializeApp } = modular;
1146+
1147+
const name = `testscoreapp${FirebaseHelpers.id}`;
1148+
const platformAppConfig = FirebaseHelpers.app.config();
1149+
platformAppConfig.authDomain = 'example.com';
1150+
const newApp = await initializeApp(platformAppConfig, name);
1151+
const secondaryApp = firebase.app(name);
1152+
const secondaryAuth = getAuth(secondaryApp);
1153+
secondaryAuth.app.name.should.equal(name);
1154+
secondaryApp.auth().app.name.should.equal(name);
1155+
const customAuthDomain = await getCustomAuthDomain(secondaryAuth);
1156+
customAuthDomain.should.equal(platformAppConfig.authDomain);
1157+
return newApp.delete();
1158+
});
11421159
});
11431160
describe('applyActionCode()', function () {
11441161
// Needs a different setup to work against the auth emulator

packages/auth/ios/RNFBAuth/RNFBAuthModule.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#import <React/RCTUtils.h>
2020

2121
#import "RNFBApp/RCTConvert+FIRApp.h"
22+
#import "RNFBApp/RNFBAppModule.h"
2223
#import "RNFBApp/RNFBSharedUtils.h"
2324
#import "RNFBAuthModule.h"
2425

@@ -159,6 +160,21 @@ - (void)invalidate {
159160
}
160161
}
161162

163+
RCT_EXPORT_METHOD(configureAuthDomain : (FIRApp *)firebaseApp) {
164+
NSString *authDomain = [RNFBAppModule getCustomDomain:firebaseApp.name];
165+
DLog(@"RNFBAuth app: %@ customAuthDomain: %@", firebaseApp.name, authDomain);
166+
if (authDomain != nil) {
167+
[FIRAuth authWithApp:firebaseApp].customAuthDomain = authDomain;
168+
}
169+
}
170+
171+
RCT_EXPORT_METHOD(getCustomAuthDomain
172+
: (FIRApp *)firebaseApp
173+
: (RCTPromiseResolveBlock)resolve
174+
: (RCTPromiseRejectBlock)reject) {
175+
resolve([FIRAuth authWithApp:firebaseApp].customAuthDomain);
176+
}
177+
162178
RCT_EXPORT_METHOD(setAppVerificationDisabledForTesting : (FIRApp *)firebaseApp : (BOOL)disabled) {
163179
[FIRAuth authWithApp:firebaseApp].settings.appVerificationDisabledForTesting = disabled;
164180
}

packages/auth/lib/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export {
5656
fetchSignInMethodsForEmail,
5757
getAdditionalUserInfo,
5858
getAuth,
59+
getCustomAuthDomain,
5960
getIdToken,
6061
getIdTokenResult,
6162
getMultiFactorResolver,
@@ -173,6 +174,12 @@ class FirebaseAuthModule extends FirebaseModule {
173174

174175
this.native.addAuthStateListener();
175176
this.native.addIdTokenListener();
177+
178+
// custom authDomain in only available from App's FirebaseOptions,
179+
// but we need it in Auth if it exists. During app configuration we store
180+
// mappings from app name to authDomain, this auth constructor
181+
// is a reasonable time to use the mapping and set it into auth natively
182+
this.native.configureAuthDomain();
176183
}
177184

178185
get languageCode() {
@@ -500,6 +507,10 @@ class FirebaseAuthModule extends FirebaseModule {
500507
}
501508
return new MultiFactorUser(this, user);
502509
}
510+
511+
getCustomAuthDomain() {
512+
return this.native.getCustomAuthDomain();
513+
}
503514
}
504515

505516
// import { SDK_VERSION } from '@react-native-firebase/auth';

0 commit comments

Comments
 (0)