KEYCLOAK-3262 Add support to save multiple state in keycloak.js
This commit is contained in:
parent
435cdb6180
commit
f52504ac41
1 changed files with 90 additions and 52 deletions
|
@ -25,7 +25,7 @@
|
||||||
var kc = this;
|
var kc = this;
|
||||||
var adapter;
|
var adapter;
|
||||||
var refreshQueue = [];
|
var refreshQueue = [];
|
||||||
var storage;
|
var callbackStorage;
|
||||||
|
|
||||||
var loginIframe = {
|
var loginIframe = {
|
||||||
enable: true,
|
enable: true,
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
kc.init = function (initOptions) {
|
kc.init = function (initOptions) {
|
||||||
kc.authenticated = false;
|
kc.authenticated = false;
|
||||||
|
|
||||||
storage = new PersistentStorage();
|
callbackStorage = createCallbackStorage();
|
||||||
|
|
||||||
if (initOptions && initOptions.adapter === 'cordova') {
|
if (initOptions && initOptions.adapter === 'cordova') {
|
||||||
adapter = loadAdapter('cordova');
|
adapter = loadAdapter('cordova');
|
||||||
|
@ -201,7 +201,7 @@
|
||||||
redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt;
|
redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.setItem('oauthState', JSON.stringify({ state: state, nonce: nonce, redirectUri: encodeURIComponent(redirectUri) }));
|
callbackStorage.add({ state: state, nonce: nonce, redirectUri: encodeURIComponent(redirectUri) });
|
||||||
|
|
||||||
var action = 'auth';
|
var action = 'auth';
|
||||||
if (options && options.action == 'register') {
|
if (options && options.action == 'register') {
|
||||||
|
@ -697,15 +697,11 @@
|
||||||
|
|
||||||
function parseCallback(url) {
|
function parseCallback(url) {
|
||||||
var oauth = new CallbackParser(url, kc.responseMode).parseUri();
|
var oauth = new CallbackParser(url, kc.responseMode).parseUri();
|
||||||
|
var oauthState = callbackStorage.get(oauth.state);
|
||||||
|
|
||||||
var oauthState = storage.getItem('oauthState');
|
if (oauthState && (oauth.code || oauth.error || oauth.access_token || oauth.id_token)) {
|
||||||
var sessionState = oauthState && JSON.parse(oauthState);
|
oauth.redirectUri = oauthState.redirectUri;
|
||||||
|
oauth.storedNonce = oauthState.nonce;
|
||||||
if (sessionState && (oauth.code || oauth.error || oauth.access_token || oauth.id_token) && oauth.state && oauth.state == sessionState.state) {
|
|
||||||
storage.removeItem('oauthState');
|
|
||||||
|
|
||||||
oauth.redirectUri = sessionState.redirectUri;
|
|
||||||
oauth.storedNonce = sessionState.nonce;
|
|
||||||
|
|
||||||
if (oauth.fragment) {
|
if (oauth.fragment) {
|
||||||
oauth.newUrl += '#' + oauth.fragment;
|
oauth.newUrl += '#' + oauth.fragment;
|
||||||
|
@ -996,60 +992,93 @@
|
||||||
throw 'invalid adapter type: ' + type;
|
throw 'invalid adapter type: ' + type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var LocalStorage = function() {
|
||||||
var PersistentStorage = function() {
|
if (!(this instanceof LocalStorage)) {
|
||||||
if (!(this instanceof PersistentStorage)) {
|
return new LocalStorage();
|
||||||
return new PersistentStorage();
|
|
||||||
}
|
}
|
||||||
var ps = this;
|
|
||||||
var useCookieStorage = function () {
|
localStorage.setItem('kc-test', 'test');
|
||||||
if (typeof localStorage === "undefined") {
|
localStorage.removeItem('kc-test');
|
||||||
return true;
|
|
||||||
|
var cs = this;
|
||||||
|
|
||||||
|
function clearExpired() {
|
||||||
|
var time = new Date().getTime();
|
||||||
|
for (var i = 1; i <= localStorage.length; i++) {
|
||||||
|
var key = localStorage.key(i);
|
||||||
|
if (key && key.indexOf('kc-callback-') == 0) {
|
||||||
|
var value = localStorage.getItem(key);
|
||||||
|
if (value) {
|
||||||
|
try {
|
||||||
|
var expires = JSON.parse(value).expires;
|
||||||
|
if (!expires || expires < time) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
}
|
||||||
var key = '@@keycloak-session-storage/test';
|
|
||||||
localStorage.setItem(key, 'test');
|
cs.get = function(state) {
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = 'kc-callback-' + state;
|
||||||
|
var value = localStorage.getItem(key);
|
||||||
|
if (value) {
|
||||||
localStorage.removeItem(key);
|
localStorage.removeItem(key);
|
||||||
return false;
|
value = JSON.parse(value);
|
||||||
} catch (err) {
|
|
||||||
// Probably in Safari "private mode" where localStorage
|
|
||||||
// quota is 0, or quota exceeded. Switching to cookie
|
|
||||||
// storage.
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ps.setItem = function(key, value) {
|
clearExpired();
|
||||||
if (useCookieStorage()) {
|
return value;
|
||||||
setCookie(key, value, cookieExpiration(5));
|
};
|
||||||
} else {
|
|
||||||
localStorage.setItem(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.getItem = function(key) {
|
cs.add = function(state) {
|
||||||
if (useCookieStorage()) {
|
clearExpired();
|
||||||
return getCookie(key);
|
|
||||||
}
|
|
||||||
return localStorage.getItem(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.removeItem = function(key) {
|
var key = 'kc-callback-' + state.state;
|
||||||
if (typeof localStorage !== "undefined") {
|
state.expires = new Date().getTime() + (60 * 60 * 1000);
|
||||||
try {
|
localStorage.setItem(key, JSON.stringify(state));
|
||||||
// Always try to delete from localStorage.
|
};
|
||||||
localStorage.removeItem(key);
|
};
|
||||||
} catch (err) { }
|
|
||||||
|
var CookieStorage = function() {
|
||||||
|
if (!(this instanceof CookieStorage)) {
|
||||||
|
return new CookieStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
var cs = this;
|
||||||
|
|
||||||
|
cs.get = function(state) {
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Always remove the cookie.
|
|
||||||
|
var value = getCookie('kc-callback-' + state);
|
||||||
|
setCookie('kc-callback-' + state, '', cookieExpiration(-100));
|
||||||
|
if (value) {
|
||||||
|
return JSON.parse(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cs.add = function(state) {
|
||||||
|
setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60));
|
||||||
|
};
|
||||||
|
|
||||||
|
cs.removeItem = function(key) {
|
||||||
setCookie(key, '', cookieExpiration(-100));
|
setCookie(key, '', cookieExpiration(-100));
|
||||||
}
|
};
|
||||||
|
|
||||||
var cookieExpiration = function (minutes) {
|
var cookieExpiration = function (minutes) {
|
||||||
var exp = new Date();
|
var exp = new Date();
|
||||||
exp.setTime(exp.getTime() + (minutes*60*1000));
|
exp.setTime(exp.getTime() + (minutes*60*1000));
|
||||||
return exp;
|
return exp;
|
||||||
}
|
};
|
||||||
|
|
||||||
var getCookie = function (key) {
|
var getCookie = function (key) {
|
||||||
var name = key + '=';
|
var name = key + '=';
|
||||||
|
@ -1064,13 +1093,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
};
|
||||||
|
|
||||||
var setCookie = function (key, value, expirationDate) {
|
var setCookie = function (key, value, expirationDate) {
|
||||||
var cookie = key + '=' + value + '; '
|
var cookie = key + '=' + value + '; '
|
||||||
+ 'expires=' + expirationDate.toUTCString() + '; ';
|
+ 'expires=' + expirationDate.toUTCString() + '; ';
|
||||||
document.cookie = cookie;
|
document.cookie = cookie;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function createCallbackStorage() {
|
||||||
|
try {
|
||||||
|
return new LocalStorage();
|
||||||
|
} catch (err) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CookieStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
var CallbackParser = function(uriToParse, responseMode) {
|
var CallbackParser = function(uriToParse, responseMode) {
|
||||||
|
|
Loading…
Reference in a new issue