Skip to content

Commit 46f9a14

Browse files
Merge pull request #2144 from bashhack/fix/browser-storage-clear-scope
fix: prevent clear() from destroying all sessionStorage
2 parents 0aa9e8d + d16ac12 commit 46f9a14

File tree

2 files changed

+95
-24
lines changed

2 files changed

+95
-24
lines changed

projects/angular-auth-oidc-client/src/lib/storage/browser-storage.service.spec.ts

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,22 @@ describe('BrowserStorageService', () => {
114114
expect(service.remove('anything', config)).toBeFalse();
115115
});
116116

117-
it('returns true if removeItem is called', () => {
117+
it('returns false if configId is missing', () => {
118+
const config = { configId: '' };
119+
120+
spyOn(service as any, 'hasStorage').and.returnValue(true);
121+
expect(service.remove('anyKey', config)).toBeFalse();
122+
});
123+
124+
it('removes the entire config blob for the configId', () => {
118125
spyOn(service as any, 'hasStorage').and.returnValue(true);
119-
const config = { configId: 'configId1' }; const setItemSpy = spyOn(
126+
const config = { configId: 'configId1' }; const removeSpy = spyOn(
120127
abstractSecurityStorage,
121128
'remove'
122129
).and.callThrough(); const result = service.remove('anyKey', config);
123130

124131
expect(result).toBe(true);
125-
expect(setItemSpy).toHaveBeenCalledOnceWith('anyKey');
132+
expect(removeSpy).toHaveBeenCalledOnceWith('configId1');
126133
});
127134
});
128135

@@ -134,17 +141,74 @@ describe('BrowserStorageService', () => {
134141
expect(service.clear(config)).toBeFalse();
135142
});
136143

137-
it('returns true if clear is called', () => {
144+
it('returns false if configId is missing', () => {
145+
const config = { configId: '' };
146+
147+
spyOn(service as any, 'hasStorage').and.returnValue(true);
148+
expect(service.clear(config)).toBeFalse();
149+
});
150+
151+
it('removes only the config blob for the specified configId', () => {
138152
spyOn(service as any, 'hasStorage').and.returnValue(true);
139153

140-
const setItemSpy = spyOn(
154+
const removeSpy = spyOn(
141155
abstractSecurityStorage,
142-
'clear'
156+
'remove'
143157
).and.callThrough();
144158
const config = { configId: 'configId1' }; const result = service.clear(config);
145159

146160
expect(result).toBe(true);
147-
expect(setItemSpy).toHaveBeenCalledTimes(1);
161+
expect(removeSpy).toHaveBeenCalledOnceWith('configId1');
162+
});
163+
});
164+
165+
describe('multi-config isolation', () => {
166+
it('clear() should only remove the specified config, not other configs', () => {
167+
spyOn(service as any, 'hasStorage').and.returnValue(true);
168+
const config1 = { configId: 'configId1' }; const removeSpy = spyOn(abstractSecurityStorage, 'remove');
169+
170+
service.clear(config1);
171+
172+
expect(removeSpy).toHaveBeenCalledOnceWith('configId1');
173+
expect(removeSpy).not.toHaveBeenCalledWith('configId2');
174+
});
175+
176+
it('remove() should only remove the specified config blob, not other configs', () => {
177+
spyOn(service as any, 'hasStorage').and.returnValue(true);
178+
const config1 = { configId: 'configId1' }; const removeSpy = spyOn(abstractSecurityStorage, 'remove');
179+
180+
service.remove('anyKey', config1);
181+
182+
expect(removeSpy).toHaveBeenCalledOnceWith('configId1');
183+
expect(removeSpy).not.toHaveBeenCalledWith('configId2');
184+
});
185+
});
186+
187+
describe('storage scope safety', () => {
188+
it('clear() should not call abstractSecurityStorage.clear() which would destroy all storage', () => {
189+
spyOn(service as any, 'hasStorage').and.returnValue(true);
190+
const config = { configId: 'configId1' }; const clearSpy = spyOn(abstractSecurityStorage, 'clear');
191+
const removeSpy = spyOn(abstractSecurityStorage, 'remove');
192+
193+
service.clear(config);
194+
195+
// Should use remove(configId), NOT clear()
196+
// This ensures other configs and consumer app data remain intact
197+
expect(clearSpy).not.toHaveBeenCalled();
198+
expect(removeSpy).toHaveBeenCalledOnceWith('configId1');
199+
});
200+
201+
it('remove() should not call abstractSecurityStorage.clear() which would destroy all storage', () => {
202+
spyOn(service as any, 'hasStorage').and.returnValue(true);
203+
const config = { configId: 'configId1' }; const clearSpy = spyOn(abstractSecurityStorage, 'clear');
204+
const removeSpy = spyOn(abstractSecurityStorage, 'remove');
205+
206+
service.remove('anyKey', config);
207+
208+
// Should use remove(configId), NOT clear()
209+
// This ensures other configs and consumer app data remain intact
210+
expect(clearSpy).not.toHaveBeenCalled();
211+
expect(removeSpy).toHaveBeenCalledOnceWith('configId1');
148212
});
149213
});
150214

projects/angular-auth-oidc-client/src/lib/storage/browser-storage.service.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,46 +67,53 @@ export class BrowserStorageService {
6767
}
6868

6969
remove(key: string, configuration: OpenIdConfiguration): boolean {
70-
if (!this.hasStorage()) {
70+
const { configId } = configuration;
71+
72+
if (!configId) {
7173
this.loggerService.logDebug(
7274
configuration,
73-
`Wanted to remove '${key}' but Storage was falsy`
75+
`Wanted to remove '${key}' but configId was '${configId}'`
7476
);
7577

7678
return false;
7779
}
7880

79-
// const storage = this.getStorage(configuration);
80-
// if (!storage) {
81-
// this.loggerService.logDebug(configuration, `Wanted to write '${key}' but Storage was falsy`);
81+
if (!this.hasStorage()) {
82+
this.loggerService.logDebug(
83+
configuration,
84+
`Wanted to remove '${key}' but Storage was falsy`
85+
);
8286

83-
// return false;
84-
// }
87+
return false;
88+
}
8589

86-
this.abstractSecurityStorage.remove(key);
90+
this.abstractSecurityStorage.remove(configId);
8791

8892
return true;
8993
}
9094

91-
// TODO THIS STORAGE WANTS AN ID BUT CLEARS EVERYTHING
9295
clear(configuration: OpenIdConfiguration): boolean {
93-
if (!this.hasStorage()) {
96+
const { configId } = configuration;
97+
98+
if (!configId) {
9499
this.loggerService.logDebug(
95100
configuration,
96-
`Wanted to clear storage but Storage was falsy`
101+
`Wanted to clear storage but configId was '${configId}'`
97102
);
98103

99104
return false;
100105
}
101106

102-
// const storage = this.getStorage(configuration);
103-
// if (!storage) {
104-
// this.loggerService.logDebug(configuration, `Wanted to clear storage but Storage was falsy`);
107+
if (!this.hasStorage()) {
108+
this.loggerService.logDebug(
109+
configuration,
110+
`Wanted to clear storage but Storage was falsy`
111+
);
105112

106-
// return false;
107-
// }
113+
return false;
114+
}
108115

109-
this.abstractSecurityStorage.clear();
116+
this.abstractSecurityStorage.remove(configId);
110117

111118
return true;
112119
}

0 commit comments

Comments
 (0)