diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java index 9c4b6b6c32..b76bae0e62 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebSession.java @@ -821,7 +821,10 @@ public class WebSession extends AbstractSessionPersistent implements SMSession, if (providerId == null) { clearAuthTokens(); } else { - removeAuthInfo(getAuthInfo(providerId)); + WebAuthInfo authInfo = getAuthInfo(providerId); + if (authInfo != null) { + removeAuthInfo(authInfo); + } } if (authTokens.isEmpty()) { resetUserState(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java index 10f9e129d4..5960919440 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java @@ -49,6 +49,7 @@ public class CBAppConfig extends BaseWebAppConfiguration { private boolean forwardProxy; private boolean publicCredentialsSaveEnabled; private boolean adminCredentialsSaveEnabled; + private boolean linkExternalCredentialsWithUser; private boolean redirectOnFederatedAuth; @@ -81,6 +82,7 @@ public class CBAppConfig extends BaseWebAppConfiguration { this.resourceQuotas = new LinkedHashMap<>(); this.enableReverseProxyAuth = false; this.forwardProxy = false; + this.linkExternalCredentialsWithUser = true; } public CBAppConfig(CBAppConfig src) { @@ -101,6 +103,7 @@ public class CBAppConfig extends BaseWebAppConfiguration { this.resourceQuotas = new LinkedHashMap<>(src.resourceQuotas); this.enableReverseProxyAuth = src.enableReverseProxyAuth; this.forwardProxy = src.forwardProxy; + this.linkExternalCredentialsWithUser = src.linkExternalCredentialsWithUser; } @@ -306,6 +309,11 @@ public class CBAppConfig extends BaseWebAppConfiguration { } } + public boolean isLinkExternalCredentialsWithUser() { + return linkExternalCredentialsWithUser; + } + + //////////////////////////////////////////// // Reverse proxy auth diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index d084be891d..5009abc2e0 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -599,30 +599,39 @@ public class CBApplication extends BaseWebApplication { } protected Map readConfiguration(File configFile) throws DBException { - try (Reader reader = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)) { - Map configProps = JSONUtils.parseMap(getGson(), reader); - patchConfigurationWithProperties(configProps); // patch original properties - readAdditionalConfiguration(configProps); - Map serverConfig = getServerConfigProps(configProps); + Map configProps = new LinkedHashMap<>(); + if (configFile.exists()) { + log.debug("Read configuration [" + configFile.getAbsolutePath() + "]"); + try (Reader reader = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)) { + configProps.putAll(JSONUtils.parseMap(getGson(), reader)); + patchConfigurationWithProperties(configProps); // patch original properties - String externalPropertiesFile = JSONUtils.getString(serverConfig, CBConstants.PARAM_EXTERNAL_PROPERTIES); - if (!CommonUtils.isEmpty(externalPropertiesFile)) { - Properties props = new Properties(); - try (InputStream is = Files.newInputStream(Path.of(externalPropertiesFile))) { - props.load(is); - } catch (IOException e) { - log.error("Error loading external properties from " + externalPropertiesFile, e); - } - for (String propName : props.stringPropertyNames()) { - this.externalProperties.put(propName, props.getProperty(propName)); - } + } catch (IOException e) { + throw new DBException("Error parsing server configuration", e); } - - patchConfigurationWithProperties(configProps); // patch again because properties can be changed - return configProps; - } catch (IOException e) { - throw new DBException("Error parsing server configuration", e); } + + readAdditionalConfiguration(configProps); + if (configProps.isEmpty()) { + return Map.of(); + } + + Map serverConfig = getServerConfigProps(configProps); + String externalPropertiesFile = JSONUtils.getString(serverConfig, CBConstants.PARAM_EXTERNAL_PROPERTIES); + if (!CommonUtils.isEmpty(externalPropertiesFile)) { + Properties props = new Properties(); + try (InputStream is = Files.newInputStream(Path.of(externalPropertiesFile))) { + props.load(is); + } catch (IOException e) { + log.error("Error loading external properties from " + externalPropertiesFile, e); + } + for (String propName : props.stringPropertyNames()) { + this.externalProperties.put(propName, props.getProperty(propName)); + } + } + + patchConfigurationWithProperties(configProps); // patch again because properties can be changed + return configProps; } private Gson getGson() { @@ -736,11 +745,7 @@ public class CBApplication extends BaseWebApplication { private Map readRuntimeConfigurationProperties() throws DBException { File runtimeConfigFile = getRuntimeAppConfigFile(); - if (runtimeConfigFile.exists()) { - log.debug("Runtime configuration [" + runtimeConfigFile.getAbsolutePath() + "]"); - return readConfiguration(runtimeConfigFile); - } - return Map.of(); + return readConfiguration(runtimeConfigFile); } protected void finishSecurityServiceConfiguration(@NotNull String adminName, @Nullable String adminPassword, @NotNull List authInfoList) throws DBException { @@ -824,6 +829,7 @@ public class CBApplication extends BaseWebApplication { appConfigProperties.put("adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled()); appConfigProperties.put("enableReverseProxyAuth", appConfig.isEnabledReverseProxyAuth()); appConfigProperties.put("forwardProxy", appConfig.isEnabledForwardProxy()); + appConfigProperties.put("linkExternalCredentialsWithUser", appConfig.isLinkExternalCredentialsWithUser()); appConfigProperties.put(CBConstants.PARAM_RESOURCE_MANAGER_ENABLED, appConfig.isResourceManagerEnabled()); Map resourceQuotas = appConfig.getResourceQuotas(); diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java index 66d3cd47ff..713a8e4f43 100644 --- a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java +++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/impl/WebServiceAuthImpl.java @@ -146,7 +146,9 @@ public class WebServiceAuthImpl implements DBWServiceAuth { userId = curUser.getUserId(); if (authProviderExternal != null) { // We may need to associate new credentials with active user - if (linkWithActiveUser) { + if (linkWithActiveUser && + CBApplication.getInstance().getAppConfiguration().isLinkExternalCredentialsWithUser() + ) { securityController.setUserCredentials(userId, authProvider.getId(), userCredentials); } } diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/CBEmbeddedSecurityController.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/CBEmbeddedSecurityController.java index a88a7850bf..052160baf1 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/CBEmbeddedSecurityController.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/internal/CBEmbeddedSecurityController.java @@ -351,7 +351,7 @@ public class CBEmbeddedSecurityController implements SMAdminController { /////////////////////////////////////////// // Credentials - private static SMAuthCredentialsProfile getCredentialProfileByParameters(SMAuthProviderDescriptor authProvider, Set keySet) { + private static SMAuthCredentialsProfile getCredentialProfileByParameters(AuthProviderDescriptor authProvider, Set keySet) { List credentialProfiles = authProvider.getCredentialProfiles(); if (credentialProfiles.size() > 1) { for (SMAuthCredentialsProfile profile : credentialProfiles) { @@ -953,6 +953,13 @@ public class CBEmbeddedSecurityController implements SMAdminController { return new SMAuthPermissions(userId, sessionId, permissions); } + @Override + public SMAuthProviderDescriptor[] getAvailableAuthProviders() { + return AuthProviderRegistry.getInstance().getAuthProviders().stream() + .filter(ap -> !ap.isTrusted()) + .map(AuthProviderDescriptor::createDescriptorBean).toArray(SMAuthProviderDescriptor[]::new); + } + @Override public void updateSession(@NotNull String sessionId, @Nullable String userId, @NotNull Map parameters) throws DBCException { try (Connection dbCon = database.openConnection()) {