From 34c0193ae2b4c132a75c9eebabbb038560439f66 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 2 Jun 2025 09:04:26 +0200 Subject: [PATCH 1/9] [NAE-2118] Implement OpenID Connector Auth for Admin node - change registry collection type in ProviderRegistry - add doc for ProviderRegistry.registerProvider --- .../engine/auth/provider/ProviderRegistry.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java index 7163fdaed32..75cab02d73c 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java @@ -4,19 +4,26 @@ import org.springframework.stereotype.Component; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; @Slf4j @Component public class ProviderRegistry { - protected final Map> configClasses = new HashMap<>(); + protected final Map> configClasses = new ConcurrentHashMap<>(); - protected final Map> providers = new HashMap<>(); + protected final Map> providers = new ConcurrentHashMap<>(); + /** + * Registers provider into this bean + * + * @param type type of the provider. It's used as a key in the map registry + * @param provider provider instance to register. It's used as a value in the map registry + * */ public void registerProvider(String type, AuthMethodProvider provider) { providers.put(type.toLowerCase(), provider); configClasses.put(type.toLowerCase(), provider.getConfigClass()); - log.info("Registered provider for type: " + type); + log.info("Registered provider for type: {}", type); } public Class getConfigClass(String type) { From 74c264ac9e4ea091816efea36b9e925c901da11f Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 4 Jun 2025 14:58:35 +0200 Subject: [PATCH 2/9] [NAE-2118] Implement OpenID Connector Auth for Admin node - fix logging in UserServiceImpl --- .../application/engine/auth/service/UserServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java index 21e1334c01c..c79dffeb183 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java @@ -129,9 +129,9 @@ public Optional findUserByUsername(String username, String realmId) { String collectionName = collectionNameProvider.getCollectionNameForRealm(realmId); Optional userOpt = userRepository.findByUsername(username, mongoTemplate, collectionName).map(user -> (IUser) user); if (userOpt.isPresent()) { - log.debug("User [{}] found in realm [{}]", username, collectionName); + log.debug("User [{}] found in realm [{}]", username, realmId); } else { - log.warn("User [{}] not found in realm [{}]", username, collectionName); + log.warn("User [{}] not found in realm [{}]", username, realmId); } return userOpt; } From 4fcc5205a2796ba208dbff10afe488a1b0e3bacd Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 10 Jun 2025 09:03:12 +0200 Subject: [PATCH 3/9] [NAE-2118] Implement OpenID Connector Auth for Admin node - optimize RealmServiceImpl.addProvider - remove unused AuthMethodProvider.createAuthMethod --- .../application/engine/auth/service/RealmServiceImpl.java | 7 ++----- .../engine/auth/provider/AuthMethodProvider.java | 3 --- .../application/engine/auth/service/RealmService.java | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java index 73ad92ac4c8..423f1a299f7 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java @@ -98,18 +98,15 @@ public Optional getRealmByName(String name) { } @Override - public > T addProvider(String realmId, AuthMethodConfig config) { + public Realm addProvider(String realmId, AuthMethodConfig config) { AuthMethodProvider provider = (AuthMethodProvider) providerRegistry.getProvider(config.getType()); if (provider == null) { throw new IllegalArgumentException("Provider type " + config.getType() + " not found"); } - AuthMethod authMethod = provider.createAuthMethod(config); Realm realm = getRealmById(realmId).orElseThrow(() -> new IllegalArgumentException("Realm with id " + realmId + " not found")); realm.addAuthMethod(config); - realmRepository.save(realm); - - return (T) authMethod; + return realmRepository.save(realm); } @Override diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java index d5a06866bec..9f73db553e3 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java @@ -1,14 +1,11 @@ package com.netgrif.application.engine.auth.provider; import com.netgrif.application.engine.objects.auth.provider.AuthMethod; -import com.netgrif.application.engine.objects.auth.provider.AuthMethodConfig; public interface AuthMethodProvider { String getProviderType(); - AuthMethod createAuthMethod(AuthMethodConfig authMethodConfig); - Class getConfigClass(); Class> getAuthMethodClass(); diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java index 876976662d6..813e8fef3bb 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java @@ -32,7 +32,7 @@ public interface RealmService { Optional getRealmByName(String name); - > T addProvider(String realmId, AuthMethodConfig config); + Realm addProvider(String realmId, AuthMethodConfig config); void removeProvider(String realmId, String providerId); From 6719ae65f5c5bf8ac313d12e01e3f1611466ed39 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 24 Jun 2025 12:48:50 +0200 Subject: [PATCH 4/9] [NAE-2127] Implement DelegatingContextFilter for Multi-Realm Support - add realm attribute in NetgrifAuthenticationToken --- .../engine/auth/domain/NetgrifAuthenticationToken.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java index 37569f17303..6761621cdbe 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.auth.domain; +import com.netgrif.application.engine.objects.auth.domain.Realm; import lombok.Getter; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -8,10 +9,18 @@ public class NetgrifAuthenticationToken extends UsernamePasswordAuthenticationToken { private final String realmId; + private final Realm realm; public NetgrifAuthenticationToken(Object principal, Object credentials, String realmId) { super(principal, credentials); this.realmId = realmId; + this.realm = null; + } + + public NetgrifAuthenticationToken(Object principal, Object credentials, Realm realm) { + super(principal, credentials); + this.realm = realm; + this.realmId = realm != null ? realm.getId() : null; } } From f7fd50807a90adef67916902720db903202cdd6d Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 26 Jun 2025 09:15:54 +0200 Subject: [PATCH 5/9] [NAE-2127] Implement DelegatingContextFilter for Multi-Realm Support - add AuthMethodConfig.order attribute --- .../engine/objects/auth/provider/AuthMethodConfig.java | 2 ++ .../engine/auth/provider/AuthMethodConfigDeserializer.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java index 321d1e5758c..4b9a9b3eb05 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java @@ -17,6 +17,8 @@ public class AuthMethodConfig implements Serializable { private boolean enabled; private T configuration; private String realmId; + /// lower number has bigger priority + private int order; public AuthMethodConfig() { if (this.id == null) { diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java index 6aa3f7d727d..b3ab12a34e4 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java @@ -54,6 +54,11 @@ public AuthMethodConfig deserialize(JsonParser jp, DeserializationContext ctx config.setEnabled(enabledNode.asBoolean()); } + JsonNode orderNode = node.get("order"); + if (orderNode != null) { + config.setOrder(orderNode.asInt()); + } + config.setType(type); config.setRealmId(realmID); From 5693b3d214960e4243c91785d93adb095f60de57 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 26 Jun 2025 14:53:30 +0200 Subject: [PATCH 6/9] [NAE-2127] Implement DelegatingContextFilter for Multi-Realm Support - implement RealmServiceImpl.updateConfigInRealm --- .../engine/auth/service/RealmServiceImpl.java | 27 +++++++++++++++++++ .../AuthMethodConfigDeserializer.java | 5 ++++ .../engine/auth/service/RealmService.java | 2 ++ 3 files changed, 34 insertions(+) diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java index 423f1a299f7..0696b496b97 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java @@ -136,6 +136,33 @@ public Realm updateRealm(String realmId, Realm update) { return realmRepository.save(realm); } + @Override + public AuthMethodConfig updateConfigInRealm(String realmId, AuthMethodConfig config) { + if (config == null) { + throw new IllegalArgumentException("Authentication config not provided"); + } + + Realm realm = getRealmById(realmId).orElseThrow(() -> new IllegalArgumentException("Realm with id " + realmId + " not found")); + Optional> configToUpdateOpt = realm.getAuthMethods().stream() + .filter(realmConfig -> realmConfig.getId().equals(config.getId())) + .findFirst(); + + if (configToUpdateOpt.isEmpty()) { + throw new IllegalArgumentException("Authentication config with id " + config.getId() + " not found in realm " + realmId); + } + + AuthMethodConfig configToUpdate = configToUpdateOpt.get(); + configToUpdate.setName(config.getName()); + configToUpdate.setDescription(config.getDescription()); + configToUpdate.setEnabled(config.isEnabled()); + configToUpdate.setOrder(config.getOrder()); + configToUpdate.setConfiguration(config.getConfiguration()); + + realmRepository.save(realm); + + return configToUpdate; + } + @Override public void deleteRealm(String realmId) { if (!realmRepository.existsById(realmId)) { diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java index b3ab12a34e4..b137422890c 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java @@ -54,6 +54,11 @@ public AuthMethodConfig deserialize(JsonParser jp, DeserializationContext ctx config.setEnabled(enabledNode.asBoolean()); } + JsonNode descNode = node.get("description"); + if (descNode != null) { + config.setDescription(descNode.asText()); + } + JsonNode orderNode = node.get("order"); if (orderNode != null) { config.setOrder(orderNode.asInt()); diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java index 813e8fef3bb..997f605c49b 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java @@ -38,6 +38,8 @@ public interface RealmService { Realm updateRealm(String realmId, Realm update); + AuthMethodConfig updateConfigInRealm(String realmId, AuthMethodConfig config); + void deleteRealm(String realmId); void addUserToRealm(String realmId, String userId); From 8bfeecb627958f39d33255bb61bd3c10ab20478f Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 27 Jun 2025 12:43:14 +0200 Subject: [PATCH 7/9] [NAE-2127] Implement DelegatingContextFilter for Multi-Realm Support - update Realm attributes --- .../startup/runner/DefaultRealmRunner.java | 16 +++++++++------- .../engine/objects/auth/domain/Realm.java | 6 ++++++ .../application/engine/auth/realm/RealmDto.java | 4 +++- .../engine/auth/realm/request/RealmSearch.java | 4 +++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java index 283ac81eec2..f8273ec91a8 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java @@ -21,13 +21,15 @@ public class DefaultRealmRunner implements ApplicationEngineStartupRunner { @Override public void run(ApplicationArguments args) throws Exception { - if (realmService.getDefaultRealm().isEmpty()) { - Realm createRequest = new Realm(); - createRequest.setName("Default"); - createRequest.setDescription("Default realm"); - createRequest.setAdminRealm(true); - createRequest.setDefaultRealm(true); - realmService.createRealm(createRequest); + if (realmService.getDefaultRealm().isPresent()) { + return; } + + Realm createRequest = new Realm(); + createRequest.setName("Default"); + createRequest.setDescription("Default realm"); + createRequest.setAdminRealm(true); + createRequest.setDefaultRealm(true); + realmService.createRealm(createRequest); } } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java index 85a72f67353..bf52878ecb6 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java @@ -2,6 +2,7 @@ import com.netgrif.application.engine.objects.auth.provider.AuthMethodConfig; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.Data; import java.time.Duration; @@ -46,6 +47,11 @@ public class Realm implements Serializable { private Duration publicSessionTimeout = Duration.ofHours(2); + private boolean enableLimitSessions = false; + + @Positive + private int maxSessionsAllowed = 1; + public Realm() { } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java index 1f7fe439ca6..9ba40e134c6 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java @@ -7,5 +7,7 @@ public record RealmDto(String id, Boolean adminRealm, Boolean enableBlocking, Integer maxFailedAttempts, - Integer blockDurationMinutes) { + Integer blockDurationMinutes, + Boolean enableLimitSessions, + Integer maxSessionsAllowed) { } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java index f548f9c0021..67d3f6f3998 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java @@ -7,5 +7,7 @@ public record RealmSearch(String id, Boolean adminRealm, Boolean enableBlocking, Integer maxFailedAttempts, - Integer blockDurationMinutes) { + Integer blockDurationMinutes, + Boolean enableLimitSessions, + Integer maxSessionsAllowed) { } From 2a7be1e768491a0246ac427591ea194933d51627 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 4 Aug 2025 10:47:43 +0200 Subject: [PATCH 8/9] [NAE-2127] Implement DelegatingContextFilter for Multi-Realm Support - fix RealmServiceImpl after merge - fix NetgrifAuthenticationToken after merge --- .../application/engine/auth/service/RealmServiceImpl.java | 2 +- .../engine/auth/domain/NetgrifAuthenticationToken.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java index 742a3f0944d..191a77c5355 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java @@ -192,7 +192,7 @@ public AuthMethodConfig updateConfigInRealm(String realmId, AuthMethodConfig< configToUpdate.setOrder(config.getOrder()); configToUpdate.setConfiguration(config.getConfiguration()); - realmRepository.save(realm); + realmRepository.save((com.netgrif.application.engine.adapter.spring.auth.domain.Realm) realm); return configToUpdate; } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java index 6761621cdbe..b1c17d21013 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java @@ -8,19 +8,19 @@ @Getter public class NetgrifAuthenticationToken extends UsernamePasswordAuthenticationToken { - private final String realmId; + private final String realmName; private final Realm realm; - public NetgrifAuthenticationToken(Object principal, Object credentials, String realmId) { + public NetgrifAuthenticationToken(Object principal, Object credentials, String realmName) { super(principal, credentials); - this.realmId = realmId; + this.realmName = realmName; this.realm = null; } public NetgrifAuthenticationToken(Object principal, Object credentials, Realm realm) { super(principal, credentials); this.realm = realm; - this.realmId = realm != null ? realm.getId() : null; + this.realmName = realm != null ? realm.getName() : null; } } From c3239e470f138efa64c3941af81c311caab635d8 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 4 Aug 2025 16:15:27 +0200 Subject: [PATCH 9/9] [NAE-2127] Implement DelegatingContextFilter for Multi-Realm Support - remove redundant setter call --- .../application/engine/startup/runner/DefaultRealmRunner.java | 1 - 1 file changed, 1 deletion(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java index ea295e69dac..e116d4dc74d 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java @@ -26,7 +26,6 @@ public void run(ApplicationArguments args) throws Exception { } Realm createRequest = new com.netgrif.application.engine.adapter.spring.auth.domain.Realm("Default"); - createRequest.setName("Default"); createRequest.setDescription("Default realm"); createRequest.setAdminRealm(true); createRequest.setDefaultRealm(true);