Allow Keycloak JS to be initialized without passing options (#33950)

Closes #8935

Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
Jon Koops 2024-10-15 17:46:15 +02:00 committed by GitHub
parent b76f4f9c1b
commit 228c21a7a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 129 additions and 123 deletions

View file

@ -542,7 +542,7 @@ declare class Keycloak {
* @param initOptions Initialization options. * @param initOptions Initialization options.
* @returns A promise to set functions to be invoked on success or error. * @returns A promise to set functions to be invoked on success or error.
*/ */
init(initOptions: KeycloakInitOptions): Promise<boolean>; init(initOptions?: KeycloakInitOptions): Promise<boolean>;
/** /**
* Redirects to login form. * Redirects to login form.

View file

@ -60,7 +60,7 @@ function Keycloak (config) {
); );
} }
kc.init = function (initOptions) { kc.init = function (initOptions = {}) {
if (kc.didInitialize) { if (kc.didInitialize) {
throw new Error("A 'Keycloak' instance can only be initialized once."); throw new Error("A 'Keycloak' instance can only be initialized once.");
} }
@ -72,9 +72,9 @@ function Keycloak (config) {
callbackStorage = createCallbackStorage(); callbackStorage = createCallbackStorage();
var adapters = ['default', 'cordova', 'cordova-native']; var adapters = ['default', 'cordova', 'cordova-native'];
if (initOptions && adapters.indexOf(initOptions.adapter) > -1) { if (adapters.indexOf(initOptions.adapter) > -1) {
adapter = loadAdapter(initOptions.adapter); adapter = loadAdapter(initOptions.adapter);
} else if (initOptions && typeof initOptions.adapter === "object") { } else if (typeof initOptions.adapter === "object") {
adapter = initOptions.adapter; adapter = initOptions.adapter;
} else { } else {
if (window.Cordova || window.cordova) { if (window.Cordova || window.cordova) {
@ -84,101 +84,99 @@ function Keycloak (config) {
} }
} }
if (initOptions) { if (typeof initOptions.useNonce !== 'undefined') {
if (typeof initOptions.useNonce !== 'undefined') { useNonce = initOptions.useNonce;
useNonce = initOptions.useNonce; }
}
if (typeof initOptions.checkLoginIframe !== 'undefined') { if (typeof initOptions.checkLoginIframe !== 'undefined') {
loginIframe.enable = initOptions.checkLoginIframe; loginIframe.enable = initOptions.checkLoginIframe;
} }
if (initOptions.checkLoginIframeInterval) { if (initOptions.checkLoginIframeInterval) {
loginIframe.interval = initOptions.checkLoginIframeInterval; loginIframe.interval = initOptions.checkLoginIframeInterval;
} }
if (initOptions.onLoad === 'login-required') { if (initOptions.onLoad === 'login-required') {
kc.loginRequired = true; kc.loginRequired = true;
} }
if (initOptions.responseMode) { if (initOptions.responseMode) {
if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') { if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') {
kc.responseMode = initOptions.responseMode; kc.responseMode = initOptions.responseMode;
} else {
throw 'Invalid value for responseMode';
}
}
if (initOptions.flow) {
switch (initOptions.flow) {
case 'standard':
kc.responseType = 'code';
break;
case 'implicit':
kc.responseType = 'id_token token';
break;
case 'hybrid':
kc.responseType = 'code id_token token';
break;
default:
throw 'Invalid value for flow';
}
kc.flow = initOptions.flow;
}
if (initOptions.timeSkew != null) {
kc.timeSkew = initOptions.timeSkew;
}
if(initOptions.redirectUri) {
kc.redirectUri = initOptions.redirectUri;
}
if (initOptions.silentCheckSsoRedirectUri) {
kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri;
}
if (typeof initOptions.silentCheckSsoFallback === 'boolean') {
kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback;
} else { } else {
kc.silentCheckSsoFallback = true; throw 'Invalid value for responseMode';
}
}
if (initOptions.flow) {
switch (initOptions.flow) {
case 'standard':
kc.responseType = 'code';
break;
case 'implicit':
kc.responseType = 'id_token token';
break;
case 'hybrid':
kc.responseType = 'code id_token token';
break;
default:
throw 'Invalid value for flow';
}
kc.flow = initOptions.flow;
}
if (initOptions.timeSkew != null) {
kc.timeSkew = initOptions.timeSkew;
}
if(initOptions.redirectUri) {
kc.redirectUri = initOptions.redirectUri;
}
if (initOptions.silentCheckSsoRedirectUri) {
kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri;
}
if (typeof initOptions.silentCheckSsoFallback === 'boolean') {
kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback;
} else {
kc.silentCheckSsoFallback = true;
}
if (typeof initOptions.pkceMethod !== "undefined") {
if (initOptions.pkceMethod !== "S256" && initOptions.pkceMethod !== false) {
throw new TypeError(`Invalid value for pkceMethod', expected 'S256' or false but got ${initOptions.pkceMethod}.`);
} }
if (typeof initOptions.pkceMethod !== "undefined") { kc.pkceMethod = initOptions.pkceMethod;
if (initOptions.pkceMethod !== "S256" && initOptions.pkceMethod !== false) { } else {
throw new TypeError(`Invalid value for pkceMethod', expected 'S256' or false but got ${initOptions.pkceMethod}.`); kc.pkceMethod = "S256";
} }
kc.pkceMethod = initOptions.pkceMethod; if (typeof initOptions.enableLogging === 'boolean') {
} else { kc.enableLogging = initOptions.enableLogging;
kc.pkceMethod = "S256"; } else {
} kc.enableLogging = false;
}
if (typeof initOptions.enableLogging === 'boolean') { if (initOptions.logoutMethod === 'POST') {
kc.enableLogging = initOptions.enableLogging; kc.logoutMethod = 'POST';
} else { } else {
kc.enableLogging = false; kc.logoutMethod = 'GET';
} }
if (initOptions.logoutMethod === 'POST') { if (typeof initOptions.scope === 'string') {
kc.logoutMethod = 'POST'; kc.scope = initOptions.scope;
} else { }
kc.logoutMethod = 'GET';
}
if (typeof initOptions.scope === 'string') { if (typeof initOptions.acrValues === 'string') {
kc.scope = initOptions.scope; kc.acrValues = initOptions.acrValues;
} }
if (typeof initOptions.acrValues === 'string') { if (typeof initOptions.messageReceiveTimeout === 'number' && initOptions.messageReceiveTimeout > 0) {
kc.acrValues = initOptions.acrValues; kc.messageReceiveTimeout = initOptions.messageReceiveTimeout;
} } else {
kc.messageReceiveTimeout = 10000;
if (typeof initOptions.messageReceiveTimeout === 'number' && initOptions.messageReceiveTimeout > 0) {
kc.messageReceiveTimeout = initOptions.messageReceiveTimeout;
} else {
kc.messageReceiveTimeout = 10000;
}
} }
if (!kc.responseMode) { if (!kc.responseMode) {
@ -207,7 +205,7 @@ function Keycloak (config) {
options.prompt = 'none'; options.prompt = 'none';
} }
if (initOptions && initOptions.locale) { if (initOptions.locale) {
options.locale = initOptions.locale; options.locale = initOptions.locale;
} }
kc.login(options).then(function () { kc.login(options).then(function () {
@ -281,42 +279,40 @@ function Keycloak (config) {
}).catch(function (error) { }).catch(function (error) {
initPromise.setError(error); initPromise.setError(error);
}); });
} else if (initOptions) { }
if (initOptions.token && initOptions.refreshToken) {
setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
if (loginIframe.enable) { if (initOptions.token && initOptions.refreshToken) {
setupCheckLoginIframe().then(function() { setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
checkLoginIframe().then(function (unchanged) {
if (unchanged) { if (loginIframe.enable) {
kc.onAuthSuccess && kc.onAuthSuccess(); setupCheckLoginIframe().then(function() {
initPromise.setSuccess(); checkLoginIframe().then(function (unchanged) {
scheduleCheckIframe(); if (unchanged) {
} else { kc.onAuthSuccess && kc.onAuthSuccess();
initPromise.setSuccess(); initPromise.setSuccess();
} scheduleCheckIframe();
}).catch(function (error) {
initPromise.setError(error);
});
});
} else {
kc.updateToken(-1).then(function() {
kc.onAuthSuccess && kc.onAuthSuccess();
initPromise.setSuccess();
}).catch(function(error) {
kc.onAuthError && kc.onAuthError();
if (initOptions.onLoad) {
onLoad();
} else { } else {
initPromise.setError(error); initPromise.setSuccess();
} }
}).catch(function (error) {
initPromise.setError(error);
}); });
} });
} else if (initOptions.onLoad) {
onLoad();
} else { } else {
initPromise.setSuccess(); kc.updateToken(-1).then(function() {
kc.onAuthSuccess && kc.onAuthSuccess();
initPromise.setSuccess();
}).catch(function(error) {
kc.onAuthError && kc.onAuthError();
if (initOptions.onLoad) {
onLoad();
} else {
initPromise.setError(error);
}
});
} }
} else if (initOptions.onLoad) {
onLoad();
} else { } else {
initPromise.setSuccess(); initPromise.setSuccess();
} }

View file

@ -51,7 +51,7 @@
globalThis.output = output; globalThis.output = output;
globalThis.event = event; globalThis.event = event;
keycloak.init({}).then((authenticated) => { keycloak.init().then((authenticated) => {
output('Init Success (' + (authenticated ? 'Authenticated' : 'Not Authenticated') + ')'); output('Init Success (' + (authenticated ? 'Authenticated' : 'Not Authenticated') + ')');
}).catch(function() { }).catch(function() {
output('Init Error'); output('Init Error');

View file

@ -48,7 +48,7 @@ public class JavascriptTestExecutor {
public JavascriptTestExecutor login() { public JavascriptTestExecutor login() {
return login((String)null, null); return login((String)null, null);
} }
public JavascriptTestExecutor login(JavascriptStateValidator validator) { public JavascriptTestExecutor login(JavascriptStateValidator validator) {
return login((String)null, validator); return login((String)null, validator);
} }
@ -81,10 +81,10 @@ public class JavascriptTestExecutor {
"" + "" +
" // Start observing the target node for configured mutations\n" + " // Start observing the target node for configured mutations\n" +
" observer.observe(targetNode, config);"); " observer.observe(targetNode, config);");
return this; return this;
} }
public JavascriptTestExecutor login(JSObjectBuilder optionsBuilder, JavascriptStateValidator validator) { public JavascriptTestExecutor login(JSObjectBuilder optionsBuilder, JavascriptStateValidator validator) {
return login(optionsBuilder.build(), validator); return login(optionsBuilder.build(), validator);
} }
@ -203,7 +203,7 @@ public class JavascriptTestExecutor {
configure(); configure();
} }
String arguments = argumentsBuilder.build(); String arguments = argumentsBuilder != null ? argumentsBuilder.build() : "";
String script = "var callback = arguments[arguments.length - 1];" + String script = "var callback = arguments[arguments.length - 1];" +
" window.keycloak.init(" + arguments + ").then(function (authenticated) {" + " window.keycloak.init(" + arguments + ").then(function (authenticated) {" +

View file

@ -238,6 +238,16 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
, SuiteContext.BROWSER_STRICT_COOKIES ? this::assertInitNotAuth : this::assertInitAuth); , SuiteContext.BROWSER_STRICT_COOKIES ? this::assertInitNotAuth : this::assertInitAuth);
} }
@Test
public void testInitNoOptions() {
testExecutor.init(null, this::assertInitNotAuth)
.login(this::assertOnLoginPage)
.loginForm(testUser, this::assertOnTestAppUrl)
.init(null, this::assertInitAuth)
.logout(this::assertOnTestAppUrl)
.init(null, this::assertInitNotAuth);
}
@Test @Test
public void testCheckSso() { public void testCheckSso() {
JSObjectBuilder checkSSO = defaultArguments().checkSSOOnLoad(); JSObjectBuilder checkSSO = defaultArguments().checkSSOOnLoad();