Skip to content

Commit

Permalink
Apply fine-grained authorisation to MQTT-Create
Browse files Browse the repository at this point in the history
  • Loading branch information
hylkevds committed Oct 10, 2024
1 parent ba5769f commit f368e90
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ FROST-Server version 2.5 and higher requires Java 21. This is because some libra
* Improved update efficiency by not doing a separate select to get the full updated entity. (georghas)
* Fixed #2030: NPE when using anonymous access when authentication is enabled on MQTT.
* Added conformance class to index document for Projects plugin.
* Apply fine-grained authorisation to MQTT-Create.


## Release version 2.4.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package de.fraunhofer.iosb.ilt.frostserver.auth.basic;

import static de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings.TAG_AUTHENTICATE_ONLY;
import static de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings.TAG_AUTH_ROLE_ADMIN;
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_PASSWORD_LENGTH;
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_USERNAME_LENGTH;
Expand All @@ -39,12 +40,16 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A FROST Auth implementation for Basic Authentication.
*/
public class BasicAuthProvider implements AuthProvider, LiquibaseUser, ConfigDefaults {

private static final Logger LOGGER = LoggerFactory.getLogger(BasicAuthProvider.class.getName());

public static final String LIQUIBASE_CHANGELOG_FILENAME = "liquibase/basicAuthTables.xml";

@DefaultValueBoolean(false)
Expand Down Expand Up @@ -81,6 +86,7 @@ public class BasicAuthProvider implements AuthProvider, LiquibaseUser, ConfigDef

private CoreSettings coreSettings;
private String roleAdmin;
private boolean authenticateOnly;
private int maxClientsPerUser;
private int maxPassLength = MAX_PASSWORD_LENGTH;
private int maxNameLength = MAX_USERNAME_LENGTH;
Expand All @@ -93,6 +99,7 @@ public InitResult init(CoreSettings coreSettings) {
this.coreSettings = coreSettings;
DatabaseHandler.init(coreSettings);
final Settings authSettings = coreSettings.getAuthSettings();
authenticateOnly = authSettings.getBoolean(TAG_AUTHENTICATE_ONLY, CoreSettings.class);
roleAdmin = authSettings.get(TAG_AUTH_ROLE_ADMIN, CoreSettings.class);
maxClientsPerUser = authSettings.getInt(TAG_MAX_CLIENTS_PER_USER, getClass());
maxPassLength = authSettings.getInt(TAG_MAX_PASSWORD_LENGTH, getClass());
Expand Down Expand Up @@ -129,6 +136,10 @@ public boolean isValidUser(String clientId, String userName, String password) {

@Override
public boolean userHasRole(String clientId, String userName, String roleName) {
if (authenticateOnly && !roleName.equalsIgnoreCase(roleAdmin)) {
LOGGER.trace("Only authenticating, not checking of User {} has role {}", userName, roleName);
return true;
}
return DatabaseHandler.getInstance(coreSettings)
.userHasRole(userName, roleName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package de.fraunhofer.iosb.ilt.frostserver.auth.keycloak;

import static de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings.TAG_AUTHENTICATE_ONLY;
import static de.fraunhofer.iosb.ilt.frostserver.settings.CoreSettings.TAG_AUTH_ROLE_ADMIN;
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_PASSWORD_LENGTH;
import static de.fraunhofer.iosb.ilt.frostserver.util.user.UserData.MAX_USERNAME_LENGTH;
Expand Down Expand Up @@ -126,6 +127,7 @@ public class KeycloakAuthProvider implements AuthProvider, LiquibaseUser, Config
private String roleAdmin;
private int maxClientsPerUser;
private boolean registerUserLocally;
private boolean authenticateOnly;
private DatabaseHandler databaseHandler;
private int maxPassLength = MAX_PASSWORD_LENGTH;
private int maxNameLength = MAX_USERNAME_LENGTH;
Expand All @@ -150,6 +152,7 @@ public InitResult init(CoreSettings coreSettings) {
maxPassLength = authSettings.getInt(TAG_MAX_PASSWORD_LENGTH, getClass());
maxNameLength = authSettings.getInt(TAG_MAX_USERNAME_LENGTH, getClass());
registerUserLocally = authSettings.getBoolean(TAG_REGISTER_USER_LOCALLY, KeycloakAuthProvider.class);
authenticateOnly = authSettings.getBoolean(TAG_AUTHENTICATE_ONLY, CoreSettings.class);
if (registerUserLocally) {
DatabaseHandler.init(coreSettings);
databaseHandler = DatabaseHandler.getInstance(coreSettings);
Expand Down Expand Up @@ -234,6 +237,10 @@ public boolean userHasRole(String clientId, String userName, String roleName) {
return false;
}
client.setLastSeen(Instant.now());
if (authenticateOnly && !roleName.equalsIgnoreCase(roleAdmin)) {
LOGGER.trace("Only authenticating, not checking of User {} has role {}", userName, roleName);
return true;
}
boolean hasRole = client.getSubject().getPrincipals().stream().anyMatch(p -> p.getName().equalsIgnoreCase(roleName));
LOGGER.trace("User {} has role {}: {}", userName, roleName, hasRole);
return hasRole;
Expand Down

0 comments on commit f368e90

Please sign in to comment.