Clear all entries stored in local storage (#34056)

Closes #15635

Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
Jon Koops 2024-10-17 19:23:40 +02:00 committed by GitHub
parent da34571769
commit 31ce14a400
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1589,6 +1589,8 @@ function Keycloak (config) {
throw 'invalid adapter type: ' + type; throw 'invalid adapter type: ' + type;
} }
const STORAGE_KEY_PREFIX = 'kc-callback-';
var LocalStorage = function() { var LocalStorage = function() {
if (!(this instanceof LocalStorage)) { if (!(this instanceof LocalStorage)) {
return new LocalStorage(); return new LocalStorage();
@ -1599,46 +1601,71 @@ function Keycloak (config) {
var cs = this; var cs = this;
function clearExpired() { /**
var time = new Date().getTime(); * Clears all values from local storage that are no longer valid.
for (var i = 0; i < localStorage.length; i++) { */
var key = localStorage.key(i); function clearInvalidValues() {
if (key && key.indexOf('kc-callback-') == 0) { const currentTime = Date.now();
var value = localStorage.getItem(key);
if (value) { for (const [key, value] of Object.entries(localStorage)) {
try { // Ignore values not known to be stored by us.
var expires = JSON.parse(value).expires; if (!key.startsWith(STORAGE_KEY_PREFIX)) {
if (!expires || expires < time) { continue;
localStorage.removeItem(key); }
}
} catch (err) { // Attempt to parse the expiry time from the value.
localStorage.removeItem(key); const expiry = parseExpiry(value);
}
} // Discard the value if it is malformed or expired.
if (expiry === null || expiry < currentTime) {
localStorage.removeItem(key);
} }
} }
} }
/**
* Parses the expiry time from a value stored in local storage.
* @param {unknown} value
* @returns {number | null} The expiry time in milliseconds, or `null` if the value is malformed.
*/
function parseExpiry(value) {
let parsedValue;
// Attempt to parse the value as JSON.
try {
parsedValue = JSON.parse(value);
} catch (error) {
return null;
}
// Attempt to extract the 'expires' property.
if (isObject(parsedValue) && 'expires' in parsedValue && typeof parsedValue.expires === 'number') {
return parsedValue.expires;
}
return null;
}
cs.get = function(state) { cs.get = function(state) {
if (!state) { if (!state) {
return; return;
} }
var key = 'kc-callback-' + state; var key = STORAGE_KEY_PREFIX + state;
var value = localStorage.getItem(key); var value = localStorage.getItem(key);
if (value) { if (value) {
localStorage.removeItem(key); localStorage.removeItem(key);
value = JSON.parse(value); value = JSON.parse(value);
} }
clearExpired(); clearInvalidValues();
return value; return value;
}; };
cs.add = function(state) { cs.add = function(state) {
clearExpired(); clearInvalidValues();
var key = 'kc-callback-' + state.state; var key = STORAGE_KEY_PREFIX + state.state;
state.expires = new Date().getTime() + (60 * 60 * 1000); state.expires = new Date().getTime() + (60 * 60 * 1000);
localStorage.setItem(key, JSON.stringify(state)); localStorage.setItem(key, JSON.stringify(state));
}; };
@ -1656,15 +1683,15 @@ function Keycloak (config) {
return; return;
} }
var value = getCookie('kc-callback-' + state); var value = getCookie(STORAGE_KEY_PREFIX + state);
setCookie('kc-callback-' + state, '', cookieExpiration(-100)); setCookie(STORAGE_KEY_PREFIX + state, '', cookieExpiration(-100));
if (value) { if (value) {
return JSON.parse(value); return JSON.parse(value);
} }
}; };
cs.add = function(state) { cs.add = function(state) {
setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60)); setCookie(STORAGE_KEY_PREFIX + state.state, JSON.stringify(state), cookieExpiration(60));
}; };
cs.removeItem = function(key) { cs.removeItem = function(key) {