dbeaver/pro#9721 [CB] Add a flag into reverse proxy allowing new user… (#4460)

* dbeaver/pro#9721 [CB] Add a flag into reverse proxy allowing new users creation

* dbeaver/pro#9721 [CB] code style fix

* dbeaver/pro#9721 [CB] code style fix

* dbeaver/pro#9721 move the method isAutoUserProvisioningEnabled to SMAuthProviderExternal

* dbeaver/pro#9721 linter fix

* dbeaver/pro#9721 code review fix

* dbeaver/pro#9721 code review fix

* dbeaver/pro#9721 code review fix

* dbeaver/pro#9721 Fix login for existing users without reverse proxy credentials when auto user provisioning is disabled

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
This commit is contained in:
Daniil
2026-07-23 10:09:30 +02:00
committed by GitHub
co-authored by Evgenia
parent f54f377344
commit eda1f8720f
7 changed files with 38 additions and 5 deletions
@@ -69,6 +69,13 @@ public interface SMAuthProviderExternal<AUTH_SESSION extends SMSession> extends
@NotNull WebUser user,
boolean selfIdentity) throws DBException;
/**
* Whether a user that is not found should be provisioned (auto-created) on external login.
*/
default boolean isAutoUserProvisioningEnabled(@Nullable SMAuthProviderCustomConfiguration providerConfig) {
return true;
}
/**
* Make some post authentication actions
*/
@@ -80,8 +80,9 @@ public class ReverseProxyConfigurator implements DBWServiceServerConfigurator {
parameters.put(RPConstants.PARAM_FIRST_NAME, RPAuthProvider.X_FIRST_NAME);
parameters.put(RPConstants.PARAM_LAST_NAME, RPAuthProvider.X_LAST_NAME);
parameters.put(RPConstants.PARAM_FULL_NAME, RPAuthProvider.X_FULL_NAME);
parameters.put(RPAuthProvider.PARAM_AUTO_USER_PROVISIONING, true);
smReverseProxyProviderConfiguration.setParameters(parameters);
authApplication.getAuthConfiguration().addAuthProviderConfiguration(smReverseProxyProviderConfiguration );
authApplication.getAuthConfiguration().addAuthProviderConfiguration(smReverseProxyProviderConfiguration);
try {
authApplication.flushConfiguration();
} catch (Exception e) {
@@ -14,3 +14,5 @@ prop.auth.model.reverseProxy.full-name-header = Full name header
prop.auth.model.reverseProxy.full-name-header.description = Full name header name
prop.auth.model.reverseProxy.role-header = Role header
prop.auth.model.reverseProxy.role-header.description = Role header name
prop.auth.model.reverseProxy.auto-user-provisioning = Auto-create users
prop.auth.model.reverseProxy.auto-user-provisioning.description = Create the user automatically on first reverse proxy login if it does not exist yet. When disabled, only existing users can log in
@@ -13,4 +13,6 @@ prop.auth.model.reverseProxy.last-name-header.description = Имя заголо
prop.auth.model.reverseProxy.full-name-header = Заголовок полного имени
prop.auth.model.reverseProxy.full-name-header.description = Имя заголовка полного имени
prop.auth.model.reverseProxy.role-header = Заголовок роли
prop.auth.model.reverseProxy.role-header.description = Имя заголовка роли
prop.auth.model.reverseProxy.role-header.description = Имя заголовка роли
prop.auth.model.reverseProxy.auto-user-provisioning = Автосоздание пользователей
prop.auth.model.reverseProxy.auto-user-provisioning.description = Создавать пользователя автоматически при первом входе через reverse proxy, если его ещё нет. Если выключено — входить могут только существующие пользователи
@@ -37,6 +37,7 @@
<property id="last-name-header" label="%last-name-header" type="string" description="%last-name-header.description"/>
<property id="full-name-header" label="%full-name-header" type="string" description="%full-name-header.description"/>
<property id="role-header" label="%role-header" type="string" description="%role-header.description" requiredFeatures="distributed"/>
<property id="auto-user-provisioning" label="%auto-user-provisioning" type="boolean" description="%auto-user-provisioning.description" defaultValue="true"/>
</propertyGroup>
</configuration>
</authProvider>
@@ -52,6 +52,7 @@ public class RPAuthProvider implements SMAuthProviderExternal<SMSession>, SMSign
public static final String X_FULL_NAME = "X-Full-name";
public static final String AUTH_PROVIDER = "reverseProxy";
public static final String LOGOUT_URL = "logout-url";
public static final String PARAM_AUTO_USER_PROVISIONING = "auto-user-provisioning";
@NotNull
@Override
@@ -71,6 +72,17 @@ public class RPAuthProvider implements SMAuthProviderExternal<SMSession>, SMSign
}
}
@Override
public boolean isAutoUserProvisioningEnabled(@Nullable SMAuthProviderCustomConfiguration providerConfig) {
if (providerConfig == null) {
return true;
}
return CommonUtils.getBoolean(
providerConfig.getParameters().get(PARAM_AUTO_USER_PROVISIONING),
true
);
}
@NotNull
@Override
public DBWUserIdentity getUserIdentity(
@@ -2880,7 +2880,7 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
@Nullable String activeUserId,
boolean createNewUserIfNotExist,
@Nullable String authRole,
SMAuthProviderCustomConfiguration providerConfig
@Nullable SMAuthProviderCustomConfiguration providerConfig
) throws DBException {
SMAuthProvider<?> smAuthProviderInstance = authProvider.getInstance();
@@ -2898,12 +2898,20 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
+ userIdFromCredentials + "'");
}
if (userId == null && createNewUserIfNotExist) {
if (!(authProvider.getInstance() instanceof SMAuthProviderExternal<?>)) {
if (!(smAuthProviderInstance instanceof SMAuthProviderExternal<?> externalProvider)) {
return null;
}
userId = authProvider.isCaseInsensitive() ? userIdFromCredentials.toLowerCase() : userIdFromCredentials;
if (!isSubjectExists(userId)) {
// Users are looked up by the credentials of this particular provider, so an already
// existing user that has no credentials for it yet is not found above. This is a typical
// reverse proxy case: the user was created earlier (by an admin or another provider) and
// only gets its reverse proxy credentials linked below on the first login.
// Therefore auto provisioning is checked here only, where the user really does not exist.
if (!externalProvider.isAutoUserProvisioningEnabled(providerConfig)) {
log.debug("User '" + userId + "' not found and auto user provisioning is disabled");
return null;
}
log.debug("Create user: " + userId);
validateAndCreateUser(
userId,