Skip to content

Commit 73e0e47

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

File tree

8 files changed

+449
-5
lines changed

8 files changed

+449
-5
lines changed

packages/auth/src/auth.js

Lines changed: 80 additions & 3 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,32 @@ 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+
// Update custom Firebase locale field.
307+
this.rpcHandler_.updateEmulatorConfig(this.emulatorConfig_);
308+
// Notify external language code change listeners.
309+
this.notifyEmulatorConfigListeners_();
310+
}
311+
}
312+
313+
/**
314+
* @return {?fireauth.constants.EmulatorSettings}
315+
*/
316+
fireauth.Auth.prototype.getEmulatorConfig = function () {
317+
return this.emulatorConfig_;
318+
}
319+
320+
275321
/**
276322
* @param {string} frameworkId The framework identifier.
277323
*/
@@ -396,7 +442,15 @@ fireauth.Auth.prototype.notifyLanguageCodeListeners_ = function() {
396442
};
397443

398444

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

401455

402456
/**
@@ -471,7 +525,10 @@ fireauth.Auth.prototype.initAuthEventManager_ = function() {
471525
/** @type {!fireauth.AuthUser} */ (self.redirectUser_));
472526
// Set the user Firebase frameworks for the redirect user.
473527
self.setUserFramework_(
474-
/** @type {!fireauth.AuthUser} */ (self.redirectUser_));
528+
/** @type {!fireauth.AuthUser} */(self.redirectUser_));
529+
// Set the user Emulator configuration for the redirect user.
530+
self.setUserEmulatorConfig_(
531+
/** @type {!fireauth.AuthUser} */(self.redirectUser_));
475532
// Reference to redirect user no longer needed.
476533
self.redirectUser_ = null;
477534
}
@@ -650,7 +707,8 @@ fireauth.Auth.prototype.signInWithPopup = function(provider) {
650707
firebase.SDK_VERSION || null,
651708
null,
652709
null,
653-
this.getTenantId());
710+
this.getTenantId(),
711+
this.emulatorConfig_);
654712
}
655713
// The popup must have a name, otherwise when successive popups are triggered
656714
// they will all render in the same instance and none will succeed since the
@@ -911,6 +969,9 @@ fireauth.Auth.prototype.setCurrentUser_ = function(user) {
911969
// Set the current frameworks used on the user and set current Auth instance
912970
// as the framework change dispatcher.
913971
this.setUserFramework_(user);
972+
// If a user is available, set the emulator config on it and set current
973+
// Auth instance as emulator config change dispatcher.
974+
this.setUserEmulatorConfig_(user);
914975
}
915976
};
916977

@@ -1179,6 +1240,22 @@ fireauth.Auth.prototype.setUserLanguage_ = function(user) {
11791240
};
11801241

11811242

1243+
/**
1244+
* Updates the emulator config on the provided user and configures the user
1245+
* to listen to the Auth instance for any emulator config changes.
1246+
* @param {!fireauth.AuthUser} user The user to whose emulator config needs
1247+
* to be set.
1248+
* @private
1249+
*/
1250+
fireauth.Auth.prototype.setUserEmulatorConfig_ = function(user) {
1251+
// Sets the current emulator config on the user.
1252+
user.setEmulatorConfig(this.emulatorConfig_);
1253+
// Sets current Auth instance as emulator config change dispatcher on the
1254+
// user.
1255+
user.setEmulatorConfigChangeDispatcher(this);
1256+
}
1257+
1258+
11821259
/**
11831260
* Handles user state changes.
11841261
* @param {!fireauth.AuthUser} user The user which triggered the state changes.

packages/auth/src/authuser.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,20 @@ fireauth.AuthUser =
249249
*/
250250
this.languageCodeChangeEventDispatcher_ = null;
251251

252+
/**
253+
* @private {function(!goog.events.Event)} The on emulator config changed
254+
* event handler.
255+
*/
256+
this.onEmulatorConfigChanged_ = function (event) {
257+
// Update the emulator config.
258+
self.setEmulatorConfig(event.emulatorConfig);
259+
};
260+
/**
261+
* @private {?goog.events.EventTarget} The emulator code change event
262+
* dispatcher.
263+
*/
264+
this.emulatorConfigChangeEventDispatcher_ = null;
265+
252266
/** @private {!Array<string>} The current Firebase frameworks. */
253267
this.frameworks_ = [];
254268
/**
@@ -288,6 +302,17 @@ fireauth.AuthUser.prototype.setLanguageCode = function(languageCode) {
288302
};
289303

290304

305+
/**
306+
* Updates the emulator config.
307+
* @param {?fireauth.constants.EmulatorSettings} emulatorConfig The current
308+
* emulator config to use in user requests.
309+
*/
310+
fireauth.AuthUser.prototype.setEmulatorConfig = function(emulatorConfig) {
311+
// Update the emulator config.
312+
this.rpcHandler_.updateEmulatorConfig(emulatorConfig);
313+
};
314+
315+
291316
/** @return {?string} The current user's language code. */
292317
fireauth.AuthUser.prototype.getLanguageCode = function() {
293318
return this.languageCode_;
@@ -322,6 +347,32 @@ fireauth.AuthUser.prototype.setLanguageCodeChangeDispatcher =
322347
};
323348

324349

350+
/**
351+
* Listens to emulator config changes triggered by the provided dispatcher.
352+
* @param {?goog.events.EventTarget} dispatcher The emulator config changed
353+
* event dispatcher.
354+
*/
355+
fireauth.AuthUser.prototype.setEmulatorConfigChangeDispatcher = function(dispatcher) {
356+
// Remove any previous listener.
357+
if (this.emulatorConfigChangeEventDispatcher_) {
358+
goog.events.unlisten(
359+
this.emulatorConfigChangeEventDispatcher_,
360+
fireauth.constants.AuthEventType.EMULATOR_CONFIG_CHANGED,
361+
this.onEmulatorConfigChanged_);
362+
}
363+
// Update current dispatcher.
364+
this.emulatorConfigChangeEventDispatcher_ = dispatcher;
365+
// Using an event listener makes it easy for non-currentUsers to detect
366+
// emulator changes on the parent Auth instance. A developer could still
367+
// call APIs that require localization on signed out user references.
368+
if (dispatcher) {
369+
goog.events.listen(
370+
dispatcher, fireauth.constants.AuthEventType.EMULATOR_CONFIG_CHANGED,
371+
this.onEmulatorConfigChanged_);
372+
}
373+
}
374+
375+
325376
/**
326377
* Updates the Firebase frameworks on the current user.
327378
* @param {!Array<string>} framework The list of Firebase frameworks.
@@ -2176,6 +2227,8 @@ fireauth.AuthUser.prototype.destroy = function() {
21762227
}
21772228
// Stop listening to language code changes.
21782229
this.setLanguageCodeChangeDispatcher(null);
2230+
// Stop listening to emulator config changes.
2231+
this.setEmulatorConfigChangeDispatcher(null);
21792232
// Stop listening to framework changes.
21802233
this.setFrameworkChangeDispatcher(null);
21812234
// Empty pending promises array.

packages/auth/src/defines.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ fireauth.constants.OperationType = {
3939
* @enum {string}
4040
*/
4141
fireauth.constants.AuthEventType = {
42+
/** Dispatched when emulator config is changed. */
43+
EMULATOR_CONFIG_CHANGED: 'emulatorConfigChanged',
4244
/** Dispatched when Firebase framework is changed. */
4345
FRAMEWORK_CHANGED: 'frameworkChanged',
4446
/** Dispatched when language code is changed. */
@@ -166,3 +168,16 @@ fireauth.constants.SAML_PREFIX = 'saml.';
166168

167169
/** @const {string} The required OIDC provider ID prefix. */
168170
fireauth.constants.OIDC_PREFIX = 'oidc.';
171+
172+
/**
173+
* The settings of an Auth emulator. The fields are:
174+
* <ul>
175+
* <li>hostname: defines the hostname where the emulator is running.</li>
176+
* <li>port: defines the port where the emulator is running.</li>
177+
* </ul>
178+
* @typedef {{
179+
* hostname: string,
180+
* port: number
181+
* }}
182+
*/
183+
fireauth.constants.EmulatorSettings;

packages/auth/src/exports_auth.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ fireauth.exportlib.exportPrototypeMethods(
197197
name: 'useDeviceLanguage',
198198
args: []
199199
},
200+
useEmulator: {
201+
name: 'useEmulator',
202+
args: [
203+
fireauth.args.string('hostname'),
204+
fireauth.args.number('port')
205+
]
206+
},
200207
verifyPasswordResetCode: {
201208
name: 'verifyPasswordResetCode',
202209
args: [fireauth.args.string('code')]

packages/auth/src/rpchandler.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ goog.provide('fireauth.XmlHttpFactory');
2626
goog.require('fireauth.AuthError');
2727
goog.require('fireauth.AuthErrorWithCredential');
2828
goog.require('fireauth.authenum.Error');
29+
goog.require('fireauth.constants');
2930
goog.require('fireauth.idp');
3031
goog.require('fireauth.idp.ProviderId');
3132
goog.require('fireauth.object');
@@ -110,10 +111,10 @@ fireauth.RpcHandler = function(apiKey, opt_config, opt_firebaseClientVersion) {
110111
this.secureTokenHeaders_ = goog.object.clone(
111112
config['secureTokenHeaders'] ||
112113
fireauth.RpcHandler.DEFAULT_SECURE_TOKEN_HEADERS_);
113-
/** @private @const {string} The Firebase Auth endpoint. */
114+
/** @private {string} The Firebase Auth endpoint. */
114115
this.firebaseEndpoint_ = config['firebaseEndpoint'] ||
115116
fireauth.RpcHandler.FIREBASE_ENDPOINT_;
116-
/** @private @const {string} The identity platform endpoint. */
117+
/** @private {string} The identity platform endpoint. */
117118
this.identityPlatformEndpoint_ = config['identityPlatformEndpoint'] ||
118119
fireauth.RpcHandler.IDENTITY_PLATFORM_ENDPOINT_;
119120
/**
@@ -435,6 +436,48 @@ fireauth.RpcHandler.prototype.updateCustomLocaleHeader =
435436
};
436437

437438

439+
/**
440+
* Updates the emulator configuration.
441+
* @param {?fireauth.constants.EmulatorSettings} emulatorConfig The new
442+
* emulator config.
443+
*/
444+
fireauth.RpcHandler.prototype.updateEmulatorConfig = function(emulatorConfig) {
445+
if (!emulatorConfig) {
446+
return;
447+
}
448+
// If an emulator config is provided, update the endpoints.
449+
this.secureTokenEndpoint_ =
450+
fireauth.RpcHandler.generateEmululatorEndpointUrl_(
451+
fireauth.RpcHandler.SECURE_TOKEN_ENDPOINT_, emulatorConfig);
452+
this.firebaseEndpoint_ =
453+
fireauth.RpcHandler.generateEmululatorEndpointUrl_(
454+
fireauth.RpcHandler.FIREBASE_ENDPOINT_, emulatorConfig);
455+
this.identityPlatformEndpoint_ =
456+
fireauth.RpcHandler.generateEmululatorEndpointUrl_(
457+
fireauth.RpcHandler.IDENTITY_PLATFORM_ENDPOINT_, emulatorConfig);
458+
}
459+
460+
461+
/**
462+
* Creates an endpoint URL intended for use by the emulator.
463+
*
464+
* According to go/firebase-auth-emulator-dd
465+
* @param {string} endpoint the production endpoint URL.
466+
* @param {?fireauth.constants.EmulatorSettings} emulatorConfig The emulator
467+
* config.
468+
* @return {string} The emulator endpoint URL.
469+
* @private
470+
*/
471+
fireauth.RpcHandler.generateEmululatorEndpointUrl_ = function(endpoint, emulatorConfig) {
472+
const uri = goog.Uri.parse(endpoint);
473+
uri.setScheme("http");
474+
uri.setPath(uri.getDomain() + uri.getPath());
475+
uri.setDomain(emulatorConfig.hostname);
476+
uri.setPort(emulatorConfig.port);
477+
return uri.toString();
478+
}
479+
480+
438481
/**
439482
* Updates the X-Client-Version in the header.
440483
* @param {?string} clientVersion The new client version.

0 commit comments

Comments
 (0)