Skip to content

Commit 92e9fca

Browse files
committed
Fix bug where immediate redirects in compat were broken; also save redirect persistence before link and reauth as well
1 parent 3862071 commit 92e9fca

File tree

5 files changed

+73
-60
lines changed

5 files changed

+73
-60
lines changed

packages-exp/auth-compat-exp/src/auth.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,15 @@ describe('auth compat', () => {
4343
sinon.restore;
4444
});
4545

46-
it('saves the persistence into session storage if available', () => {
47-
const authCompat = new Auth(app, underlyingAuth);
46+
it('saves the persistence into session storage if available', async () => {
4847
if (typeof self !== 'undefined') {
48+
underlyingAuth._initializationPromise = Promise.resolve();
4949
sinon.stub(underlyingAuth, '_getPersistence').returns('TEST');
50+
sinon.stub(underlyingAuth, '_initializationPromise').value(Promise.resolve());
51+
sinon.stub(exp._getInstance<exp.PopupRedirectResolverInternal>(CompatPopupRedirectResolver), '_openRedirect');
52+
const authCompat = new Auth(app, underlyingAuth);
5053
// eslint-disable-next-line @typescript-eslint/no-floating-promises
51-
authCompat.signInWithRedirect(new exp.GoogleAuthProvider());
54+
await authCompat.signInWithRedirect(new exp.GoogleAuthProvider());
5255
expect(
5356
sessionStorage.getItem('firebase:persistence:api-key:undefined')
5457
).to.eq('TEST');

packages-exp/auth-compat-exp/src/auth.ts

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
Unsubscribe
2626
} from '@firebase/util';
2727

28-
import { _validatePersistenceArgument, Persistence } from './persistence';
28+
import { _validatePersistenceArgument, Persistence, _getPersistenceFromRedirect, _savePersistenceForRedirect } from './persistence';
2929
import { _isPopupRedirectSupported } from './platform';
3030
import { CompatPopupRedirectResolver } from './popup_redirect';
3131
import { User } from './user';
@@ -35,7 +35,6 @@ import {
3535
} from './user_credential';
3636
import { unwrap, Wrapper } from './wrap';
3737

38-
const PERSISTENCE_KEY = 'persistence';
3938
const _assert: typeof exp._assert = exp._assert;
4039

4140
export class Auth
@@ -51,7 +50,7 @@ export class Auth
5150
// Note this is slightly different behavior: in this case, the stored
5251
// persistence is checked *first* rather than last. This is because we want
5352
// the fallback (if no user is found) to be the stored persistence type
54-
const storedPersistence = this.getPersistenceFromRedirect();
53+
const storedPersistence = _getPersistenceFromRedirect(this.auth);
5554
const persistences = storedPersistence ? [storedPersistence] : [];
5655
persistences.push(exp.indexedDBLocalPersistence);
5756

@@ -294,7 +293,8 @@ export class Auth
294293
this.auth,
295294
exp.AuthErrorCode.OPERATION_NOT_SUPPORTED
296295
);
297-
this.savePersistenceForRedirect();
296+
297+
await _savePersistenceForRedirect(this.auth);
298298
return exp.signInWithRedirect(
299299
this.auth,
300300
provider as exp.AuthProvider,
@@ -313,49 +313,6 @@ export class Auth
313313
_delete(): Promise<void> {
314314
return this.auth._delete();
315315
}
316-
317-
private savePersistenceForRedirect(): void {
318-
const win = getSelfWindow();
319-
const key = exp._persistenceKeyName(
320-
PERSISTENCE_KEY,
321-
this.auth.config.apiKey,
322-
this.auth.name
323-
);
324-
if (win?.sessionStorage) {
325-
win.sessionStorage.setItem(key, this.auth._getPersistence());
326-
}
327-
}
328-
329-
private getPersistenceFromRedirect(): exp.Persistence | null {
330-
const win = getSelfWindow();
331-
if (!win?.sessionStorage) {
332-
return null;
333-
}
334-
335-
const key = exp._persistenceKeyName(
336-
PERSISTENCE_KEY,
337-
this.auth.config.apiKey,
338-
this.auth.name
339-
);
340-
const persistence = win.sessionStorage.getItem(key);
341-
342-
switch (persistence) {
343-
case exp.inMemoryPersistence.type:
344-
return exp.inMemoryPersistence;
345-
case exp.indexedDBLocalPersistence.type:
346-
return exp.indexedDBLocalPersistence;
347-
case exp.browserSessionPersistence.type:
348-
return exp.browserSessionPersistence;
349-
case exp.browserLocalPersistence.type:
350-
return exp.browserLocalPersistence;
351-
default:
352-
return null;
353-
}
354-
}
355-
}
356-
357-
function getSelfWindow(): Window | null {
358-
return typeof window !== 'undefined' ? window : null;
359316
}
360317

361318
function wrapObservers(

packages-exp/auth-compat-exp/src/persistence.ts

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { _assert, AuthErrorCode, Auth } from '@firebase/auth-exp/internal';
18+
import { AuthInternal } from '@firebase/auth-exp/dist/esm5/src/model/auth';
19+
import * as exp from '@firebase/auth-exp/internal';
1920
import { isIndexedDBAvailable, isNode, isReactNative } from '@firebase/util';
2021
import { _isWebStorageSupported, _isWorker } from './platform';
2122

@@ -25,26 +26,30 @@ export const Persistence = {
2526
SESSION: 'SESSION'
2627
};
2728

29+
const _assert: typeof exp._assert = exp._assert;
30+
31+
const PERSISTENCE_KEY = 'persistence';
32+
2833
/**
2934
* Validates that an argument is a valid persistence value. If an invalid type
3035
* is specified, an error is thrown synchronously.
3136
*/
3237
export function _validatePersistenceArgument(
33-
auth: Auth,
38+
auth: exp.Auth,
3439
persistence: string
3540
): void {
3641
_assert(
3742
Object.values(Persistence).includes(persistence),
3843
auth,
39-
AuthErrorCode.INVALID_PERSISTENCE
44+
exp.AuthErrorCode.INVALID_PERSISTENCE
4045
);
4146
// Validate if the specified type is supported in the current environment.
4247
if (isReactNative()) {
4348
// This is only supported in a browser.
4449
_assert(
4550
persistence !== Persistence.SESSION,
4651
auth,
47-
AuthErrorCode.UNSUPPORTED_PERSISTENCE
52+
exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE
4853
);
4954
return;
5055
}
@@ -53,7 +58,7 @@ export function _validatePersistenceArgument(
5358
_assert(
5459
persistence === Persistence.NONE,
5560
auth,
56-
AuthErrorCode.UNSUPPORTED_PERSISTENCE
61+
exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE
5762
);
5863
return;
5964
}
@@ -64,14 +69,59 @@ export function _validatePersistenceArgument(
6469
persistence === Persistence.NONE ||
6570
(persistence === Persistence.LOCAL && isIndexedDBAvailable()),
6671
auth,
67-
AuthErrorCode.UNSUPPORTED_PERSISTENCE
72+
exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE
6873
);
6974
return;
7075
}
7176
// This is restricted by what the browser supports.
7277
_assert(
7378
persistence === Persistence.NONE || _isWebStorageSupported(),
7479
auth,
75-
AuthErrorCode.UNSUPPORTED_PERSISTENCE
80+
exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE
81+
);
82+
}
83+
84+
export async function _savePersistenceForRedirect(auth: AuthInternal): Promise<void> {
85+
await auth._initializationPromise;
86+
87+
const win = getSelfWindow();
88+
const key = exp._persistenceKeyName(
89+
PERSISTENCE_KEY,
90+
auth.config.apiKey,
91+
auth.name
7692
);
93+
if (win?.sessionStorage) {
94+
win.sessionStorage.setItem(key, auth._getPersistence());
95+
}
7796
}
97+
98+
export function _getPersistenceFromRedirect(auth: AuthInternal): exp.Persistence | null {
99+
const win = getSelfWindow();
100+
if (!win?.sessionStorage) {
101+
return null;
102+
}
103+
104+
const key = exp._persistenceKeyName(
105+
PERSISTENCE_KEY,
106+
auth.config.apiKey,
107+
auth.name
108+
);
109+
const persistence = win.sessionStorage.getItem(key);
110+
111+
switch (persistence) {
112+
case exp.inMemoryPersistence.type:
113+
return exp.inMemoryPersistence;
114+
case exp.indexedDBLocalPersistence.type:
115+
return exp.indexedDBLocalPersistence;
116+
case exp.browserSessionPersistence.type:
117+
return exp.browserSessionPersistence;
118+
case exp.browserLocalPersistence.type:
119+
return exp.browserLocalPersistence;
120+
default:
121+
return null;
122+
}
123+
}
124+
125+
function getSelfWindow(): Window | null {
126+
return typeof window !== 'undefined' ? window : null;
127+
}

packages-exp/auth-compat-exp/src/user.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import * as exp from '@firebase/auth-exp/internal';
1919
import * as compat from '@firebase/auth-types';
20+
import { _savePersistenceForRedirect } from './persistence';
2021
import { CompatPopupRedirectResolver } from './popup_redirect';
2122
import {
2223
convertConfirmationResult,
@@ -96,7 +97,8 @@ export class User implements compat.User, Wrapper<exp.User> {
9697
)
9798
);
9899
}
99-
linkWithRedirect(provider: compat.AuthProvider): Promise<void> {
100+
async linkWithRedirect(provider: compat.AuthProvider): Promise<void> {
101+
await _savePersistenceForRedirect(exp._castAuth(this.auth));
100102
return exp.linkWithRedirect(
101103
this.user,
102104
provider as exp.AuthProvider,
@@ -144,7 +146,8 @@ export class User implements compat.User, Wrapper<exp.User> {
144146
)
145147
);
146148
}
147-
reauthenticateWithRedirect(provider: compat.AuthProvider): Promise<void> {
149+
async reauthenticateWithRedirect(provider: compat.AuthProvider): Promise<void> {
150+
await _savePersistenceForRedirect(exp._castAuth(this.auth));
148151
return exp.reauthenticateWithRedirect(
149152
this.user,
150153
provider as exp.AuthProvider,

packages-exp/auth-exp/internal/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export {
3333
} from '../src/model/popup_redirect';
3434
export { UserCredentialInternal, UserParameters } from '../src/model/user';
3535
export { registerAuth } from '../src/core/auth/register';
36-
export { DefaultConfig, AuthImpl } from '../src/core/auth/auth_impl';
36+
export { DefaultConfig, AuthImpl, _castAuth } from '../src/core/auth/auth_impl';
3737

3838
export { ClientPlatform, _getClientVersion } from '../src/core/util/version';
3939

0 commit comments

Comments
 (0)