Skip to content

Commit c9c0ae8

Browse files
committed
Fix bug in compat layer when cookies are disabled
1 parent 2d04af9 commit c9c0ae8

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

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

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import * as sinon from 'sinon';
2323
import sinonChai from 'sinon-chai';
2424
import { Auth } from './auth';
2525
import { CompatPopupRedirectResolver } from './popup_redirect';
26+
import * as platform from './platform';
2627

2728
use(sinonChai);
2829

@@ -45,7 +46,7 @@ describe('auth compat', () => {
4546
});
4647

4748
afterEach(() => {
48-
sinon.restore;
49+
sinon.restore();
4950
});
5051

5152
it('saves the persistence into session storage if available', async () => {
@@ -75,6 +76,36 @@ describe('auth compat', () => {
7576
}
7677
});
7778

79+
it('does not save persistence if property throws DOMException', async () => {
80+
if (typeof self !== 'undefined') {
81+
sinon.stub(platform, '_getSelfWindow').returns({
82+
get sessionStorage(): Storage {
83+
throw new DOMException('Nope!');
84+
}
85+
} as unknown as Window);
86+
const setItemSpy = sinon.spy(sessionStorage, 'setItem');
87+
sinon.stub(underlyingAuth, '_getPersistence').returns('TEST');
88+
sinon
89+
.stub(underlyingAuth, '_initializationPromise')
90+
.value(Promise.resolve());
91+
sinon.stub(
92+
exp._getInstance<exp.PopupRedirectResolverInternal>(
93+
CompatPopupRedirectResolver
94+
),
95+
'_openRedirect'
96+
);
97+
providerStub.isInitialized.returns(true);
98+
providerStub.getImmediate.returns(underlyingAuth);
99+
const authCompat = new Auth(
100+
app,
101+
providerStub as unknown as Provider<'auth'>
102+
);
103+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
104+
await authCompat.signInWithRedirect(new exp.GoogleAuthProvider());
105+
expect(setItemSpy).not.to.have.been.calledWith('firebase:persistence:api-key:undefined', 'TEST');
106+
}
107+
});
108+
78109
it('pulls the persistence and sets as the main persitsence if set', () => {
79110
if (typeof self !== 'undefined') {
80111
sessionStorage.setItem(
@@ -98,5 +129,34 @@ describe('auth compat', () => {
98129
});
99130
}
100131
});
132+
133+
it('does not die if sessionStorage errors', () => {
134+
if (typeof self !== 'undefined') {
135+
sinon.stub(platform, '_getSelfWindow').returns({
136+
get sessionStorage(): Storage {
137+
throw new DOMException('Nope!');
138+
}
139+
} as unknown as Window);
140+
sessionStorage.setItem(
141+
'firebase:persistence:api-key:undefined',
142+
'none'
143+
);
144+
providerStub.isInitialized.returns(false);
145+
providerStub.initialize.returns(underlyingAuth);
146+
new Auth(app, providerStub as unknown as Provider<'auth'>);
147+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
148+
expect(providerStub.initialize).to.have.been.calledWith({
149+
options: {
150+
popupRedirectResolver: CompatPopupRedirectResolver,
151+
persistence: [
152+
exp.indexedDBLocalPersistence,
153+
exp.browserLocalPersistence,
154+
exp.browserSessionPersistence,
155+
exp.inMemoryPersistence,
156+
]
157+
}
158+
});
159+
}
160+
});
101161
});
102162
});

packages/auth-compat/src/persistence.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import * as exp from '@firebase/auth/internal';
1919
import { isIndexedDBAvailable, isNode, isReactNative } from '@firebase/util';
20-
import { _isWebStorageSupported, _isWorker } from './platform';
20+
import { _getSelfWindow, _isWebStorageSupported, _isWorker } from './platform';
2121

2222
export const Persistence = {
2323
LOCAL: 'local',
@@ -84,29 +84,28 @@ export async function _savePersistenceForRedirect(
8484
auth: exp.AuthInternal
8585
): Promise<void> {
8686
await auth._initializationPromise;
87-
88-
const win = getSelfWindow();
87+
const session = getSessionStorageIfAvailable();
8988
const key = exp._persistenceKeyName(
9089
PERSISTENCE_KEY,
9190
auth.config.apiKey,
9291
auth.name
9392
);
94-
if (win?.sessionStorage) {
95-
win.sessionStorage.setItem(key, auth._getPersistence());
93+
if (session) {
94+
session.setItem(key, auth._getPersistence());
9695
}
9796
}
9897

9998
export function _getPersistencesFromRedirect(
10099
apiKey: string,
101100
appName: string
102101
): exp.Persistence[] {
103-
const win = getSelfWindow();
104-
if (!win?.sessionStorage) {
102+
const session = getSessionStorageIfAvailable();
103+
if (!session) {
105104
return [];
106105
}
107106

108107
const key = exp._persistenceKeyName(PERSISTENCE_KEY, apiKey, appName);
109-
const persistence = win.sessionStorage.getItem(key);
108+
const persistence = session.getItem(key);
110109

111110
switch (persistence) {
112111
case Persistence.NONE:
@@ -120,6 +119,11 @@ export function _getPersistencesFromRedirect(
120119
}
121120
}
122121

123-
function getSelfWindow(): Window | null {
124-
return typeof window !== 'undefined' ? window : null;
122+
/** Returns session storage, or null if the property access errors */
123+
function getSessionStorageIfAvailable(): Storage | null {
124+
try {
125+
return _getSelfWindow()?.sessionStorage || null;
126+
} catch (e) {
127+
return null;
128+
}
125129
}

packages/auth-compat/src/platform.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,7 @@ export async function _isCordova(): Promise<boolean> {
171171
});
172172
});
173173
}
174+
175+
export function _getSelfWindow(): Window | null {
176+
return typeof window !== 'undefined' ? window : null;
177+
}

0 commit comments

Comments
 (0)