Account console backend should redirect to login on missing auth (#31469)

Adapted the login redirect logic from the old account console.

Fixes #31469

Signed-off-by: Thomas Darimont <thomas.darimont@googlemail.com>
This commit is contained in:
Thomas Darimont 2024-09-05 11:06:54 +02:00 committed by Pedro Igor
parent 4d5c692e3e
commit c400eff9b0
3 changed files with 72 additions and 3 deletions

View file

@ -161,7 +161,7 @@ public abstract class AbstractSecuredLocalService {
return oauth.redirect(session.getContext().getUri(), accountUri.toString());
}
static class OAuthRedirect extends AbstractOAuthClient {
public static class OAuthRedirect extends AbstractOAuthClient {
/**
* closes client

View file

@ -2,7 +2,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.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import org.jboss.resteasy.reactive.NoCache;
import org.keycloak.authentication.requiredactions.DeleteAccount;
import org.keycloak.common.Profile;
@ -17,12 +19,14 @@ 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;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resource.AccountResourceProvider;
import org.keycloak.services.resources.AbstractSecuredLocalService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.util.ResolveRelative;
import org.keycloak.services.util.ViteManifest;
@ -34,9 +38,11 @@ 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.util.HashMap;
import java.util.Locale;
import java.util.Map;
@ -93,8 +99,13 @@ public class AccountConsole implements AccountResourceProvider {
@GET
@NoCache
@Path("{any:.*}")
public Response getMainPage() throws IOException, FreeMarkerException {
@Path("{path:.*}")
public Response getMainPage(@PathParam("path") String path) throws IOException, FreeMarkerException {
if (auth == null) {
return redirectToLogin(path);
}
final var serverUriInfo = session.getContext().getUri(UrlType.FRONTEND);
final var serverBaseUri = serverUriInfo.getBaseUri();
// Strip any trailing slashes from the URL.
@ -195,6 +206,20 @@ 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);
}
URI targetUri = consoleUriBuilder.build(realm.getName());
var oauthRedirect = new AbstractSecuredLocalService.OAuthRedirect();
oauthRedirect.setAuthUrl(OIDCLoginProtocolService.authUrl(session.getContext().getUri()).build(realm.getName()).toString());
oauthRedirect.setClientId(client.getClientId());
oauthRedirect.setSecure(realm.getSslRequired().isRequired(session.getContext().getConnection()));
return oauthRedirect.redirect(session.getContext().getUri(), targetUri.toString());
}
private Map<String, String> supportedLocales(Properties messages) {
return realm.getSupportedLocalesStream()
.collect(Collectors.toMap(Function.identity(), l -> messages.getProperty("locale_" + l, l)));

View file

@ -0,0 +1,44 @@
package org.keycloak.testsuite.account;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.Test;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.util.OAuthClient;
public class AccountConsoleTest extends AbstractTestRealmKeycloakTest {
@Page
protected LoginPage loginPage;
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
}
@Test
public void redirectToLoginIfNotAuthenticated() throws Exception {
String accountUrl = oauth.getCurrentUri().toString().replace("/admin/master/console", "/realms/" + oauth.getRealm() + "/account");
HttpGet getAccount = new HttpGet(accountUrl);
int statusCode;
String redirectLocation;
try (var client = HttpClientBuilder.create().disableRedirectHandling().build()) {
try (var response = client.execute(getAccount)) {
statusCode = response.getStatusLine().getStatusCode();
redirectLocation = response.getFirstHeader("Location").getValue();
}
}
Assert.assertEquals(302, statusCode);
String expectedLoginUrlPart = "/realms/" + oauth.getRealm() + "/protocol/openid-connect/auth?client_id=account";
Assert.assertTrue(redirectLocation.contains(expectedLoginUrlPart));
}
}