mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Use back keycloak-js instead of initiate login in the backend for account (#42035)
Closes #40463 Signed-off-by: rmartinc <rmartinc@redhat.com> (cherry picked from commit 360ff7050c290939d529e68b461ba61c7c11404a)
This commit is contained in:
parent
3ff08efd66
commit
9804b53f3b
@ -215,4 +215,22 @@ organizationList=List of organizations
|
||||
domains=Domains
|
||||
refresh=Refresh
|
||||
termsAndConditionsDeclined=You need to accept the Terms and Conditions to continue
|
||||
defaultLocale=Choose...
|
||||
defaultLocale=Choose...
|
||||
# standard error responses OAuth
|
||||
invalid_request=Invalid request
|
||||
unauthorized_client=Unauthorized client
|
||||
access_denied=Access denied
|
||||
unsupported_response_type=Unsupported response type
|
||||
invalid_scope=Invalid scope
|
||||
server_error=Server error
|
||||
temporarily_unavailable=Temporarily unavailable
|
||||
# standard error responses OIDC
|
||||
interaction_required=Interaction required
|
||||
login_required=Login required
|
||||
account_selection_required=Account selection required
|
||||
consent_required=Consent required
|
||||
invalid_request_uri=Invalid request uri
|
||||
invalid_request_object=Invalid request object
|
||||
request_not_supported=Request not supported
|
||||
request_uri_not_supported=Request uri not supported
|
||||
registration_not_supported=Registration not supported
|
||||
|
||||
@ -3502,3 +3502,21 @@ givenNameClaim=Given name Claim
|
||||
givenNameClaimHelp=The name of the claim from the JSON document returned by the user profile endpoint representing the user's given name. If not provided, defaults to `given_name`.
|
||||
familyNameClaim=Family name Claim
|
||||
familyNameClaimHelp=The name of the claim from the JSON document returned by the user profile endpoint representing the user's family name. If not provided, defaults to `family_name`.
|
||||
# standard error responses OAuth
|
||||
invalid_request=Invalid request
|
||||
unauthorized_client=Unauthorized client
|
||||
access_denied=Access denied
|
||||
unsupported_response_type=Unsupported response type
|
||||
invalid_scope=Invalid scope
|
||||
server_error=Server error
|
||||
temporarily_unavailable=Temporarily unavailable
|
||||
# standard error responses OIDC
|
||||
interaction_required=Interaction required
|
||||
login_required=Login required
|
||||
account_selection_required=Account selection required
|
||||
consent_required=Consent required
|
||||
invalid_request_uri=Invalid request uri
|
||||
invalid_request_object=Invalid request object
|
||||
request_not_supported=Request not supported
|
||||
request_uri_not_supported=Request uri not supported
|
||||
registration_not_supported=Registration not supported
|
||||
|
||||
@ -7,18 +7,17 @@ import {
|
||||
TextContent,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getNetworkErrorDescription } from "../utils/errors";
|
||||
import { getNetworkErrorMessage } from "../utils/errors";
|
||||
|
||||
type ErrorPageProps = {
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export const ErrorPage = (props: ErrorPageProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const error = props.error;
|
||||
const errorMessage =
|
||||
getErrorMessage(error) ||
|
||||
getNetworkErrorDescription(error)?.replace(/\+/g, " ");
|
||||
const errorMessage = getErrorMessage(error);
|
||||
const networkErrorMessage = getNetworkErrorMessage(error);
|
||||
console.error(error);
|
||||
|
||||
function onRetry() {
|
||||
@ -29,7 +28,7 @@ export const ErrorPage = (props: ErrorPageProps) => {
|
||||
<Page>
|
||||
<Modal
|
||||
variant={ModalVariant.small}
|
||||
title={errorMessage ? "" : t("somethingWentWrong")}
|
||||
title={t("somethingWentWrong")}
|
||||
titleIconVariant="danger"
|
||||
showClose={false}
|
||||
isOpen
|
||||
@ -42,6 +41,8 @@ export const ErrorPage = (props: ErrorPageProps) => {
|
||||
<TextContent>
|
||||
{errorMessage ? (
|
||||
<Text>{t(errorMessage)}</Text>
|
||||
) : networkErrorMessage && i18n.exists(networkErrorMessage) ? (
|
||||
<Text>{t(networkErrorMessage)}</Text>
|
||||
) : (
|
||||
<Text>{t("somethingWentWrongDescription")}</Text>
|
||||
)}
|
||||
@ -52,10 +53,6 @@ export const ErrorPage = (props: ErrorPageProps) => {
|
||||
};
|
||||
|
||||
function getErrorMessage(error: unknown): string | null {
|
||||
if (typeof error === "string") {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
return error.message;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ export const KeycloakProvider = <T extends BaseEnvironment>({
|
||||
|
||||
const init = () =>
|
||||
keycloak.init({
|
||||
onLoad: "check-sso",
|
||||
onLoad: "login-required",
|
||||
pkceMethod: "S256",
|
||||
responseMode: "query",
|
||||
scope: environment.scope,
|
||||
@ -80,14 +80,8 @@ export const KeycloakProvider = <T extends BaseEnvironment>({
|
||||
calledOnce.current = true;
|
||||
}, [keycloak]);
|
||||
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
if (error || searchParams.get("error_description")) {
|
||||
return (
|
||||
<ErrorPage
|
||||
error={error ? error : searchParams.get("error_description")}
|
||||
/>
|
||||
);
|
||||
if (error) {
|
||||
return <ErrorPage error={error} />;
|
||||
}
|
||||
|
||||
if (!init) {
|
||||
|
||||
@ -3,13 +3,9 @@ package org.keycloak.services.resources.account;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.ServerErrorException;
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
import org.jboss.resteasy.reactive.NoCache;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.authentication.requiredactions.DeleteAccount;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.Version;
|
||||
@ -18,7 +14,6 @@ import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.IdentityProviderStorageProvider;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.utils.PkceUtils;
|
||||
import org.keycloak.utils.SecureContextResolver;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.ClientModel;
|
||||
@ -28,7 +23,6 @@ import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.protocol.oidc.utils.RedirectUtils;
|
||||
import org.keycloak.services.Urls;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
@ -46,18 +40,15 @@ import org.keycloak.theme.freemarker.FreeMarkerProvider;
|
||||
import org.keycloak.urls.UrlType;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.utils.MediaType;
|
||||
import org.keycloak.utils.StringUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -110,10 +101,6 @@ public class AccountConsole implements AccountResourceProvider {
|
||||
@Path("{path:.*}")
|
||||
public Response getMainPage(@PathParam("path") String path) throws IOException, FreeMarkerException {
|
||||
|
||||
if (auth == null) {
|
||||
return redirectToLogin(path);
|
||||
}
|
||||
|
||||
return renderAccountConsole();
|
||||
}
|
||||
|
||||
@ -232,77 +219,6 @@ public class AccountConsole implements AccountResourceProvider {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private Response redirectToLogin(String path) {
|
||||
UriBuilder consoleUriBuilder = Urls.accountBase(session.getContext().getUri().getBaseUri());
|
||||
if (!StringUtil.isNullOrEmpty(path)) {
|
||||
consoleUriBuilder.path(path);
|
||||
}
|
||||
var queryParameters = session.getContext().getUri().getQueryParameters();
|
||||
if (!queryParameters.isEmpty()) {
|
||||
String referrer = queryParameters.getFirst("referrer");
|
||||
if (referrer != null) {
|
||||
consoleUriBuilder.queryParam("referrer", referrer);
|
||||
}
|
||||
|
||||
String referrerUri = queryParameters.getFirst("referrer_uri");
|
||||
if (referrerUri != null) {
|
||||
consoleUriBuilder.queryParam("referrer_uri", referrerUri);
|
||||
}
|
||||
}
|
||||
URI targetUri = consoleUriBuilder.build(realm.getName());
|
||||
|
||||
String pkceChallenge;
|
||||
try {
|
||||
// Add PKCE parameters as it is required for the account-console client.
|
||||
// Because the account console configuration requires PKCE, we need to send this with the redirect in order to not fail validations.
|
||||
// The real PKCE challenge will be sent by the account-console OIDC client JavaScript integration.
|
||||
String codeVerifier = UUID.randomUUID().toString();
|
||||
pkceChallenge = PkceUtils.generateS256CodeChallenge(codeVerifier);
|
||||
} catch (Exception e) {
|
||||
// this should never happen
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
UriBuilder uriBuilder = UriBuilder.fromUri(OIDCLoginProtocolService.authUrl(session.getContext().getUri()).build(realm.getName()).toString())
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, Constants.ACCOUNT_CONSOLE_CLIENT_ID)
|
||||
.queryParam(OAuth2Constants.REDIRECT_URI, targetUri)
|
||||
// dummy state param to make it usable with secure-session client policy.
|
||||
// Once bootstrapped the account-console frontend will send the actual state with the authorize request.
|
||||
.queryParam(OAuth2Constants.STATE, UUID.randomUUID().toString())
|
||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||
.queryParam(OAuth2Constants.CODE_CHALLENGE, pkceChallenge)
|
||||
.queryParam(OAuth2Constants.CODE_CHALLENGE_METHOD, OAuth2Constants.PKCE_METHOD_S256);
|
||||
|
||||
if (!queryParameters.isEmpty()) {
|
||||
String error = queryParameters.getFirst(OAuth2Constants.ERROR);
|
||||
if (error != null) {
|
||||
String state = queryParameters.getFirst(OAuth2Constants.STATE);
|
||||
if (state != null) {
|
||||
// Omit the "state" parameter to make sure that account console displays the error (it may not be shown due the keycloak.js, which will not be able to find the "callback data" in the browser callbackStorage)
|
||||
URI url = session.getContext().getUri(UrlType.FRONTEND)
|
||||
.getRequestUriBuilder()
|
||||
.replaceQueryParam(OAuth2Constants.STATE, null)
|
||||
.build();
|
||||
return Response.status(302).location(url).build();
|
||||
} else {
|
||||
try {
|
||||
return renderAccountConsole();
|
||||
} catch (IOException | FreeMarkerException e) {
|
||||
throw new ServerErrorException(Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
String scope = queryParameters.getFirst(OIDCLoginProtocol.SCOPE_PARAM);
|
||||
if (StringUtil.isNotBlank(scope)) {
|
||||
uriBuilder.queryParam(OIDCLoginProtocol.SCOPE_PARAM, scope);
|
||||
}
|
||||
}
|
||||
|
||||
URI url = uriBuilder.build();
|
||||
|
||||
return Response.status(302).location(url).build();
|
||||
}
|
||||
|
||||
private Map<String, String> supportedLocales(Properties messages) {
|
||||
return realm.getSupportedLocalesStream()
|
||||
.collect(Collectors.toMap(Function.identity(), l -> messages.getProperty("locale_" + l, l)));
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
package org.keycloak.testsuite.account;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
|
||||
public class AccountConsoleTest extends AbstractTestRealmKeycloakTest {
|
||||
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@Override
|
||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void redirectToLoginIfNotAuthenticated() {
|
||||
assertRedirectLocation(getAccount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScopesPresentInAuthorizationRequest() {
|
||||
String expectedScopes = "phone address";
|
||||
String redirectLocation = URLDecoder.decode(assertRedirectLocation(getAccount(expectedScopes)));
|
||||
Assert.assertTrue(redirectLocation.contains(expectedScopes));
|
||||
expectedScopes = "phone";
|
||||
redirectLocation = URLDecoder.decode(assertRedirectLocation(getAccount(expectedScopes)));
|
||||
Assert.assertTrue(redirectLocation.contains(expectedScopes));
|
||||
Assert.assertTrue(!redirectLocation.contains("address"));
|
||||
|
||||
// should render the account with the phone scope
|
||||
driver.navigate().to(redirectLocation);
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
|
||||
// should render the account with the address scope only
|
||||
expectedScopes = "address";
|
||||
redirectLocation = URLDecoder.decode(assertRedirectLocation(getAccount(expectedScopes)));
|
||||
driver.navigate().to(redirectLocation);
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
|
||||
// should render the account with the phone and address scopes
|
||||
expectedScopes = "phone address";
|
||||
redirectLocation = URLDecoder.decode(assertRedirectLocation(getAccount(expectedScopes)));
|
||||
driver.navigate().to(redirectLocation);
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
|
||||
// should keep previously requested scopes when not setting the scope parameter
|
||||
redirectLocation = URLDecoder.decode(assertRedirectLocation(getAccount()));
|
||||
driver.navigate().to(redirectLocation);
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
}
|
||||
|
||||
private CloseableHttpResponse getAccount() {
|
||||
return getAccount(null);
|
||||
}
|
||||
|
||||
private CloseableHttpResponse getAccount(String scope) {
|
||||
try {
|
||||
var uriBuilder = new URIBuilder(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/realms/test/account");
|
||||
|
||||
if (scope != null) {
|
||||
uriBuilder.setParameter(OIDCLoginProtocol.SCOPE_PARAM, scope);
|
||||
}
|
||||
|
||||
var request = new HttpGet(uriBuilder.build());
|
||||
|
||||
try (var client = HttpClientBuilder.create().disableRedirectHandling().build()) {
|
||||
return client.execute(request);
|
||||
}
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String assertRedirectLocation(CloseableHttpResponse Account) {
|
||||
try (var response = Account) {
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
Assert.assertEquals(302, statusCode);
|
||||
String expectedLoginUrlPart = "/realms/" + oauth.getRealm() + "/protocol/openid-connect/auth?client_id=" + Constants.ACCOUNT_CONSOLE_CLIENT_ID;
|
||||
String redirectLocation = response.getFirstHeader("Location").getValue();
|
||||
Assert.assertTrue(redirectLocation.contains(expectedLoginUrlPart));
|
||||
return redirectLocation;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,7 +187,7 @@ public class TermsAndConditionsTest extends AbstractChangeImportedUserPasswordsT
|
||||
attributes.get(TermsAndConditions.USER_ATTRIBUTE));
|
||||
}
|
||||
assertThat(DroneUtils.getCurrentDriver().getTitle(), equalTo("Account Management"));
|
||||
Assert.assertTrue(DroneUtils.getCurrentDriver().getPageSource().contains("You need to accept the Terms and Conditions to continue"));
|
||||
Assert.assertTrue(DroneUtils.getCurrentDriver().getPageSource().contains("Access denied"));
|
||||
Assert.assertFalse(DroneUtils.getCurrentDriver().getPageSource().contains("An unexpected error occurred"));
|
||||
|
||||
WebElement tryAgainButton = DroneUtils.getCurrentDriver().findElement(By.tagName("button"));
|
||||
|
||||
@ -345,7 +345,7 @@ public abstract class AbstractBaseBrokerTest extends AbstractKeycloakTest {
|
||||
|
||||
// Completely logout from realm and confirm logout if present
|
||||
protected void logoutFromRealm(String contextRoot, String realm, String initiatingIdp, String idTokenHint, String clientId, String redirectUri) {
|
||||
final String defaultRedirectUri = redirectUri != null ? redirectUri : getAccountUrl(contextRoot, realm);
|
||||
final String defaultRedirectUri = redirectUri != null ? redirectUri : oauth.loginForm().build();
|
||||
final String defaultClientId = (idTokenHint == null && clientId == null) ? "test-app" : clientId;
|
||||
|
||||
executeLogoutFromRealm(contextRoot, realm, initiatingIdp, idTokenHint, defaultClientId, defaultRedirectUri);
|
||||
|
||||
@ -73,6 +73,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
||||
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.utils.OIDCResponseMode;
|
||||
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
|
||||
import org.keycloak.representations.AuthorizationResponseToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
@ -115,7 +116,9 @@ import org.keycloak.testsuite.util.ClientPoliciesUtil.ClientProfileBuilder;
|
||||
import org.keycloak.testsuite.util.ClientPoliciesUtil.ClientProfilesBuilder;
|
||||
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
|
||||
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
|
||||
import org.keycloak.testsuite.util.oauth.OAuthClient;
|
||||
import org.keycloak.testsuite.util.oauth.ParResponse;
|
||||
import org.keycloak.testsuite.util.oauth.PkceGenerator;
|
||||
import org.keycloak.testsuite.util.RoleBuilder;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
@ -933,9 +936,16 @@ public class ClientPoliciesExecutorTest extends AbstractClientPoliciesTest {
|
||||
updatePolicies(json);
|
||||
|
||||
// Test account-console is loaded successfully when "secure-session-enforce" executor is present
|
||||
appPage.open();
|
||||
appPage.openAccount();
|
||||
oauth.client(Constants.ACCOUNT_CONSOLE_CLIENT_ID)
|
||||
.redirectUri(OAuthClient.AUTH_SERVER_ROOT + "/realms/test/account/")
|
||||
.responseMode(OIDCResponseMode.QUERY.value())
|
||||
.loginForm()
|
||||
.state(KeycloakModelUtils.generateId())
|
||||
.nonce(KeycloakModelUtils.generateId())
|
||||
.codeChallenge(PkceGenerator.s256())
|
||||
.open();
|
||||
loginPage.assertCurrent();
|
||||
Assert.assertEquals("Sign in to your account", loginPage.getTitleText());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
package org.keycloak.testsuite.forms;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.testsuite.AbstractChangeImportedUserPasswordsTest;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDriver;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.openqa.selenium.firefox.FirefoxDriver;
|
||||
|
||||
// real browser needed as it needs the account console and keycloak-js
|
||||
@IgnoreBrowserDriver(value={ChromeDriver.class, FirefoxDriver.class}, negate=true)
|
||||
public class AccountConsoleTest extends AbstractChangeImportedUserPasswordsTest {
|
||||
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@Test
|
||||
public void redirectToLoginIfNotAuthenticated() {
|
||||
driver.navigate().to(getAccount());
|
||||
WaitUtils.waitForPageToLoad();
|
||||
loginPage.assertCurrent();
|
||||
Assert.assertTrue(driver.getCurrentUrl().contains("client_id=" + Constants.ACCOUNT_CONSOLE_CLIENT_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScopesPresentInAuthorizationRequest() {
|
||||
String expectedScopes = "openid phone";
|
||||
String redirectLocation = getAccount(expectedScopes);
|
||||
|
||||
// should render the account with the phone scope
|
||||
driver.navigate().to(redirectLocation);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
|
||||
// should render the account with the address scope only
|
||||
expectedScopes = "openid address";
|
||||
redirectLocation = getAccount(expectedScopes);
|
||||
driver.navigate().to(redirectLocation);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
|
||||
// should render the account with the phone and address scopes
|
||||
expectedScopes = "openid phone address";
|
||||
redirectLocation = getAccount(expectedScopes);
|
||||
driver.navigate().to(redirectLocation);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
|
||||
// should keep previously requested scopes when not setting the scope parameter
|
||||
redirectLocation = getAccount();
|
||||
driver.navigate().to(redirectLocation);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
Assert.assertTrue(driver.getPageSource().contains("\"scope\": \"" + expectedScopes + "\""));
|
||||
}
|
||||
|
||||
private String getAccount() {
|
||||
return getAccount(null);
|
||||
}
|
||||
|
||||
private String getAccount(String scope) {
|
||||
try {
|
||||
var uriBuilder = new URIBuilder(suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/realms/test/account");
|
||||
|
||||
if (scope != null) {
|
||||
uriBuilder.setParameter(OIDCLoginProtocol.SCOPE_PARAM, scope);
|
||||
}
|
||||
|
||||
return uriBuilder.build().toString();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -424,7 +424,7 @@ public class OrganizationInvitationLinkTest extends AbstractOrganizationTest {
|
||||
}
|
||||
|
||||
private void acceptInvitation(OrganizationResource organization, UserRepresentation user) throws MessagingException, IOException {
|
||||
acceptInvitation(organization, user, "Sign in to");
|
||||
acceptInvitation(organization, user, "Account Management");
|
||||
}
|
||||
|
||||
private void acceptInvitation(OrganizationResource organization, UserRepresentation user, String pageTitle) throws MessagingException, IOException {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user