Skip to content

Commit c3e5d5a

Browse files
authored
Fix up the redirect persistence storage in Auth Compat (#4537)
* Fix bug where immediate redirects in compat were broken; also save redirect persistence before link and reauth as well * Formatting
1 parent 04e5322 commit c3e5d5a

File tree

5 files changed

+91
-60
lines changed

5 files changed

+91
-60
lines changed

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,22 @@ 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
51+
.stub(underlyingAuth, '_initializationPromise')
52+
.value(Promise.resolve());
53+
sinon.stub(
54+
exp._getInstance<exp.PopupRedirectResolverInternal>(
55+
CompatPopupRedirectResolver
56+
),
57+
'_openRedirect'
58+
);
59+
const authCompat = new Auth(app, underlyingAuth);
5060
// eslint-disable-next-line @typescript-eslint/no-floating-promises
51-
authCompat.signInWithRedirect(new exp.GoogleAuthProvider());
61+
await authCompat.signInWithRedirect(new exp.GoogleAuthProvider());
5262
expect(
5363
sessionStorage.getItem('firebase:persistence:api-key:undefined')
5464
).to.eq('TEST');

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

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

28-
import { _validatePersistenceArgument, Persistence } from './persistence';
28+
import {
29+
_validatePersistenceArgument,
30+
Persistence,
31+
_getPersistenceFromRedirect,
32+
_savePersistenceForRedirect
33+
} from './persistence';
2934
import { _isPopupRedirectSupported } from './platform';
3035
import { CompatPopupRedirectResolver } from './popup_redirect';
3136
import { User } from './user';
@@ -35,7 +40,6 @@ import {
3540
} from './user_credential';
3641
import { unwrap, Wrapper } from './wrap';
3742

38-
const PERSISTENCE_KEY = 'persistence';
3943
const _assert: typeof exp._assert = exp._assert;
4044

4145
export class Auth
@@ -51,7 +55,7 @@ export class Auth
5155
// Note this is slightly different behavior: in this case, the stored
5256
// persistence is checked *first* rather than last. This is because we want
5357
// the fallback (if no user is found) to be the stored persistence type
54-
const storedPersistence = this.getPersistenceFromRedirect();
58+
const storedPersistence = _getPersistenceFromRedirect(this.auth);
5559
const persistences = storedPersistence ? [storedPersistence] : [];
5660
persistences.push(exp.indexedDBLocalPersistence);
5761

@@ -294,7 +298,8 @@ export class Auth
294298
this.auth,
295299
exp.AuthErrorCode.OPERATION_NOT_SUPPORTED
296300
);
297-
this.savePersistenceForRedirect();
301+
302+
await _savePersistenceForRedirect(this.auth);
298303
return exp.signInWithRedirect(
299304
this.auth,
300305
provider as exp.AuthProvider,
@@ -313,49 +318,6 @@ export class Auth
313318
_delete(): Promise<void> {
314319
return this.auth._delete();
315320
}
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;
359321
}
360322

361323
function wrapObservers(

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

Lines changed: 61 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,63 @@ 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(
85+
auth: AuthInternal
86+
): Promise<void> {
87+
await auth._initializationPromise;
88+
89+
const win = getSelfWindow();
90+
const key = exp._persistenceKeyName(
91+
PERSISTENCE_KEY,
92+
auth.config.apiKey,
93+
auth.name
94+
);
95+
if (win?.sessionStorage) {
96+
win.sessionStorage.setItem(key, auth._getPersistence());
97+
}
98+
}
99+
100+
export function _getPersistenceFromRedirect(
101+
auth: AuthInternal
102+
): exp.Persistence | null {
103+
const win = getSelfWindow();
104+
if (!win?.sessionStorage) {
105+
return null;
106+
}
107+
108+
const key = exp._persistenceKeyName(
109+
PERSISTENCE_KEY,
110+
auth.config.apiKey,
111+
auth.name
76112
);
113+
const persistence = win.sessionStorage.getItem(key);
114+
115+
switch (persistence) {
116+
case exp.inMemoryPersistence.type:
117+
return exp.inMemoryPersistence;
118+
case exp.indexedDBLocalPersistence.type:
119+
return exp.indexedDBLocalPersistence;
120+
case exp.browserSessionPersistence.type:
121+
return exp.browserSessionPersistence;
122+
case exp.browserLocalPersistence.type:
123+
return exp.browserLocalPersistence;
124+
default:
125+
return null;
126+
}
127+
}
128+
129+
function getSelfWindow(): Window | null {
130+
return typeof window !== 'undefined' ? window : null;
77131
}

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

Lines changed: 7 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,10 @@ export class User implements compat.User, Wrapper<exp.User> {
144146
)
145147
);
146148
}
147-
reauthenticateWithRedirect(provider: compat.AuthProvider): Promise<void> {
149+
async reauthenticateWithRedirect(
150+
provider: compat.AuthProvider
151+
): Promise<void> {
152+
await _savePersistenceForRedirect(exp._castAuth(this.auth));
148153
return exp.reauthenticateWithRedirect(
149154
this.user,
150155
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)