KEYCLOAK-14412 Keycloak.js should honor scopes configured in initOptions and loginOptions

This commit is contained in:
Thomas Darimont 2020-06-05 23:18:58 +02:00 committed by Bruno Oliveira da Silva
parent 4946484cb6
commit b926cd20f1
4 changed files with 66 additions and 11 deletions

View file

@ -182,7 +182,8 @@ declare namespace Keycloak {
interface KeycloakLoginOptions {
/**
* @private Undocumented.
* Specifies the scope parameter for the login url
* The scope 'openid' will be added to the scope if it is missing or undefined.
*/
scope?: string;

View file

@ -191,6 +191,10 @@
} else {
kc.enableLogging = false;
}
if (typeof initOptions.scope === "string") {
kc.scope = initOptions.scope;
}
}
if (!kc.responseMode) {
@ -433,15 +437,13 @@
baseUrl = kc.endpoints.authorize();
}
var scope;
if (options && options.scope) {
if (options.scope.indexOf("openid") != -1) {
scope = options.scope;
} else {
scope = "openid " + options.scope;
}
} else {
var scope = options && options.scope || kc.scope;
if (!scope) {
// if scope is not set, default to "openid"
scope = "openid";
} else if (scope.indexOf("openid") === -1) {
// if openid scope is missing, prefix the given scopes with it
scope = "openid " + scope;
}
var url = baseUrl

View file

@ -42,11 +42,11 @@ public class JavascriptTestExecutor {
}
public JavascriptTestExecutor login() {
return login(null, null);
return login((String)null, null);
}
public JavascriptTestExecutor login(JavascriptStateValidator validator) {
return login(null, validator);
return login((String)null, validator);
}
/**
@ -81,6 +81,10 @@ public class JavascriptTestExecutor {
return this;
}
public JavascriptTestExecutor login(JSObjectBuilder optionsBuilder, JavascriptStateValidator validator) {
return login(optionsBuilder.build(), validator);
}
public JavascriptTestExecutor login(String options, JavascriptStateValidator validator) {
if (options == null)
jsExecutor.executeScript("keycloak.login()");

View file

@ -30,6 +30,7 @@ import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.UserBuilder;
import org.keycloak.testsuite.util.javascript.JSObjectBuilder;
import org.keycloak.testsuite.util.javascript.JavascriptStateValidator;
import org.keycloak.testsuite.util.javascript.JavascriptTestExecutor;
import org.keycloak.testsuite.util.javascript.XMLHttpRequest;
import org.openqa.selenium.TimeoutException;
@ -450,6 +451,53 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
.init(defaultArguments(), this::assertInitAuth);
}
/**
* Test for scope handling via {@code initOptions}: <pre>{@code
* Keycloak keycloak = new Keycloak(); keycloak.init({.... scope: "profile email phone"})
* }</pre>
* See KEYCLOAK-14412
*/
@Test
public void testScopeInInitOptionsShouldBeConsideredByLoginUrl() {
JSObjectBuilder initOptions = defaultArguments()
.loginRequiredOnLoad()
// phone is optional client scope
.add("scope", "profile email phone");
try {
testExecutor.init(initOptions);
// This throws exception because when JavascriptExecutor waits for AsyncScript to finish
// it is redirected to login page and executor gets no response
throw new RuntimeException("Probably the login-required OnLoad mode doesn't work, because testExecutor should fail with error that page was redirected.");
} catch (WebDriverException ex) {
// should happen
}
testExecutor.loginForm(testUser, this::assertOnTestAppUrl)
.init(initOptions, this::assertSuccessfullyLoggedIn)
.executeScript("return window.keycloak.tokenParsed.scope", assertOutputContains("phone"));
}
/**
* Test for scope handling via {@code loginOptions}: <pre>{@code
* Keycloak keycloak = new Keycloak(); keycloak.login({.... scope: "profile email phone"})
* }</pre>
* See KEYCLOAK-14412
*/
@Test
public void testScopeInLoginOptionsShouldBeConsideredByLoginUrl() {
testExecutor.configure().init(defaultArguments());
JSObjectBuilder loginOptions = JSObjectBuilder.create().add("scope", "profile email phone");
testExecutor.login(loginOptions, (JavascriptStateValidator) (driver, output, events) -> {
assertThat(driver.getCurrentUrl(), containsString("&scope=openid%20profile%20email%20phone"));
});
}
@Test
public void testUpdateToken() {
XMLHttpRequest request = XMLHttpRequest.create()