Skip to content

Commit

Permalink
Fixed #2072: Users are always anonymous when combining keycloak, fine…
Browse files Browse the repository at this point in the history
…grained auth & anonymous access
  • Loading branch information
hylkevds committed Dec 5, 2024
1 parent e1ee0c2 commit 1738145
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**New Features**

**Internal changes & Bugfixes**
* Fixed #2072: Users are always anonymous when combining keycloak, finegrained auth and anonymous access.


## Release version 2.5.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
HttpServletResponse httpResponse = (HttpServletResponse) response;

Role requiredRole = findRequiredRoleForRequest(httpRequest);
if (requiredRole == Role.NONE) {
if (!authenticateOnly && requiredRole == Role.NONE) {
chain.doFilter(request, response);
return;
}
Expand Down Expand Up @@ -236,6 +236,12 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
}
}
}

if (requiredRole == Role.NONE) {
chain.doFilter(request, response);
return;
}

AuthChallenge challenge = authenticator.getChallenge();
if (challenge != null) {
LOGGER.debug("Challenge.");
Expand All @@ -244,7 +250,6 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
return;
} catch (IllegalStateException ex) {
LOGGER.debug("Challenge failed.", ex);
// Failed the challenge.
}
}
LOGGER.debug("User is not allowed.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import de.fraunhofer.iosb.ilt.statests.f01auth.BasicAuthTests11;
import de.fraunhofer.iosb.ilt.statests.f01auth.FineGrainedAuthTestsBasic11;
import de.fraunhofer.iosb.ilt.statests.f01auth.FineGrainedAuthTestsKeycloak11;
import de.fraunhofer.iosb.ilt.statests.f01auth.FineGrainedAuthTestsKeycloakAnon11;
import de.fraunhofer.iosb.ilt.statests.f01auth.KeyCloakAnonReadTests10;
import de.fraunhofer.iosb.ilt.statests.f01auth.KeyCloakAnonReadTests11;
import de.fraunhofer.iosb.ilt.statests.f01auth.KeyCloakTests10;
Expand Down Expand Up @@ -172,22 +173,23 @@
Capability7Tests11.class,
MqttCoreTests.class,
MqttExtraTests.class,
CustomLinksTests10.class,
CustomLinksTests11.class,
MetadataTests10.class,
MetadataTests11.class,
BasicAuthTests10.class,
BasicAuthTests11.class,
BasicAuthAnonReadTests10.class,
BasicAuthAnonReadTests11.class,
BasicAuthCryptPwTests10.class,
BasicAuthCryptPwTests11.class,
FineGrainedAuthTestsBasic11.class,
FineGrainedAuthTestsKeycloak11.class,
KeyCloakTests10.class,
KeyCloakTests11.class,
KeyCloakAnonReadTests10.class,
KeyCloakAnonReadTests11.class,
CustomLinksTests10.class,
CustomLinksTests11.class,
MetadataTests10.class,
MetadataTests11.class,
FineGrainedAuthTestsBasic11.class,
FineGrainedAuthTestsKeycloak11.class,
FineGrainedAuthTestsKeycloakAnon11.class,
TestSuite.SuiteFinaliser.class
})
@Suite
Expand Down Expand Up @@ -452,7 +454,7 @@ private void startMqttServer(int key, Map<String, String> parameters) throws IOE

String dbDriver = parameters.getOrDefault(PREFIX_PERSISTENCE + TAG_DB_DRIVER, "org.postgresql.Driver");
properties.put(PREFIX_PERSISTENCE + PersistenceSettings.TAG_IMPLEMENTATION_CLASS, VAL_PERSISTENCE_MANAGER);
properties.put(PREFIX_PERSISTENCE + TAG_AUTO_UPDATE_DATABASE, "true");
properties.put(PREFIX_PERSISTENCE + TAG_AUTO_UPDATE_DATABASE, "false");
properties.put(PREFIX_PERSISTENCE + TAG_DB_DRIVER, dbDriver);
properties.put(PREFIX_PERSISTENCE + TAG_DB_URL, createDbUrl(dbDriver, parameters.get(KEY_DB_NAME)));
properties.put(PREFIX_PERSISTENCE + TAG_DB_USERNAME, VAL_PG_USER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ private static String resourceUrl(String path, String name) {
private static MqttHelper2 mqttHelperAdminProject1;
private static MqttHelper2 mqttHelperAdminProject2;

private final boolean anonymousReadAllowed;
private final AuthTestHelper ath;

protected static void addCommonProperties(Map<String, String> properties) {
Expand All @@ -175,8 +176,9 @@ protected static void addCommonProperties(Map<String, String> properties) {
properties.put("auth.mqtt.topicAllowList", "^/[a-zA-Z0-9_-]+\\((('[^']+')|([0-9]+))\\)/[a-zA-Z0-9_-]+$");
}

public FineGrainedAuthTests(ServerVersion version, Map<String, String> properties) {
public FineGrainedAuthTests(ServerVersion version, Map<String, String> properties, boolean anonymousReadAllowed) {
super(version, properties);
this.anonymousReadAllowed = anonymousReadAllowed;
ath = new AuthTestHelper(serverSettings);
}

Expand Down Expand Up @@ -325,7 +327,11 @@ void test_02a_ReadProjects() {
testFilterResults(ADMIN, serviceAdmin, mdlUsers.etProject, "", PROJECTS);
testFilterResults(WRITE, serviceWrite, mdlUsers.etProject, "", PROJECTS);
testFilterResults(READ, serviceRead, mdlUsers.etProject, "", PROJECTS);
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etProject, "", H401);
if (anonymousReadAllowed) {
testFilterResults(ANONYMOUS, serviceAnon, mdlUsers.etProject, "", PROJECTS);
} else {
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etProject, "", H401);
}
testFilterResults(ADMIN_P1, serviceAdminProject1, mdlUsers.etProject, "", PROJECTS);
testFilterResults(ADMIN_P2, serviceAdminProject2, mdlUsers.etProject, "", PROJECTS);
testFilterResults(OBS_CREATE_P1, serviceObsCreaterProject1, mdlUsers.etProject, "", PROJECTS);
Expand Down Expand Up @@ -369,7 +375,7 @@ void test_03_ReadUserProjectRole() {
testFilterResults(serviceAdmin, mdlUsers.etUserProjectRole, "", USER_PROJECT_ROLES);
filterForException(WRITE, serviceWrite, mdlUsers.etUserProjectRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(READ, serviceRead, mdlUsers.etUserProjectRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etUserProjectRole, "", HTTP_CODE_401_UNAUTHORIZED, H403);
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etUserProjectRole, "", anonymousReadAllowed ? new int[]{H404} : new int[]{H401, H403});
filterForException(ADMIN_P1, serviceAdminProject1, mdlUsers.etUserProjectRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(ADMIN_P2, serviceAdminProject2, mdlUsers.etUserProjectRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(OBS_CREATE_P1, serviceObsCreaterProject1, mdlUsers.etUserProjectRole, "", HTTP_CODE_404_NOT_FOUND);
Expand All @@ -382,7 +388,11 @@ void test_04a_ReadUser() {
testFilterResults(serviceAdmin, mdlUsers.etUser, "", USERS);
testFilterResults(serviceWrite, mdlUsers.etUser, "", Utils.getFromList(USERS, 6));
testFilterResults(serviceRead, mdlUsers.etUser, "", Utils.getFromList(USERS, 5));
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etUser, "", H401, H403);
if (anonymousReadAllowed) {
testFilterResults(ANONYMOUS, serviceAnon, mdlUsers.etUser, "", Collections.emptyList());
} else {
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etUser, "", H401, H403);
}
testFilterResults(serviceAdminProject1, mdlUsers.etUser, "", USERS);
testFilterResults(serviceAdminProject2, mdlUsers.etUser, "", USERS);
testFilterResults(serviceObsCreaterProject1, mdlUsers.etUser, "", Utils.getFromList(USERS, 3));
Expand All @@ -408,7 +418,7 @@ void test_05_ReadRole() {
testFilterResults(ADMIN, serviceAdmin, mdlUsers.etRole, "", ROLES);
filterForException(WRITE, serviceWrite, mdlUsers.etRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(READ, serviceRead, mdlUsers.etRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etRole, "", H401, H403);
filterForException(ANONYMOUS, serviceAnon, mdlUsers.etRole, "", anonymousReadAllowed ? new int[]{H404} : new int[]{H401, H403});
filterForException(ADMIN_P1, serviceAdminProject1, mdlUsers.etRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(ADMIN_P2, serviceAdminProject2, mdlUsers.etRole, "", HTTP_CODE_404_NOT_FOUND);
filterForException(OBS_CREATE_P1, serviceObsCreaterProject1, mdlUsers.etRole, "", HTTP_CODE_404_NOT_FOUND);
Expand Down Expand Up @@ -489,7 +499,11 @@ void test_08a_ObservationRead() {
testFilterResults(ADMIN, serviceAdmin, mdlSensing.etObservation, "", OBSERVATIONS);
testFilterResults(WRITE, serviceWrite, mdlSensing.etObservation, "", OBSERVATIONS);
testFilterResults(READ, serviceRead, mdlSensing.etObservation, "", OBSERVATIONS);
filterForException(ANONYMOUS, serviceAnon, mdlSensing.etObservation, "", HTTP_CODE_401_UNAUTHORIZED);
if (anonymousReadAllowed) {
testFilterResults(ANONYMOUS, serviceAnon, mdlSensing.etObservation, "", Collections.emptyList());
} else {
filterForException(ANONYMOUS, serviceAnon, mdlSensing.etObservation, "", HTTP_CODE_401_UNAUTHORIZED);
}
testFilterResults(ADMIN_P1, serviceAdminProject1, mdlSensing.etObservation, "", Utils.getFromList(OBSERVATIONS, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23));
testFilterResults(ADMIN_P2, serviceAdminProject2, mdlSensing.etObservation, "", Utils.getFromList(OBSERVATIONS, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23));
testFilterResults(OBS_CREATE_P1, serviceObsCreaterProject1, mdlSensing.etObservation, "", Utils.getFromList(OBSERVATIONS, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23));
Expand All @@ -503,7 +517,11 @@ void test_08b_ObservationReadFilter() {
testFilterResults(ADMIN, serviceAdmin, mdlSensing.etObservedProperty, filter, Utils.getFromList(O_PROPS, 0));
testFilterResults(WRITE, serviceWrite, mdlSensing.etObservedProperty, filter, Utils.getFromList(O_PROPS, 0));
testFilterResults(READ, serviceRead, mdlSensing.etObservedProperty, filter, Utils.getFromList(O_PROPS, 0));
filterForException(ANONYMOUS, serviceAnon, mdlSensing.etObservedProperty, filter, H401);
if (anonymousReadAllowed) {
testFilterResults(ANONYMOUS, serviceAnon, mdlSensing.etObservedProperty, filter, Collections.emptyList());
} else {
filterForException(ANONYMOUS, serviceAnon, mdlSensing.etObservedProperty, filter, H401);
}
testFilterResults(ADMIN_P1, serviceAdminProject1, mdlSensing.etObservedProperty, filter, Utils.getFromList(O_PROPS, 0));
testFilterResults(ADMIN_P2, serviceAdminProject2, mdlSensing.etObservedProperty, filter, Collections.emptyList());
testFilterResults(OBS_CREATE_P1, serviceObsCreaterProject1, mdlSensing.etObservedProperty, filter, Utils.getFromList(O_PROPS, 0));
Expand All @@ -518,7 +536,7 @@ void test_08c_DatastreamFromObservationRead() throws ServiceFailureException, UR
fetchForCode(ADMIN, serviceAdmin, link, H200);
fetchForCode(WRITE, serviceWrite, link, H200);
fetchForCode(READ, serviceRead, link, H200);
fetchForCode(ANONYMOUS, serviceAnon, link, H401);
fetchForCode(ANONYMOUS, serviceAnon, link, anonymousReadAllowed ? H404 : H401);
fetchForCode(ADMIN_P1, serviceAdminProject1, link, H200);
fetchForCode(ADMIN_P2, serviceAdminProject2, link, H404);
fetchForCode(OBS_CREATE_P1, serviceObsCreaterProject1, link, H200);
Expand All @@ -533,7 +551,7 @@ void test_08d_ObservationsFromDatastreamRead() throws ServiceFailureException, U
fetchForCode(ADMIN, serviceAdmin, link, H200);
fetchForCode(WRITE, serviceWrite, link, H200);
fetchForCode(READ, serviceRead, link, H200);
fetchForCode(ANONYMOUS, serviceAnon, link, H401);
fetchForCode(ANONYMOUS, serviceAnon, link, anonymousReadAllowed ? H404 : H401);
fetchForCode(ADMIN_P1, serviceAdminProject1, link, H200);
fetchForCode(ADMIN_P2, serviceAdminProject2, link, H404);
fetchForCode(OBS_CREATE_P1, serviceObsCreaterProject1, link, H200);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class FineGrainedAuthTestsBasic extends FineGrainedAuthTests {
}

public FineGrainedAuthTestsBasic(ServerVersion version) {
super(version, SERVER_PROPERTIES);
super(version, SERVER_PROPERTIES, false);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class FineGrainedAuthTestsKeycloak extends FineGrainedAuthTests {

private static final Logger LOGGER = LoggerFactory.getLogger(FineGrainedAuthTestsKeycloak.class.getName());
private static final Map<String, String> SERVER_PROPERTIES = new LinkedHashMap<>();
private static final Map<String, String> SERVER_PROPERTIES_ANON = new LinkedHashMap<>();

static {
FineGrainedAuthTests.addCommonProperties(SERVER_PROPERTIES);
Expand All @@ -68,10 +69,18 @@ public class FineGrainedAuthTestsKeycloak extends FineGrainedAuthTests {
SERVER_PROPERTIES.put("auth.authenticateOnly", "true");
SERVER_PROPERTIES.put("auth.registerUserLocally", "true");
SERVER_PROPERTIES.put("auth.userRoleDecoderClass", ProjectRoleDecoder.class.getName());

final String dbNameAnon = "fineGrainedAuthKeycloakAnon";
SERVER_PROPERTIES_ANON.putAll(SERVER_PROPERTIES);
SERVER_PROPERTIES_ANON.put("auth.db.url", TestSuite.createDbUrl(dbDriver, dbNameAnon));
SERVER_PROPERTIES_ANON.put(KEY_DB_NAME, dbNameAnon);
SERVER_PROPERTIES_ANON.put("auth_allowAnonymousRead", "true");
}

public FineGrainedAuthTestsKeycloak(ServerVersion version) {
super(version, SERVER_PROPERTIES);
public FineGrainedAuthTestsKeycloak(ServerVersion version, boolean anonymousReadAllowed) {
super(version,
anonymousReadAllowed ? SERVER_PROPERTIES_ANON : SERVER_PROPERTIES,
anonymousReadAllowed);
}

@BeforeEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
public class FineGrainedAuthTestsKeycloak11 extends FineGrainedAuthTestsKeycloak {

public FineGrainedAuthTestsKeycloak11() {
super(ServerVersion.v_1_1);
super(ServerVersion.v_1_1, false);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2024 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131
* Karlsruhe, Germany.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.fraunhofer.iosb.ilt.statests.f01auth;

import de.fraunhofer.iosb.ilt.statests.ServerVersion;

/**
* Runs the FineGrained Auth Tests using Keycloak Auth on the v1.1 API.
*/
public class FineGrainedAuthTestsKeycloakAnon11 extends FineGrainedAuthTestsKeycloak {

public FineGrainedAuthTestsKeycloakAnon11() {
super(ServerVersion.v_1_1, true);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import org.slf4j.LoggerFactory;

/**
* Decodes Roles for the Projects plugsin.
* Decodes Roles for the Projects plugin.
*/
public class ProjectRoleDecoder implements UserRoleDecoder, ConfigDefaults {

Expand Down

0 comments on commit 1738145

Please sign in to comment.