dbeaver/pro#8260 Provide a method to create or restore a WebSession… (#4222)

* dbeaver/pro#8260 Provide a method to create or restore a `WebSession` from `smAccessToken`

* dbeaver/pro#8260 Annotations and constants

---------

Co-authored-by: Ivan Gagarkin <gagarkin@Ivans-MacBook-Pro.local>
Co-authored-by: Serge Rider <serge@jkiss.org>
Co-authored-by: serge-rider <serge@dbeaver.com>
This commit is contained in:
Ivan Gagarkin
2026-03-24 10:56:19 +01:00
committed by GitHub
co-authored by Ivan Gagarkin Serge Rider serge-rider
parent 3ae74763ff
commit 44077ad27a
4 changed files with 63 additions and 90 deletions
@@ -379,6 +379,63 @@ public class CBSessionManager implements WebAppSessionManager {
}
}
@Nullable
public WebSession getWebSession(
@Nullable String smAccessToken,
@NotNull WebHttpRequestInfo requestInfo,
boolean create
) throws DBException {
if (CommonUtils.isEmpty(smAccessToken)) {
return null;
}
synchronized (sessionMap) {
var tempCredProvider = new SMTokenCredentialProvider(smAccessToken);
SMAuthPermissions authPermissions = application.createSecurityController(tempCredProvider).getTokenPermissions();
var sessionId = requestInfo.getId() != null ? requestInfo.getId()
: authPermissions.getSessionId();
var existSession = sessionMap.get(sessionId);
if (existSession instanceof WebSession webSession) {
var creds = webSession.getUserContext().getActiveUserCredentials();
if (creds == null || !smAccessToken.equals(creds.getSmAccessToken())) {
if (webSession.getUserContext().refresh(
smAccessToken,
null,
authPermissions
)) {
webSession.refreshUserData();
}
}
return webSession;
}
if (existSession != null) {
//session exist but it not web session
return null;
}
if (!create) {
return null;
}
if (requestInfo.getId() == null) {
requestInfo = new WebHttpRequestInfo(
sessionId,
requestInfo.getLocale(),
requestInfo.getLastRemoteAddress(),
requestInfo.getLastRemoteUserAgent()
);
}
var webSession = createWebSessionImpl(requestInfo);
webSession.getUserContext().refresh(
smAccessToken,
null,
authPermissions
);
webSession.refreshUserData();
sessionMap.put(sessionId, webSession);
return webSession;
}
}
/**
* Send session state with remaining alive time to all cached session
*/
@@ -24,7 +24,6 @@ import jakarta.websocket.HandshakeResponse;
import jakarta.websocket.server.HandshakeRequest;
import jakarta.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.ee11.websocket.jakarta.server.internal.JakartaWebSocketCreator;
import org.eclipse.jetty.http.BadMessageException;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
@@ -89,7 +88,7 @@ public class CBWebSocketServerConfigurator extends ServerEndpointConfig.Configur
throw new RuntimeException(e.getMessage(), e);
}
if (sec.getUserProperties().get(PROP_WEB_SESSION) == null) {
throw new BadMessageException("No web session found for websocket request");
throw new RuntimeException("No web session found for websocket request");
}
}
@@ -97,8 +96,8 @@ public class CBWebSocketServerConfigurator extends ServerEndpointConfig.Configur
private String getSessionId(@NotNull HandshakeRequest request) {
// complex auth uses bearer authentication
List<String> authHeaders = WSClientUtils.getHeaders(request.getHeaders(), HttpConstants.HEADER_AUTHORIZATION);
if (!CommonUtils.isEmpty(authHeaders) && authHeaders.get(0).startsWith("Bearer ")) {
return authHeaders.get(0).substring(7);
if (!CommonUtils.isEmpty(authHeaders) && authHeaders.getFirst().startsWith(HttpConstants.BEARER_PREFIX)) {
return authHeaders.getFirst().substring(7);
}
return request.getHttpSession() instanceof HttpSession httpSession ? httpSession.getId() : null;
}
@@ -32,7 +32,6 @@ import io.cloudbeaver.service.security.bruteforce.UserLoginRecord;
import io.cloudbeaver.service.security.db.CBDatabase;
import io.cloudbeaver.service.security.internal.AuthAttemptSessionInfo;
import io.cloudbeaver.service.security.internal.CBAuthSubjectRepo;
import io.cloudbeaver.service.security.internal.SMTokenInfo;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -2437,7 +2436,9 @@ public class CBEmbeddedSecurityController<T extends ServletAuthApplication>
}
}
private SMTokenInfo readAccessTokenInfo(String smAccessToken) throws DBException {
@NotNull
@Override
public SMTokenInfo readAccessTokenInfo(@NotNull String smAccessToken) throws DBException {
try (Connection dbCon = database.openConnection();
PreparedStatement dbStat = dbCon.prepareStatement(
"""
@@ -1,84 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 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.security.internal;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
public class SMTokenInfo {
@NotNull
private final String accessToken;
@NotNull
private final String refreshToken;
@NotNull
private final String sessionId;
@NotNull
private final String userId;
@Nullable
private final String authRole;
private final boolean serviceToken;
public SMTokenInfo(
@NotNull String accessToken,
@NotNull String refreshToken,
@NotNull String sessionId,
@NotNull String userId,
@Nullable String authRole,
boolean serviceToken
) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
this.sessionId = sessionId;
this.userId = userId;
this.authRole = authRole;
this.serviceToken = serviceToken;
}
@NotNull
public String getRefreshToken() {
return refreshToken;
}
@NotNull
public String getSessionId() {
return sessionId;
}
@NotNull
public String getUserId() {
return userId;
}
@NotNull
public String getAccessToken() {
return accessToken;
}
@Nullable
public String getAuthRole() {
return authRole;
}
public boolean isServiceToken() {
return serviceToken;
}
}