KEYCLOAK-17387: 403 response on localization endpoint for cross realm users

- add ForbiddenPage class for the assertion at the selenium test
- add assertion to selenium test
- GET requests for localization texts require at least one role for the realm
- Make GET requests for localization texts public, to display the admin UI correctly, even if the role view-realm is missing
This commit is contained in:
Christoph Leistert 2021-05-03 18:29:11 +02:00 committed by GitHub
parent 96501760e0
commit 61bdc92ad9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 3 deletions

View file

@ -24,6 +24,7 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import java.io.IOException;
@ -46,6 +47,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.util.JsonSerialization;
public class RealmLocalizationResource {
@ -130,7 +132,9 @@ public class RealmLocalizationResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Stream<String> getRealmLocalizationLocales() {
this.auth.realm().requireViewRealm();
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) {
throw new ForbiddenException();
}
return realm.getRealmLocalizationTexts().keySet().stream().sorted();
}
@ -139,7 +143,10 @@ public class RealmLocalizationResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> getRealmLocalizationTexts(@PathParam("locale") String locale) {
this.auth.realm().requireViewRealm();
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) {
throw new ForbiddenException();
}
return realm.getRealmLocalizationTextsByLocale(locale);
}
@ -147,7 +154,10 @@ public class RealmLocalizationResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getRealmLocalizationText(@PathParam("locale") String locale, @PathParam("key") String key) {
this.auth.realm().requireViewRealm();
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) {
throw new ForbiddenException();
}
String text = session.realms().getLocalizationTextsById(realm, locale, key);
if (text != null) {
return text;

View file

@ -0,0 +1,32 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.console.page;
import javax.ws.rs.core.UriBuilder;
public class ForbiddenPage extends AdminConsole {
@Override
public UriBuilder createUriBuilder() {
return super.createUriBuilder().path("/");
}
@Override
public String getUriFragment() {
return "/forbidden";
}
}

View file

@ -17,13 +17,27 @@
*/
package org.keycloak.testsuite.console;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.Test;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.console.page.ForbiddenPage;
import org.openqa.selenium.JavascriptExecutor;
import static org.junit.Assert.assertEquals;
import static org.keycloak.testsuite.admin.ApiUtil.assignClientRoles;
import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
public class BasicConsoleTest extends AbstractConsoleTest {
@Page
ForbiddenPage forbiddenPage;
private final static String TEST_USER_VIEW_USERS_NAME = "BasicConsoleTest-view-users";
private final static String DEFAULT_PASSWORD = "Test12345!";
@Test
// KEYCLOAK-4717
public void testPostWindowMessage() throws InterruptedException {
@ -37,4 +51,30 @@ public class BasicConsoleTest extends AbstractConsoleTest {
assertEquals("Expected window not to have reloaded", "check", result);
}
@Test
// KEYCLOAK-17387
public void testUserWithViewUsersRoleCanOpenConsole() {
UserRepresentation userRepresentation = createTestUserWithViewUsersRole();
try {
loginToTestRealmConsoleAs(userRepresentation);
assertCurrentUrlDoesntStartWith(forbiddenPage);
} finally {
ApiUtil.removeUserByUsername(testRealmResource(), TEST_USER_VIEW_USERS_NAME);
}
}
private UserRepresentation createTestUserWithViewUsersRole() {
ApiUtil.removeUserByUsername(testRealmResource(), TEST_USER_VIEW_USERS_NAME);
log.debug("creating test user with view-users role");
UserRepresentation userRepresentation = createUserRepresentation(TEST_USER_VIEW_USERS_NAME, null, null, null, true, DEFAULT_PASSWORD);
String id = createUserAndResetPasswordWithAdminClient(testRealmResource(), userRepresentation, DEFAULT_PASSWORD);
userRepresentation.setId(id);
assignClientRoles(testRealmResource(), id, "realm-management", "view-users");
return userRepresentation;
}
}