Merge pull request #2704 from stianst/KEYCLOAK-2838

KEYCLOAK-2838: Add cookie storage fallback to keycloak.js
This commit is contained in:
Stian Thorgersen 2016-04-21 13:37:52 +02:00
commit 19b05ad62f

View file

@ -25,6 +25,7 @@
var kc = this; var kc = this;
var adapter; var adapter;
var refreshQueue = []; var refreshQueue = [];
var storage;
var loginIframe = { var loginIframe = {
enable: true, enable: true,
@ -34,6 +35,9 @@
kc.init = function (initOptions) { kc.init = function (initOptions) {
kc.authenticated = false; kc.authenticated = false;
storage = new PersistentStorage();
if (initOptions && initOptions.adapter === 'cordova') { if (initOptions && initOptions.adapter === 'cordova') {
adapter = loadAdapter('cordova'); adapter = loadAdapter('cordova');
} else if (initOptions && initOptions.adapter === 'default') { } else if (initOptions && initOptions.adapter === 'default') {
@ -45,7 +49,7 @@
adapter = loadAdapter(); adapter = loadAdapter();
} }
} }
if (initOptions) { if (initOptions) {
if (typeof initOptions.checkLoginIframe !== 'undefined') { if (typeof initOptions.checkLoginIframe !== 'undefined') {
loginIframe.enable = initOptions.checkLoginIframe; loginIframe.enable = initOptions.checkLoginIframe;
@ -197,7 +201,7 @@
redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt; redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt;
} }
localStorage.oauthState = JSON.stringify({ state: state, nonce: nonce, redirectUri: encodeURIComponent(redirectUri) }); storage.setItem('oauthState', JSON.stringify({ state: state, nonce: nonce, redirectUri: encodeURIComponent(redirectUri) }));
var action = 'auth'; var action = 'auth';
if (options && options.action == 'register') { if (options && options.action == 'register') {
@ -694,10 +698,11 @@
function parseCallback(url) { function parseCallback(url) {
var oauth = new CallbackParser(url, kc.responseMode).parseUri(); var oauth = new CallbackParser(url, kc.responseMode).parseUri();
var sessionState = localStorage.oauthState && JSON.parse(localStorage.oauthState); var oauthState = storage.getItem('oauthState');
var sessionState = oauthState && JSON.parse(oauthState);
if (sessionState && (oauth.code || oauth.error || oauth.access_token || oauth.id_token) && oauth.state && oauth.state == sessionState.state) { if (sessionState && (oauth.code || oauth.error || oauth.access_token || oauth.id_token) && oauth.state && oauth.state == sessionState.state) {
delete localStorage.oauthState; storage.removeItem('oauthState');
oauth.redirectUri = sessionState.redirectUri; oauth.redirectUri = sessionState.redirectUri;
oauth.storedNonce = sessionState.nonce; oauth.storedNonce = sessionState.nonce;
@ -978,6 +983,82 @@
} }
var PersistentStorage = function() {
if (!(this instanceof PersistentStorage)) {
return new PersistentStorage();
}
var ps = this;
var useCookieStorage = function () {
if (typeof localStorage === "undefined") {
return true;
}
try {
var key = '@@keycloak-session-storage/test';
localStorage.setItem(key, 'test');
localStorage.removeItem(key);
return false;
} 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) {
if (useCookieStorage()) {
setCookie(key, value, cookieExpiration(5));
} else {
localStorage.setItem(key, value);
}
}
ps.getItem = function(key) {
if (useCookieStorage()) {
return getCookie(key);
}
return localStorage.getItem(key);
}
ps.removeItem = function(key) {
if (typeof localStorage !== "undefined") {
try {
// Always try to delete from localStorage.
localStorage.removeItem(key);
} catch (err) { }
}
// Always remove the cookie.
setCookie(key, '', cookieExpiration(-100));
}
var cookieExpiration = function (minutes) {
var exp = new Date();
exp.setTime(exp.getTime() + (minutes*60*1000));
return exp;
}
var getCookie = function (key) {
var name = key + '=';
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return '';
}
var setCookie = function (key, value, expirationDate) {
var cookie = key + '=' + value + '; '
+ 'expires=' + expirationDate.toUTCString() + '; ';
document.cookie = cookie;
}
}
var CallbackParser = function(uriToParse, responseMode) { var CallbackParser = function(uriToParse, responseMode) {
if (!(this instanceof CallbackParser)) { if (!(this instanceof CallbackParser)) {
return new CallbackParser(uriToParse, responseMode); return new CallbackParser(uriToParse, responseMode);