From 4cdb3ac30b1cf96244674cfedc94f8ff0685ee4e Mon Sep 17 00:00:00 2001 From: DenisSinelnikov <142215442+DenisSinelnikov@users.noreply.github.com> Date: Tue, 23 Jan 2024 20:15:34 +0400 Subject: [PATCH] Cb 4389 convert reverse proxy (#2300) * CB-4389. Converted reverse proxy to identity provider * CB-4039 build logout redirect link on backend side * CB-4039 fix return value * CB-4389. Added auto configuration for Reverse proxy if its enabled on ce, fixed typo, rename plugin parameters * CB-4389. Added check for already exist configuration * CB-4389. Refactor after review * CB-4039 adds logout with context for Okta Identity Provider * CB-4039 backward compatibility fix * CB-4039 add since annotation * CB-4039 api return type fix * CB-4039 logout extended * CB-4389. Refactor after review * CB-4389. Refactor after review * CB-4039 okta logout redirect moved to AuthenticationService * CB-4039 remove windowService dep * CB-4039 removes old logic of identity provider logout links * CB-4039 okta review changes * CB-4389. Merge logout logic into branch * CB-4389. Delete param after review * CB-4389. Converted reverse proxy to identity provider * CB-4389. Added auto configuration for Reverse proxy if its enabled on ce, fixed typo, rename plugin parameters * CB-4389. Added check for already exist configuration * CB-4389. Refactor after review * CB-4389. Refactor after review * CB-4389. Refactor after review * CB-4039 adds logout with context for Okta Identity Provider * CB-4039 okta logout redirect moved to AuthenticationService * CB-4389. Merge logout logic into branch * CB-4389. Delete param after review * CB-4546 shows hex/base64 only on blob column selection (#2314) Co-authored-by: s.teleshev Co-authored-by: Evgenia Bezborodova <139753579+EvgeniaBzzz@users.noreply.github.com> Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com> * CB-4389. Fix logout redirect and npe for logout parameter * CB-4389. Fix logout redirect and npe for logout parameter * CB-4389. Change version --------- Co-authored-by: Aleksandr Skoblikov Co-authored-by: s.teleshev Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com> Co-authored-by: Evgenia Bezborodova <139753579+EvgeniaBzzz@users.noreply.github.com> Co-authored-by: sergeyteleshev --- .../auth/SMAuthProviderFederated.java | 9 +- .../auth/SMSignOutLinkProvider.java | 37 ++++++ .../WebAuthProviderConfiguration.java | 5 +- .../io.cloudbeaver.service.auth/plugin.xml | 3 + .../cloudbeaver/service/auth/RPConstants.java | 26 +++++ .../service/auth/RPSessionHandler.java | 49 ++++++-- .../auth/ReverseProxyConfigurator.java | 110 ++++++++++++++++++ .../service/auth/impl/WebServiceAuthImpl.java | 19 ++- .../plugin.xml | 11 ++ .../auth/provider/rp/RPAuthProvider.java | 18 ++- .../CBEmbeddedSecurityController.java | 2 +- 11 files changed, 262 insertions(+), 27 deletions(-) create mode 100644 server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMSignOutLinkProvider.java create mode 100644 server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPConstants.java create mode 100644 server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java index 1ec4d407ed..bd2bab25e2 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMAuthProviderFederated.java @@ -27,17 +27,12 @@ * Federated auth provider. * Provides links to external auth resource */ -public interface SMAuthProviderFederated { +public interface SMAuthProviderFederated extends SMSignOutLinkProvider { @NotNull String getSignInLink(String id, @NotNull Map providerConfig) throws DBException; - /** - * @return a common link for logout, not related with the user context - */ - @NotNull - String getCommonSignOutLink(String id, @NotNull Map providerConfig) throws DBException; - + @Override default String getUserSignOutLink( @NotNull SMAuthProviderCustomConfiguration providerConfig, @NotNull Map userCredentials diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMSignOutLinkProvider.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMSignOutLinkProvider.java new file mode 100644 index 0000000000..3cbd7f70b1 --- /dev/null +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/auth/SMSignOutLinkProvider.java @@ -0,0 +1,37 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2024 DBeaver Corp and others + * + * 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 io.cloudbeaver.auth; + +import org.jkiss.code.NotNull; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration; + +import java.util.Map; + +public interface SMSignOutLinkProvider { + + /** + * @return a common link for logout, not related with the user context + */ + @NotNull + String getCommonSignOutLink(String id, @NotNull Map providerConfig) throws DBException; + + String getUserSignOutLink( + @NotNull SMAuthProviderCustomConfiguration providerConfig, + @NotNull Map userCredentials + ) throws DBException; +} diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java index 46712a0a59..864d765b41 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/registry/WebAuthProviderConfiguration.java @@ -18,6 +18,7 @@ import io.cloudbeaver.auth.CBAuthConstants; import io.cloudbeaver.auth.SMAuthProviderFederated; +import io.cloudbeaver.auth.SMSignOutLinkProvider; import io.cloudbeaver.utils.WebAppUtils; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; @@ -85,8 +86,8 @@ private String buildRedirectUrl(String baseUrl) { @Property public String getSignOutLink() throws DBException { SMAuthProvider instance = providerDescriptor.getInstance(); - return instance instanceof SMAuthProviderFederated - ? ((SMAuthProviderFederated) instance).getCommonSignOutLink(getId(), config.getParameters()) + return instance instanceof SMSignOutLinkProvider + ? ((SMSignOutLinkProvider) instance).getCommonSignOutLink(getId(), config.getParameters()) : null; } diff --git a/server/bundles/io.cloudbeaver.service.auth/plugin.xml b/server/bundles/io.cloudbeaver.service.auth/plugin.xml index 01901218ac..e888ba9255 100644 --- a/server/bundles/io.cloudbeaver.service.auth/plugin.xml +++ b/server/bundles/io.cloudbeaver.service.auth/plugin.xml @@ -7,6 +7,9 @@ + + diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPConstants.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPConstants.java new file mode 100644 index 0000000000..304be1493a --- /dev/null +++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPConstants.java @@ -0,0 +1,26 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2024 DBeaver Corp and others + * + * 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 io.cloudbeaver.service.auth; + +interface RPConstants { + String PARAM_LOGOUT_URL = "logout-url"; + String PARAM_USER = "user-header"; + String PARAM_TEAM = "team-header"; + String PARAM_FIRST_NAME = "first-name-header"; + String PARAM_LAST_NAME = "last-name-header"; + String PARAM_ROLE_NAME = "role-header"; +} diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java index 10f4669cb6..4088b0beaa 100644 --- a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java +++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java @@ -33,6 +33,7 @@ import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.auth.SMAuthInfo; +import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration; import org.jkiss.dbeaver.model.security.SMConstants; import org.jkiss.dbeaver.model.security.SMController; import org.jkiss.dbeaver.model.security.SMStandardMeta; @@ -41,10 +42,10 @@ import java.io.IOException; import java.text.MessageFormat; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; public class RPSessionHandler implements DBWSessionHandler { @@ -62,22 +63,38 @@ public boolean handleSessionOpen(WebSession webSession, HttpServletRequest reque return false; } - public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @NotNull WebSession webSession) throws DBWebException { + public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @NotNull WebSession webSession) throws DBException { SMController securityController = webSession.getSecurityController(); WebAuthProviderDescriptor authProvider = WebAuthProviderRegistry.getInstance().getAuthProvider(RPAuthProvider.AUTH_PROVIDER); if (authProvider == null) { throw new DBWebException("Auth provider " + RPAuthProvider.AUTH_PROVIDER + " not found"); } SMAuthProviderExternal authProviderExternal = (SMAuthProviderExternal) authProvider.getInstance(); - String userName = request.getHeader(RPAuthProvider.X_USER); - String teams = request.getHeader(RPAuthProvider.X_TEAM); + SMAuthProviderCustomConfiguration configuration = WebAppUtils.getWebAuthApplication() + .getAuthConfiguration() + .getAuthCustomConfigurations() + .stream() + .filter(p -> p.getProvider().equals(authProvider.toString())) + .findFirst() + .orElse(null); + Map paramConfigMap = new HashMap<>(); + if (configuration != null) { + authProvider.getConfigurationParameters().forEach(p -> + paramConfigMap.put(p.getId(), configuration.getParameters().get(p.getId()) + )); + } + String userName = request.getHeader( + resolveParam(paramConfigMap.get(RPConstants.PARAM_USER), RPAuthProvider.X_USER) + ); + String teams = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_TEAM), RPAuthProvider.X_TEAM)); if (CommonUtils.isEmpty(teams)) { // backward compatibility teams = request.getHeader(RPAuthProvider.X_ROLE); } - String role = request.getHeader(RPAuthProvider.X_ROLE_TE); - String firstName = request.getHeader(RPAuthProvider.X_FIRST_NAME); - String lastName = request.getHeader(RPAuthProvider.X_LAST_NAME); + String role = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_ROLE_NAME), RPAuthProvider.X_ROLE_TE)); + String firstName = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_FIRST_NAME), RPAuthProvider.X_FIRST_NAME)); + String lastName = request.getHeader(resolveParam(paramConfigMap.get(RPConstants.PARAM_LAST_NAME), RPAuthProvider.X_LAST_NAME)); + String logoutUrl = Objects.requireNonNull(configuration).getParameter(RPConstants.PARAM_LOGOUT_URL); List userTeams = teams == null ? Collections.emptyList() : List.of(teams.split("\\|")); if (userName != null) { try { @@ -89,6 +106,9 @@ public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @Not if (!CommonUtils.isEmpty(lastName)) { credentials.put(SMStandardMeta.META_LAST_NAME, lastName); } + if (CommonUtils.isNotEmpty(logoutUrl)) { + credentials.put("logoutUrl", logoutUrl); + } Map sessionParameters = webSession.getSessionParameters(); sessionParameters.put(SMConstants.SESSION_PARAM_TRUSTED_USER_TEAMS, userTeams); sessionParameters.put(SMConstants.SESSION_PARAM_TRUSTED_USER_ROLE, role); @@ -102,7 +122,7 @@ public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @Not webSession.getSessionId(), currentSmSessionId, sessionParameters, - WebSession.CB_SESSION_TYPE, authProvider.getId(), null, userCredentials); + WebSession.CB_SESSION_TYPE, authProvider.getId(), configuration.getId(), userCredentials); new WebSessionAuthProcessor(webSession, smAuthInfo, false).authenticateSession(); log.debug(MessageFormat.format( "Successful reverse proxy authentication: user ''{0}'' with teams {1}", userName, userTeams)); @@ -120,4 +140,11 @@ public void reverseProxyAuthentication(@NotNull HttpServletRequest request, @Not public boolean handleSessionClose(WebSession webSession) throws DBException, IOException { return false; } + + private String resolveParam(Object value, String defaultValue) { + if (value != null && !value.toString().isEmpty()) { + return value.toString(); + } + return defaultValue; + } } diff --git a/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java new file mode 100644 index 0000000000..ee415c0ffc --- /dev/null +++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/ReverseProxyConfigurator.java @@ -0,0 +1,110 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2024 DBeaver Corp and others + * + * 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 io.cloudbeaver.service.auth; + +import io.cloudbeaver.auth.provider.rp.RPAuthProvider; +import io.cloudbeaver.model.app.WebAppConfiguration; +import io.cloudbeaver.model.app.WebApplication; +import io.cloudbeaver.model.app.WebAuthApplication; +import io.cloudbeaver.model.session.WebSession; +import io.cloudbeaver.service.DBWServiceServerConfigurator; +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.Log; +import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration; + +import java.util.HashMap; +import java.util.Map; + +public class ReverseProxyConfigurator implements DBWServiceServerConfigurator { + private static final Log log = Log.getLog(ReverseProxyConfigurator.class); + + @Override + public void configureServer( + @NotNull WebApplication application, + @Nullable WebSession session, + @NotNull WebAppConfiguration appConfig + ) throws DBException { + } + + @Override + public void migrateConfigurationIfNeeded(@NotNull WebApplication application) throws DBException { + if (migrationNotNeeded(application)) { + return; + } + migrateConfiguration(application); + } + + @Override + public void reloadConfiguration(@NotNull WebAppConfiguration appConfig) throws DBException { + + } + + private void migrateConfiguration( + @NotNull WebApplication application + ) { + if (!(application instanceof WebAuthApplication authApplication)) { + return; + } + + SMAuthProviderCustomConfiguration smReverseProxyProviderConfiguration = + authApplication.getAuthConfiguration().getAuthProviderConfiguration(RPAuthProvider.AUTH_PROVIDER); + if (smReverseProxyProviderConfiguration == null) { + smReverseProxyProviderConfiguration = new SMAuthProviderCustomConfiguration(RPAuthProvider.AUTH_PROVIDER); + smReverseProxyProviderConfiguration.setProvider(RPAuthProvider.AUTH_PROVIDER); + smReverseProxyProviderConfiguration.setDisplayName("Reverse Proxy"); + smReverseProxyProviderConfiguration.setDescription( + "Automatically created provider after changing Reverse Proxy configuration way in 23.3.4 version" + ); + smReverseProxyProviderConfiguration .setIconURL(""); + Map parameters = new HashMap<>(); + parameters.put(RPConstants.PARAM_USER, RPAuthProvider.X_USER); + parameters.put(RPConstants.PARAM_TEAM, RPAuthProvider.X_TEAM); + parameters.put(RPConstants.PARAM_FIRST_NAME, RPAuthProvider.X_FIRST_NAME); + parameters.put(RPConstants.PARAM_LAST_NAME, RPAuthProvider.X_LAST_NAME); + smReverseProxyProviderConfiguration.setParameters(parameters); + authApplication.getAuthConfiguration().addAuthProviderConfiguration(smReverseProxyProviderConfiguration ); + try { + authApplication.flushConfiguration(); + } catch (Exception e) { + log.error("Failed to save server configuration", e); + } + } + } + + private boolean migrationNotNeeded(@NotNull WebApplication application) { + if (!(application instanceof WebAuthApplication authApplication)) { + return true; + } + + if (!authApplication.getAuthConfiguration().isAuthProviderEnabled(RPAuthProvider.AUTH_PROVIDER)) { + log.debug("Reverse proxy provider disabled, migration not needed"); + return true; + } + + boolean isReverseProxyConfigured = authApplication.getAuthConfiguration() + .getAuthCustomConfigurations().stream() + .anyMatch(p -> p.getProvider().equals(RPAuthProvider.AUTH_PROVIDER)); + + if (isReverseProxyConfigured) { + log.debug("Reverse proxy provider already exist, migration not needed"); + return true; + } + return false; + } +} 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 0d1f3db208..f590be3c38 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 @@ -19,6 +19,7 @@ import io.cloudbeaver.DBWebException; import io.cloudbeaver.WebServiceUtils; import io.cloudbeaver.auth.SMAuthProviderFederated; +import io.cloudbeaver.auth.SMSignOutLinkProvider; import io.cloudbeaver.auth.provider.local.LocalAuthProvider; import io.cloudbeaver.model.WebPropertyInfo; import io.cloudbeaver.model.session.WebAuthInfo; @@ -148,8 +149,8 @@ public WebLogoutInfo authLogout( var cbApp = CBApplication.getInstance(); for (WebAuthInfo removedInfo : removedInfos) { if (removedInfo.getAuthProviderDescriptor() - .getInstance() instanceof SMAuthProviderFederated federatedProvider - && removedInfo.getAuthSession() instanceof SMSessionExternal externalSession + .getInstance() instanceof SMSignOutLinkProvider provider + && removedInfo.getAuthSession() != null ) { var providerConfig = cbApp.getAuthConfiguration().getAuthProviderConfiguration(removedInfo.getAuthConfiguration()); @@ -157,9 +158,17 @@ public WebLogoutInfo authLogout( log.warn(removedInfo.getAuthConfiguration() + " provider configuration wasn't found"); continue; } - String logoutUrl = federatedProvider.getUserSignOutLink(providerConfig, - externalSession.getAuthParameters()); - logoutUrls.add(logoutUrl); + String logoutUrl; + if (removedInfo.getAuthSession() instanceof SMSessionExternal externalSession) { + logoutUrl = provider.getUserSignOutLink(providerConfig, + externalSession.getAuthParameters()); + } else { + logoutUrl = provider.getUserSignOutLink(providerConfig, + Map.of()); + } + if (CommonUtils.isNotEmpty(logoutUrl)) { + logoutUrls.add(logoutUrl); + } } } return new WebLogoutInfo(logoutUrls); diff --git a/server/bundles/io.cloudbeaver.service.security/plugin.xml b/server/bundles/io.cloudbeaver.service.security/plugin.xml index 88eff847ae..5878dca3c7 100644 --- a/server/bundles/io.cloudbeaver.service.security/plugin.xml +++ b/server/bundles/io.cloudbeaver.service.security/plugin.xml @@ -18,6 +18,7 @@ @@ -25,6 +26,16 @@ + + + + + + + + + + diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java index 8d8d0a0244..14106ec3cb 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/auth/provider/rp/RPAuthProvider.java @@ -18,6 +18,7 @@ import io.cloudbeaver.DBWUserIdentity; import io.cloudbeaver.auth.SMAuthProviderExternal; +import io.cloudbeaver.auth.SMSignOutLinkProvider; import io.cloudbeaver.auth.provider.local.LocalAuthSession; import io.cloudbeaver.model.session.WebSession; import io.cloudbeaver.model.user.WebUser; @@ -37,7 +38,7 @@ import java.util.HashMap; import java.util.Map; -public class RPAuthProvider implements SMAuthProviderExternal { +public class RPAuthProvider implements SMAuthProviderExternal, SMSignOutLinkProvider { private static final Log log = Log.getLog(RPAuthProvider.class); @@ -49,6 +50,7 @@ public class RPAuthProvider implements SMAuthProviderExternal { public static final String X_FIRST_NAME = "X-First-name"; public static final String X_LAST_NAME = "X-Last-name"; public static final String AUTH_PROVIDER = "reverseProxy"; + public static final String LOGOUT_URL = "logout-url"; @NotNull @Override @@ -122,4 +124,18 @@ public void closeSession(@NotNull SMSession mainSession, SMSession session) thro public void refreshSession(@NotNull DBRProgressMonitor monitor, @NotNull SMSession mainSession, SMSession session) throws DBException { } + + @NotNull + @Override + public String getCommonSignOutLink(String id, @NotNull Map providerConfig) throws DBException { + return providerConfig.get(LOGOUT_URL) != null ? providerConfig.get(LOGOUT_URL).toString() : ""; + } + + @Override + public String getUserSignOutLink(@NotNull SMAuthProviderCustomConfiguration providerConfig, @NotNull Map userCredentials) throws DBException { + return providerConfig.getParameters().get(LOGOUT_URL) != null ? + providerConfig.getParameters().get(LOGOUT_URL).toString() : + null; + } + } diff --git a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java index 3120ac1f67..d9c223c900 100644 --- a/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java +++ b/server/bundles/io.cloudbeaver.service.security/src/io/cloudbeaver/service/security/CBEmbeddedSecurityController.java @@ -1346,7 +1346,7 @@ public SMAuthInfo authenticate( String signInLink = buildRedirectLink(authProviderFederated.getSignInLink(authProviderConfigurationId, Map.of()), authAttemptId); String signOutLink = authProviderFederated.getCommonSignOutLink(authProviderConfigurationId, - Map.of()); + providerConfig.getParameters()); Map authData = Map.of(new SMAuthConfigurationReference(authProviderId, authProviderConfigurationId), filteredUserCreds); return SMAuthInfo.inProgress(authAttemptId, signInLink, signOutLink, authData, isMainSession);