Skip to content

Commit 9c4aca6

Browse files
authored
Make initializeAuth() idempotent (#5279)
1 parent 7cba1e6 commit 9c4aca6

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

packages-exp/auth-exp/src/core/auth/initialize.test.ts

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
import { ClientPlatform, _getClientVersion } from '../util/version';
5151
import { initializeAuth } from './initialize';
5252
import { registerAuth } from './register';
53+
import { debugErrorMap, prodErrorMap } from '../errors';
5354

5455
describe('core/auth/initialize', () => {
5556
let fakeApp: FirebaseApp;
@@ -127,7 +128,8 @@ describe('core/auth/initialize', () => {
127128
}
128129
}
129130

130-
const fakePopupRedirectResolver: PopupRedirectResolver = FakePopupRedirectResolver;
131+
const fakePopupRedirectResolver: PopupRedirectResolver =
132+
FakePopupRedirectResolver;
131133

132134
before(() => {
133135
registerAuth(ClientPlatform.BROWSER);
@@ -203,15 +205,63 @@ describe('core/auth/initialize', () => {
203205
const auth = initializeAuth(fakeApp, {
204206
popupRedirectResolver: fakePopupRedirectResolver
205207
}) as AuthInternal;
206-
await ((auth as unknown) as _FirebaseService)._delete();
208+
await (auth as unknown as _FirebaseService)._delete();
207209
await auth._initializationPromise;
208210

209211
expect(auth._isInitialized).to.be.false;
210212
});
211213

212-
it('should throw if called more than once', () => {
213-
initializeAuth(fakeApp);
214-
expect(() => initializeAuth(fakeApp)).to.throw();
214+
it('should not throw if called again with same (no) params', () => {
215+
const auth = initializeAuth(fakeApp);
216+
expect(initializeAuth(fakeApp)).to.equal(auth);
217+
});
218+
219+
it('should not throw if called again with same params', () => {
220+
const auth = initializeAuth(fakeApp, {
221+
errorMap: prodErrorMap,
222+
persistence: fakeSessionPersistence,
223+
popupRedirectResolver: fakePopupRedirectResolver
224+
});
225+
expect(
226+
initializeAuth(fakeApp, {
227+
errorMap: prodErrorMap,
228+
persistence: fakeSessionPersistence,
229+
popupRedirectResolver: fakePopupRedirectResolver
230+
})
231+
).to.equal(auth);
232+
});
233+
234+
it('should throw if called again with different params (popupRedirectResolver)', () => {
235+
initializeAuth(fakeApp, {
236+
popupRedirectResolver: fakePopupRedirectResolver
237+
});
238+
expect(() =>
239+
initializeAuth(fakeApp, {
240+
popupRedirectResolver: undefined
241+
})
242+
).to.throw();
243+
});
244+
245+
it('should throw if called again with different params (errorMap)', () => {
246+
initializeAuth(fakeApp, {
247+
errorMap: prodErrorMap
248+
});
249+
expect(() =>
250+
initializeAuth(fakeApp, {
251+
errorMap: debugErrorMap
252+
})
253+
).to.throw();
254+
});
255+
256+
it('should throw if called again with different params (persistence)', () => {
257+
initializeAuth(fakeApp, {
258+
persistence: [inMemoryPersistence, fakeSessionPersistence]
259+
});
260+
expect(() =>
261+
initializeAuth(fakeApp, {
262+
persistence: [fakeSessionPersistence, inMemoryPersistence]
263+
})
264+
).to.throw();
215265
});
216266
});
217267
});

packages-exp/auth-exp/src/core/auth/initialize.ts

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

1818
import { _getProvider, FirebaseApp } from '@firebase/app-exp';
19+
import { deepEqual } from '@firebase/util';
1920
import { Auth, Dependencies } from '../../model/public_types';
2021

2122
import { AuthErrorCode } from '../errors';
@@ -54,7 +55,12 @@ export function initializeAuth(app: FirebaseApp, deps?: Dependencies): Auth {
5455

5556
if (provider.isInitialized()) {
5657
const auth = provider.getImmediate() as AuthImpl;
57-
_fail(auth, AuthErrorCode.ALREADY_INITIALIZED);
58+
const initialOptions = provider.getOptions() as Dependencies;
59+
if (deepEqual(initialOptions, deps ?? {})) {
60+
return auth;
61+
} else {
62+
_fail(auth, AuthErrorCode.ALREADY_INITIALIZED);
63+
}
5864
}
5965

6066
const auth = provider.initialize({ options: deps }) as AuthImpl;
@@ -67,9 +73,8 @@ export function _initializeAuthInstance(
6773
deps?: Dependencies
6874
): void {
6975
const persistence = deps?.persistence || [];
70-
const hierarchy = (Array.isArray(persistence)
71-
? persistence
72-
: [persistence]
76+
const hierarchy = (
77+
Array.isArray(persistence) ? persistence : [persistence]
7378
).map<PersistenceInternal>(_getInstance);
7479
if (deps?.errorMap) {
7580
auth._updateErrorMap(deps.errorMap);

packages-exp/auth-exp/src/core/errors.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@ function _debugErrorMap(): ErrorMap<AuthErrorCode> {
349349
[AuthErrorCode.WEB_STORAGE_UNSUPPORTED]:
350350
'This browser is not supported or 3rd party cookies and data may be disabled.',
351351
[AuthErrorCode.ALREADY_INITIALIZED]:
352-
'Auth can only be initialized once per app.'
352+
'initializeAuth() has already been called with ' +
353+
'different options. To avoid this error, call initializeAuth() with the ' +
354+
'same options as when it was originally called, or call getAuth() to return the' +
355+
' already initialized instance.'
353356
};
354357
}
355358

0 commit comments

Comments
 (0)