From b0d323914a84b17717d6f53c1c6c8f3000289e93 Mon Sep 17 00:00:00 2001
From: Ainur <59531286+yagudin10@users.noreply.github.com>
Date: Tue, 15 Mar 2022 12:20:55 +0300
Subject: [PATCH] CB-1546 reverse proxy header auth (#709)
---
.../auth/provider/local/LocalAuthSession.java | 2 +-
.../io/cloudbeaver/server/CBAppConfig.java | 10 ++
.../io.cloudbeaver.service.auth/plugin.xml | 3 +
.../service/auth/RPSessionHandler.java | 101 ++++++++++++++++++
4 files changed, 115 insertions(+), 1 deletion(-)
create mode 100644 server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java
diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java
index 266f0b5278..a88bc75403 100644
--- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java
+++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/auth/provider/local/LocalAuthSession.java
@@ -33,7 +33,7 @@ public class LocalAuthSession implements SMSession {
private final SMSession webSession;
private final String userId;
- LocalAuthSession(SMSession webSession, String userId) {
+ public LocalAuthSession(SMSession webSession, String userId) {
this.webSession = webSession;
this.userId = userId;
}
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 475dd6c94d..ee9553eb4f 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 implements WebAppConfiguration {
private boolean supportsCustomConnections;
private boolean supportsConnectionBrowser;
private boolean supportsUserWorkspaces;
+ private boolean supportsReverseProxyAuth;
private boolean publicCredentialsSaveEnabled;
private boolean adminCredentialsSaveEnabled;
@@ -84,6 +85,7 @@ public class CBAppConfig implements WebAppConfiguration {
this.plugins = new LinkedHashMap<>();
this.authConfiguration = new LinkedHashMap<>();
this.resourceQuotas = new LinkedHashMap<>();
+ this.supportsReverseProxyAuth = false;
}
public CBAppConfig(CBAppConfig src) {
@@ -105,6 +107,7 @@ public class CBAppConfig implements WebAppConfiguration {
this.plugins = new LinkedHashMap<>(src.plugins);
this.authConfiguration = new LinkedHashMap<>(src.authConfiguration);
this.resourceQuotas = new LinkedHashMap<>(src.resourceQuotas);
+ this.supportsReverseProxyAuth = src.supportsReverseProxyAuth;
}
public boolean isAnonymousAccessEnabled() {
@@ -328,4 +331,11 @@ public class CBAppConfig implements WebAppConfiguration {
}
}
+ ////////////////////////////////////////////
+ // Reverse proxy auth
+
+ public boolean isSupportsReverseProxyAuth() {
+ return supportsReverseProxyAuth;
+ }
+
}
diff --git a/server/bundles/io.cloudbeaver.service.auth/plugin.xml b/server/bundles/io.cloudbeaver.service.auth/plugin.xml
index 88c2b42c37..2c07a5ec6e 100644
--- a/server/bundles/io.cloudbeaver.service.auth/plugin.xml
+++ b/server/bundles/io.cloudbeaver.service.auth/plugin.xml
@@ -19,6 +19,9 @@
+
+
+
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
new file mode 100644
index 0000000000..f970099a5c
--- /dev/null
+++ b/server/bundles/io.cloudbeaver.service.auth/src/io/cloudbeaver/service/auth/RPSessionHandler.java
@@ -0,0 +1,101 @@
+package io.cloudbeaver.service.auth;
+
+import io.cloudbeaver.DBWUserIdentity;
+import io.cloudbeaver.DBWebException;
+import io.cloudbeaver.auth.provider.local.LocalAuthSession;
+import io.cloudbeaver.model.session.WebAuthInfo;
+import io.cloudbeaver.model.session.WebSession;
+import io.cloudbeaver.model.user.WebUser;
+import io.cloudbeaver.server.CBApplication;
+import io.cloudbeaver.server.CBPlatform;
+import io.cloudbeaver.service.DBWSessionHandler;
+import org.jkiss.code.NotNull;
+import org.jkiss.dbeaver.DBException;
+import org.jkiss.dbeaver.model.auth.SMSession;
+import org.jkiss.dbeaver.model.security.SMController;
+import org.jkiss.dbeaver.registry.auth.AuthProviderDescriptor;
+import org.jkiss.dbeaver.registry.auth.AuthProviderRegistry;
+import org.jkiss.utils.CommonUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.OffsetDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RPSessionHandler implements DBWSessionHandler {
+
+ public static final String X_USER = "X-User";
+ public static final String X_ROLE = "X-Role";
+ public static final String AUTH_PROVIDER = "local";
+
+ @Override
+ public boolean handleSessionOpen(WebSession webSession, HttpServletRequest request, HttpServletResponse response) throws DBException, IOException {
+ boolean configMode = CBApplication.getInstance().isConfigurationMode();
+ //checks if the app is not in configuration mode and reverse proxy auth is enabled in the config file
+ if (!configMode && CBApplication.getInstance().getAppConfiguration().isSupportsReverseProxyAuth()) {
+ reverseProxyAuthentication(request, webSession);
+ }
+ return false;
+ }
+ public boolean reverseProxyAuthentication(@NotNull HttpServletRequest request, @NotNull WebSession webSession) throws DBWebException {
+ SMController securityController = CBPlatform.getInstance().getApplication().getSecurityController();
+ AuthProviderDescriptor authProvider = AuthProviderRegistry.getInstance().getAuthProvider(AUTH_PROVIDER);
+
+ String userName = request.getHeader(X_USER);
+ String roles = request.getHeader(X_ROLE);
+ String[] userRoles = roles.split("\\|");
+ WebUser curUser = webSession.getUser();
+ SMSession authSession;
+ if (userName != null) {
+ try {
+ WebUser user = securityController.getUserById(userName);
+ Map credentials = new HashMap<>();
+ credentials.put("user", userName);
+ var adminSecurityController = CBPlatform.getInstance().getApplication().getAdminSecurityController();
+ if (user == null) {
+ // User doesn't exist. We can create new user automatically
+ // Create new user
+ curUser = new WebUser(userName);
+ adminSecurityController.createUser(curUser);
+
+ String defaultRoleName = CBPlatform.getInstance().getApplication().getAppConfiguration().getDefaultUserRole();
+ if (userRoles.length == 0) {
+ userRoles = new String[]{defaultRoleName};
+ }
+ // We need to associate new credentials with active user
+ securityController.setUserCredentials(userName, authProvider, credentials);
+ }
+ adminSecurityController.setUserRoles(userName, userRoles, userName);
+ user = curUser;
+ if (user == null) {
+ user = new WebUser(userName);
+ }
+ DBWUserIdentity userIdentity = new DBWUserIdentity(userName, userName);
+
+ if (CommonUtils.isEmpty(user.getDisplayName())) {
+ user.setDisplayName(userIdentity.getDisplayName());
+ }
+ authSession = new LocalAuthSession(webSession, userName);
+
+ WebAuthInfo authInfo = new WebAuthInfo(
+ webSession,
+ user,
+ authProvider,
+ userIdentity,
+ authSession,
+ OffsetDateTime.now());
+ authInfo.setMessage("Authenticated with " + authProvider.getLabel() + " provider");
+ webSession.addAuthInfo(authInfo);
+ } catch (Exception e) {
+ throw new DBWebException("Error", e);
+ }
+ }
+ return false;
+ }
+ @Override
+ public boolean handleSessionClose(WebSession webSession) throws DBException, IOException {
+ return false;
+ }
+}