Skip to content

Commit 3fdce5d

Browse files
committed
Add a way to specify emulator host/port for Auth
1 parent 0986b92 commit 3fdce5d

File tree

13 files changed

+635
-40
lines changed

13 files changed

+635
-40
lines changed

packages/auth/buildtools/run_demo.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ cp ../firebase/firebase-auth.js demo/public/dist/firebase-auth.js
3434
cp ../firebase/firebase-database.js demo/public/dist/firebase-database.js
3535
# Serve demo app.
3636
cd demo
37-
`yarn bin`/firebase serve --only hosting,functions
37+
`yarn bin`/firebase emulators:start

packages/auth/src/auth.js

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ fireauth.Auth = function(app) {
184184
* is currently only used to log FirebaseUI.
185185
*/
186186
this.frameworks_ = [];
187+
188+
/**
189+
* @private {?fireauth.constants.EmulatorSettings} The current
190+
* emulator settings.
191+
*/
192+
this.emulatorConfig_ = null;
187193
};
188194
goog.inherits(fireauth.Auth, goog.events.EventTarget);
189195

@@ -202,6 +208,20 @@ fireauth.Auth.LanguageCodeChangeEvent = function(languageCode) {
202208
goog.inherits(fireauth.Auth.LanguageCodeChangeEvent, goog.events.Event);
203209

204210

211+
/**
212+
* Emulator config change custom event.
213+
* @param {?fireauth.constants.EmulatorSettings} emulatorConfig The new
214+
* emulator settings.
215+
* @constructor
216+
* @extends {goog.events.Event}
217+
*/
218+
fireauth.Auth.EmulatorConfigChangeEvent = function(emulatorConfig) {
219+
goog.events.Event.call(this, fireauth.constants.AuthEventType.EMULATOR_CONFIG_CHANGED);
220+
this.emulatorConfig = emulatorConfig;
221+
};
222+
goog.inherits(fireauth.Auth.EmulatorConfigChangeEvent, goog.events.Event);
223+
224+
205225
/**
206226
* Framework change custom event.
207227
* @param {!Array<string>} frameworks The new frameworks array.
@@ -272,6 +292,34 @@ fireauth.Auth.prototype.useDeviceLanguage = function() {
272292
};
273293

274294

295+
/**
296+
* Sets the emulator configuration (go/firebase-emulator-connection-api).
297+
* @param {string} hostname The hostname for the Auth emulator.
298+
* @param {number} port The port for the Auth emulator.
299+
*/
300+
fireauth.Auth.prototype.useEmulator = function(hostname, port) {
301+
// Don't do anything if no change detected.
302+
if (!this.emulatorConfig_ ||
303+
hostname !== this.emulatorConfig_.hostname ||
304+
port !== this.emulatorConfig_.port) {
305+
this.emulatorConfig_ = { hostname: hostname, port: port };
306+
// Disable app verification.
307+
this.settings_().setAppVerificationDisabledForTesting(true);
308+
// Update custom Firebase locale field.
309+
this.rpcHandler_.updateEmulatorConfig(this.emulatorConfig_);
310+
// Notify external language code change listeners.
311+
this.notifyEmulatorConfigListeners_();
312+
}
313+
}
314+
315+
/**
316+
* @return {?fireauth.constants.EmulatorSettings}
317+
*/
318+
fireauth.Auth.prototype.getEmulatorConfig = function () {
319+
return this.emulatorConfig_;
320+
}
321+
322+
275323
/**
276324
* @param {string} frameworkId The framework identifier.
277325
*/
@@ -396,7 +444,15 @@ fireauth.Auth.prototype.notifyLanguageCodeListeners_ = function() {
396444
};
397445

398446

399-
447+
/**
448+
* Notifies all external listeners of the emulator config change.
449+
* @private
450+
*/
451+
fireauth.Auth.prototype.notifyEmulatorConfigListeners_ = function() {
452+
// Notify external listeners on the language code change.
453+
this.dispatchEvent(
454+
new fireauth.Auth.EmulatorConfigChangeEvent(this.emulatorConfig_));
455+
}
400456

401457

402458
/**
@@ -449,7 +505,10 @@ fireauth.Auth.prototype.initAuthEventManager_ = function() {
449505
// By this time currentUser should be ready if available and will be able
450506
// to resolve linkWithRedirect if detected.
451507
self.authEventManager_ = fireauth.AuthEventManager.getManager(
452-
authDomain, apiKey, self.app_().name);
508+
authDomain,
509+
apiKey,
510+
self.app_().name,
511+
self.emulatorConfig_);
453512
// Subscribe Auth instance.
454513
self.authEventManager_.subscribe(self);
455514
// Subscribe current user by enabling popup and redirect on that user.
@@ -471,7 +530,10 @@ fireauth.Auth.prototype.initAuthEventManager_ = function() {
471530
/** @type {!fireauth.AuthUser} */ (self.redirectUser_));
472531
// Set the user Firebase frameworks for the redirect user.
473532
self.setUserFramework_(
474-
/** @type {!fireauth.AuthUser} */ (self.redirectUser_));
533+
/** @type {!fireauth.AuthUser} */(self.redirectUser_));
534+
// Set the user Emulator configuration for the redirect user.
535+
self.setUserEmulatorConfig_(
536+
/** @type {!fireauth.AuthUser} */(self.redirectUser_));
475537
// Reference to redirect user no longer needed.
476538
self.redirectUser_ = null;
477539
}
@@ -650,7 +712,8 @@ fireauth.Auth.prototype.signInWithPopup = function(provider) {
650712
firebase.SDK_VERSION || null,
651713
null,
652714
null,
653-
this.getTenantId());
715+
this.getTenantId(),
716+
this.emulatorConfig_);
654717
}
655718
// The popup must have a name, otherwise when successive popups are triggered
656719
// they will all render in the same instance and none will succeed since the
@@ -856,6 +919,7 @@ fireauth.Auth.prototype.signInWithIdTokenResponse =
856919
options['apiKey'] = self.app_().options['apiKey'];
857920
options['authDomain'] = self.app_().options['authDomain'];
858921
options['appName'] = self.app_().name;
922+
options['emulatorConfig'] = self.emulatorConfig_;
859923
// Wait for state to be ready.
860924
// This is used internally and is also used for redirect sign in so there is
861925
// no need for waiting for redirect result to resolve since redirect result
@@ -911,6 +975,9 @@ fireauth.Auth.prototype.setCurrentUser_ = function(user) {
911975
// Set the current frameworks used on the user and set current Auth instance
912976
// as the framework change dispatcher.
913977
this.setUserFramework_(user);
978+
// If a user is available, set the emulator config on it and set current
979+
// Auth instance as emulator config change dispatcher.
980+
this.setUserEmulatorConfig_(user);
914981
}
915982
};
916983

@@ -1179,6 +1246,22 @@ fireauth.Auth.prototype.setUserLanguage_ = function(user) {
11791246
};
11801247

11811248

1249+
/**
1250+
* Updates the emulator config on the provided user and configures the user
1251+
* to listen to the Auth instance for any emulator config changes.
1252+
* @param {!fireauth.AuthUser} user The user to whose emulator config needs
1253+
* to be set.
1254+
* @private
1255+
*/
1256+
fireauth.Auth.prototype.setUserEmulatorConfig_ = function(user) {
1257+
// Sets the current emulator config on the user.
1258+
user.setEmulatorConfig(this.emulatorConfig_);
1259+
// Sets current Auth instance as emulator config change dispatcher on the
1260+
// user.
1261+
user.setEmulatorConfigChangeDispatcher(this);
1262+
}
1263+
1264+
11821265
/**
11831266
* Handles user state changes.
11841267
* @param {!fireauth.AuthUser} user The user which triggered the state changes.
@@ -1679,6 +1762,17 @@ fireauth.Auth.prototype.app_ = function() {
16791762
};
16801763

16811764

1765+
1766+
/**
1767+
* @return {!fireauth.AuthSettings} The AuthSettings object this auth object
1768+
* is connected to.
1769+
* @private
1770+
*/
1771+
fireauth.Auth.prototype.settings_ = function() {
1772+
return this['settings'];
1773+
}
1774+
1775+
16821776
/**
16831777
* @return {!fireauth.RpcHandler} The RPC handler.
16841778
*/

packages/auth/src/autheventmanager.js

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ goog.require('goog.array');
4747
* @param {string} apiKey The API key for sending backend Auth requests.
4848
* @param {string} appName The App ID for the Auth instance that triggered this
4949
* request.
50+
* @param {?fireauth.constants.EmulatorSettings=} emulatorConfig The emulator
51+
* configuration.
5052
* @constructor
5153
*/
52-
fireauth.AuthEventManager = function(authDomain, apiKey, appName) {
54+
fireauth.AuthEventManager = function(authDomain, apiKey, appName, emulatorConfig) {
5355
/**
5456
* @private {!Object<string, boolean>} The map of processed auth event IDs.
5557
*/
@@ -62,6 +64,8 @@ fireauth.AuthEventManager = function(authDomain, apiKey, appName) {
6264
this.apiKey_ = apiKey;
6365
/** @private {string} The App name. */
6466
this.appName_ = appName;
67+
/** @private @const {?fireauth.constants.EmulatorSettings|undefined} The emulator config. */
68+
this.emulatorConfig_ = emulatorConfig;
6569
/**
6670
* @private {!Array<!fireauth.AuthEventHandler>} List of subscribed handlers.
6771
*/
@@ -111,9 +115,12 @@ fireauth.AuthEventManager = function(authDomain, apiKey, appName) {
111115
*/
112116
this.oauthSignInHandler_ =
113117
fireauth.AuthEventManager.instantiateOAuthSignInHandler(
114-
this.authDomain_, this.apiKey_, this.appName_,
115-
firebase.SDK_VERSION || null,
116-
fireauth.constants.clientEndpoint);
118+
this.authDomain_,
119+
this.apiKey_,
120+
this.appName_,
121+
firebase.SDK_VERSION || null,
122+
fireauth.constants.clientEndpoint,
123+
this.emulatorConfig_);
117124
};
118125

119126

@@ -149,22 +156,35 @@ fireauth.AuthEventManager.prototype.getPopupAuthEventProcessor = function() {
149156
* request.
150157
* @param {?string} version The SDK client version.
151158
* @param {?string=} opt_endpointId The endpoint ID (staging, test Gaia, etc).
159+
* @param {?fireauth.constants.EmulatorSettings=} emulatorConfig The emulator
160+
* configuration.
152161
* @return {!fireauth.OAuthSignInHandler} The OAuth sign in handler depending
153162
* on the current environment.
154163
*/
155164
fireauth.AuthEventManager.instantiateOAuthSignInHandler =
156-
function(authDomain, apiKey, appName, version, opt_endpointId) {
165+
function(authDomain, apiKey, appName, version, opt_endpointId, emulatorConfig) {
157166
// This assumes that android/iOS file environment must be a Cordova
158167
// environment which is not true. This is the best way currently available
159168
// to instantiate this synchronously without waiting for checkIfCordova to
160169
// resolve. If it is determined that the Cordova was falsely detected, it will
161170
// be caught via actionable public popup and redirect methods.
162171
return fireauth.util.isAndroidOrIosCordovaScheme() ?
163172
new fireauth.CordovaHandler(
164-
authDomain, apiKey, appName, version, undefined, undefined,
165-
opt_endpointId) :
173+
authDomain,
174+
apiKey,
175+
appName,
176+
version,
177+
undefined,
178+
undefined,
179+
opt_endpointId,
180+
emulatorConfig) :
166181
new fireauth.iframeclient.IfcHandler(
167-
authDomain, apiKey, appName, version, opt_endpointId);
182+
authDomain,
183+
apiKey,
184+
appName,
185+
version,
186+
opt_endpointId,
187+
emulatorConfig);
168188
};
169189

170190

@@ -179,8 +199,12 @@ fireauth.AuthEventManager.prototype.reset = function() {
179199

180200
this.oauthSignInHandler_ =
181201
fireauth.AuthEventManager.instantiateOAuthSignInHandler(
182-
this.authDomain_, this.apiKey_, this.appName_,
183-
firebase.SDK_VERSION || null);
202+
this.authDomain_,
203+
this.apiKey_,
204+
this.appName_,
205+
firebase.SDK_VERSION || null,
206+
null,
207+
this.emulatorConfig_);
184208
this.processedEvents_ = {};
185209
};
186210

@@ -662,14 +686,16 @@ fireauth.AuthEventManager.getKey_ = function(apiKey, appName) {
662686
* @param {string} apiKey The API key for sending backend Auth requests.
663687
* @param {string} appName The Auth instance that initiated the Auth event
664688
* manager.
689+
* @param {?fireauth.constants.EmulatorSettings=} emulatorConfig The emulator
690+
* configuration.
665691
* @return {!fireauth.AuthEventManager} the requested manager instance.
666692
*/
667-
fireauth.AuthEventManager.getManager = function(authDomain, apiKey, appName) {
693+
fireauth.AuthEventManager.getManager = function(authDomain, apiKey, appName, emulatorConfig) {
668694
// Construct storage key.
669695
var key = fireauth.AuthEventManager.getKey_(apiKey, appName);
670696
if (!fireauth.AuthEventManager.manager_[key]) {
671697
fireauth.AuthEventManager.manager_[key] =
672-
new fireauth.AuthEventManager(authDomain, apiKey, appName);
698+
new fireauth.AuthEventManager(authDomain, apiKey, appName, emulatorConfig);
673699
}
674700
return fireauth.AuthEventManager.manager_[key];
675701
};

packages/auth/src/authuser.js

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ fireauth.AuthUser =
182182
this.apiKey_,
183183
// Get the client Auth endpoint used.
184184
fireauth.constants.getEndpointConfig(fireauth.constants.clientEndpoint),
185-
clientFullVersion);
185+
clientFullVersion);
186+
if (appOptions['emulatorConfig']) {
187+
this.rpcHandler_.updateEmulatorConfig(appOptions['emulatorConfig']);
188+
}
186189
// TODO: Consider having AuthUser take a fireauth.StsTokenManager
187190
// instance instead of a token response but make sure lastAccessToken_ also
188191
// initialized at the right time. In this case initializeFromIdTokenResponse
@@ -249,6 +252,20 @@ fireauth.AuthUser =
249252
*/
250253
this.languageCodeChangeEventDispatcher_ = null;
251254

255+
/**
256+
* @private {function(!goog.events.Event)} The on emulator config changed
257+
* event handler.
258+
*/
259+
this.onEmulatorConfigChanged_ = function (event) {
260+
// Update the emulator config.
261+
self.setEmulatorConfig(event.emulatorConfig);
262+
};
263+
/**
264+
* @private {?goog.events.EventTarget} The emulator code change event
265+
* dispatcher.
266+
*/
267+
this.emulatorConfigChangeEventDispatcher_ = null;
268+
252269
/** @private {!Array<string>} The current Firebase frameworks. */
253270
this.frameworks_ = [];
254271
/**
@@ -288,6 +305,17 @@ fireauth.AuthUser.prototype.setLanguageCode = function(languageCode) {
288305
};
289306

290307

308+
/**
309+
* Updates the emulator config.
310+
* @param {?fireauth.constants.EmulatorSettings} emulatorConfig The current
311+
* emulator config to use in user requests.
312+
*/
313+
fireauth.AuthUser.prototype.setEmulatorConfig = function(emulatorConfig) {
314+
// Update the emulator config.
315+
this.rpcHandler_.updateEmulatorConfig(emulatorConfig);
316+
};
317+
318+
291319
/** @return {?string} The current user's language code. */
292320
fireauth.AuthUser.prototype.getLanguageCode = function() {
293321
return this.languageCode_;
@@ -322,6 +350,32 @@ fireauth.AuthUser.prototype.setLanguageCodeChangeDispatcher =
322350
};
323351

324352

353+
/**
354+
* Listens to emulator config changes triggered by the provided dispatcher.
355+
* @param {?goog.events.EventTarget} dispatcher The emulator config changed
356+
* event dispatcher.
357+
*/
358+
fireauth.AuthUser.prototype.setEmulatorConfigChangeDispatcher = function(dispatcher) {
359+
// Remove any previous listener.
360+
if (this.emulatorConfigChangeEventDispatcher_) {
361+
goog.events.unlisten(
362+
this.emulatorConfigChangeEventDispatcher_,
363+
fireauth.constants.AuthEventType.EMULATOR_CONFIG_CHANGED,
364+
this.onEmulatorConfigChanged_);
365+
}
366+
// Update current dispatcher.
367+
this.emulatorConfigChangeEventDispatcher_ = dispatcher;
368+
// Using an event listener makes it easy for non-currentUsers to detect
369+
// emulator changes on the parent Auth instance. A developer could still
370+
// call APIs that require localization on signed out user references.
371+
if (dispatcher) {
372+
goog.events.listen(
373+
dispatcher, fireauth.constants.AuthEventType.EMULATOR_CONFIG_CHANGED,
374+
this.onEmulatorConfigChanged_);
375+
}
376+
}
377+
378+
325379
/**
326380
* Updates the Firebase frameworks on the current user.
327381
* @param {!Array<string>} framework The list of Firebase frameworks.
@@ -1043,7 +1097,8 @@ fireauth.AuthUser.prototype.notifyUserInvalidatedListeners_ = function() {
10431097
* @return {!goog.Promise<undefined>}
10441098
* @private
10451099
*/
1046-
fireauth.AuthUser.prototype.setUserAccountInfoFromToken_ = function(idToken) {
1100+
fireauth.AuthUser.prototype.setUserAccountInfoFromToken_ = function (idToken) {
1101+
debugger
10471102
return this.rpcHandler_.getAccountInfoByIdToken(idToken)
10481103
.then(goog.bind(this.parseAccountInfo_, this));
10491104
};
@@ -2176,6 +2231,8 @@ fireauth.AuthUser.prototype.destroy = function() {
21762231
}
21772232
// Stop listening to language code changes.
21782233
this.setLanguageCodeChangeDispatcher(null);
2234+
// Stop listening to emulator config changes.
2235+
this.setEmulatorConfigChangeDispatcher(null);
21792236
// Stop listening to framework changes.
21802237
this.setFrameworkChangeDispatcher(null);
21812238
// Empty pending promises array.

0 commit comments

Comments
 (0)