mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Cb 3738 exception when logout invalid update token (#1853)
* CB-3738 log all gql errors * CB-3310 do not update token for child sessions * CB-3738 skip headless session on refresh --------- Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
This commit is contained in:
co-authored by
mr-anton-t
parent
d2f1f29e80
commit
d93d7748cf
+17
-7
@@ -80,16 +80,21 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
* refresh context state based on new token from security manager
|
||||
*
|
||||
* @param smAuthInfo - auth info from security manager
|
||||
* @return - true if context changed
|
||||
* @throws DBException - if user already authorized and new token come from another user
|
||||
*/
|
||||
public synchronized boolean refresh(SMAuthInfo smAuthInfo) throws DBException {
|
||||
if (smAuthInfo.getAuthStatus() != SMAuthStatus.SUCCESS || smAuthInfo.getSmAccessToken() == null) {
|
||||
throw new DBCException("Authorization did not complete successfully");
|
||||
}
|
||||
if (smAuthInfo.getAuthPermissions() == null) {
|
||||
if (smAuthInfo.getAuthPermissions() == null && !isAuthorizedInSecurityManager()) {
|
||||
throw new DBCException("Required information about session permissions is missing");
|
||||
}
|
||||
return refresh(smAuthInfo.getSmAccessToken(), smAuthInfo.getSmRefreshToken(), smAuthInfo.getAuthPermissions());
|
||||
boolean sessionChanged = !CommonUtils.equalObjects(smSessionId, smAuthInfo.getAuthPermissions().getSessionId());
|
||||
if (smAuthInfo.getAuthStatus() != SMAuthStatus.SUCCESS || (sessionChanged && smAuthInfo.getSmAccessToken() == null)) {
|
||||
throw new DBCException("Authorization did not complete successfully");
|
||||
}
|
||||
if (sessionChanged) {
|
||||
return refresh(smAuthInfo.getSmAccessToken(), smAuthInfo.getSmRefreshToken(), smAuthInfo.getAuthPermissions());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized boolean refresh(
|
||||
@@ -108,7 +113,7 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
smAuthPermissions.getSessionId(),
|
||||
smAuthPermissions.getPermissions()
|
||||
);
|
||||
this.refreshToken = smRefreshToken;
|
||||
setRefreshToken(smRefreshToken);
|
||||
setUserPermissions(smAuthPermissions.getPermissions());
|
||||
this.securityController = application.createSecurityController(this);
|
||||
this.adminSecurityController = application.getAdminSecurityController(this);
|
||||
@@ -131,7 +136,7 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
return;
|
||||
}
|
||||
var newTokens = securityController.refreshSession(refreshToken);
|
||||
this.refreshToken = newTokens.getSmRefreshToken();
|
||||
setRefreshToken(newTokens.getSmRefreshToken());
|
||||
this.smCredentials = new SMCredentials(
|
||||
newTokens.getSmAccessToken(),
|
||||
smCredentials.getUserId(),
|
||||
@@ -204,6 +209,7 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
*/
|
||||
public synchronized void refreshPermissions() throws DBException {
|
||||
if (isAuthorizedInSecurityManager()) {
|
||||
log.debug("refresh permissions " + getUserId() + " " + getSmSessionId());
|
||||
setUserPermissions(securityController.getTokenPermissions().getPermissions());
|
||||
} else {
|
||||
setUserPermissions(getDefaultPermissions());
|
||||
@@ -238,4 +244,8 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
public Set<String> getAccessibleProjectIds() {
|
||||
return accessibleProjectIds;
|
||||
}
|
||||
|
||||
private void setRefreshToken(@Nullable String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
|
||||
public class SessionStateJob extends PeriodicSystemJob {
|
||||
private static final Log log = Log.getLog(SessionStateJob.class);
|
||||
private static final int PERIOD_MS = 60_000; // once per 60 seconds
|
||||
private static final int PERIOD_MS = 30_000; // once per 60 seconds
|
||||
|
||||
public SessionStateJob(@NotNull CBPlatform platform) {
|
||||
super("Session state sender", platform, PERIOD_MS);
|
||||
|
||||
+1
@@ -174,6 +174,7 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
|
||||
throw e.getTargetException();
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
log.error("Unexpected error during gql request", ex);
|
||||
if (SMUtils.isTokenExpiredExceptionWasHandled(ex)) {
|
||||
WebSession webSession = findWebSession(env);
|
||||
if (webSession != null) {
|
||||
|
||||
+10
-3
@@ -326,11 +326,18 @@ public class WebSessionManager {
|
||||
/**
|
||||
* Send session state with remaining alive time to all cached session
|
||||
*/
|
||||
public void sendSessionsStates() throws DBException {
|
||||
public void sendSessionsStates() {
|
||||
synchronized (sessionMap) {
|
||||
for (var session : sessionMap.values()) {
|
||||
session.getUserContext().refreshPermissions();
|
||||
session.addSessionEvent(new WSSessionStateEvent(session.getRemainingTime(), session.isValid()));
|
||||
if (session instanceof WebHeadlessSession) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
session.getUserContext().refreshPermissions();
|
||||
session.addSessionEvent(new WSSessionStateEvent(session.getRemainingTime(), session.isValid()));
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to refresh session state: " + session.getSessionId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+35
-19
@@ -1183,7 +1183,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
var smTokens = generateNewSessionToken(smSessionId, null, null, dbCon);
|
||||
var permissions = getAnonymousUserPermissions();
|
||||
txn.commit();
|
||||
return SMAuthInfo.success(
|
||||
return SMAuthInfo.successMainSession(
|
||||
UUID.randomUUID().toString(),
|
||||
smTokens.getSmAccessToken(),
|
||||
smTokens.getSmRefreshToken(),
|
||||
@@ -1215,6 +1215,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
var authProgressMonitor = new LoggingProgressMonitor(log);
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
|
||||
boolean isMainSession = previousSmSessionId == null;
|
||||
Map<String, Object> securedUserIdentifyingCredentials = userCredentials;
|
||||
WebAuthProviderDescriptor authProviderDescriptor = getAuthProvider(authProviderId);
|
||||
var authProviderInstance = authProviderDescriptor.getInstance();
|
||||
@@ -1236,7 +1237,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
appSessionId,
|
||||
previousSmSessionId,
|
||||
sessionType,
|
||||
sessionParameters
|
||||
sessionParameters,
|
||||
isMainSession
|
||||
);
|
||||
|
||||
if (SMAuthProviderFederated.class.isAssignableFrom(authProviderInstance.getClass())) {
|
||||
@@ -1252,7 +1254,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
return finishAuthentication(
|
||||
SMAuthInfo.inProgress(
|
||||
authAttemptId,
|
||||
null, Map.of(new SMAuthConfigurationReference(authProviderId, null), securedUserIdentifyingCredentials)
|
||||
null,
|
||||
Map.of(new SMAuthConfigurationReference(authProviderId, null), securedUserIdentifyingCredentials)
|
||||
),
|
||||
true,
|
||||
false
|
||||
@@ -1286,7 +1289,8 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
String appSessionId,
|
||||
String prevSessionId,
|
||||
SMSessionType sessionType,
|
||||
Map<String, Object> sessionParameters
|
||||
Map<String, Object> sessionParameters,
|
||||
boolean isMainSession
|
||||
) throws DBException {
|
||||
String authAttemptId = UUID.randomUUID().toString();
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
@@ -1489,7 +1493,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
SMTokens smTokens = findTokenBySmSession(smSessionId);
|
||||
SMAuthPermissions authPermissions = getTokenPermissions(smTokens.getSmAccessToken());
|
||||
String authRole = readTokenAuthRole(smTokens.getSmAccessToken());
|
||||
var successAuthStatus = SMAuthInfo.success(
|
||||
var successAuthStatus = SMAuthInfo.successMainSession(
|
||||
authId,
|
||||
smTokens.getSmAccessToken(),
|
||||
smTokens.getSmRefreshToken(),
|
||||
@@ -1517,7 +1521,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
for (SMAuthInfo authData : allLatestAuthData) {
|
||||
mergedData.putAll(authData.getAuthData());
|
||||
}
|
||||
return SMAuthInfo.success(
|
||||
return SMAuthInfo.successMainSession(
|
||||
"restore_session_attempt_" + UUID.randomUUID(),
|
||||
latestActiveSmTokens.getAccessToken(),
|
||||
latestActiveSmTokens.getRefreshToken(),
|
||||
@@ -1597,6 +1601,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
return currentUserCreds;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SMTokens findTokenBySmSession(String smSessionId) throws DBException {
|
||||
try (Connection dbCon = database.openConnection();
|
||||
PreparedStatement dbStat = dbCon.prepareStatement(
|
||||
@@ -1697,12 +1702,13 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
|
||||
SMTokens smTokens = null;
|
||||
SMAuthPermissions permissions = null;
|
||||
String activeUserId = null;
|
||||
if (!isMainAuthSession) {
|
||||
var accessToken = findTokenBySmSession(authAttemptSessionInfo.getSmSessionId()).getSmAccessToken();
|
||||
//this is an additional authorization and we should to return the original permissions and userId
|
||||
smTokens = findTokenBySmSession(authAttemptSessionInfo.getSmSessionId());
|
||||
permissions = getTokenPermissions(smTokens.getSmAccessToken());
|
||||
permissions = getTokenPermissions(accessToken);
|
||||
activeUserId = permissions.getUserId();
|
||||
}
|
||||
String activeUserId = permissions == null ? null : permissions.getUserId();
|
||||
|
||||
Map<SMAuthConfigurationReference, Object> storedUserData = new LinkedHashMap<>();
|
||||
SMTeam[] allTeams = null;
|
||||
@@ -1768,7 +1774,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
|
||||
String tokenAuthRole = updateUserAuthRoleIfNeeded(activeUserId, detectedAuthRole);
|
||||
if (smTokens == null && permissions == null) {
|
||||
if (isMainAuthSession) {
|
||||
try (Connection dbCon = database.openConnection()) {
|
||||
try (JDBCTransaction txn = new JDBCTransaction(dbCon)) {
|
||||
String smSessionId;
|
||||
@@ -1798,15 +1804,24 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
}
|
||||
var authStatus = forceExpireAuthAfterSuccess ? SMAuthStatus.EXPIRED : SMAuthStatus.SUCCESS;
|
||||
updateAuthStatus(authId, authStatus, storedUserData, null, permissions.getSessionId());
|
||||
return SMAuthInfo.success(
|
||||
authId,
|
||||
smTokens.getSmAccessToken(),
|
||||
//refresh token must be sent only once
|
||||
isMainAuthSession ? smTokens.getSmRefreshToken() : null,
|
||||
permissions,
|
||||
authInfo.getAuthData(),
|
||||
tokenAuthRole
|
||||
);
|
||||
|
||||
if (isMainAuthSession) {
|
||||
return SMAuthInfo.successMainSession(
|
||||
authId,
|
||||
smTokens.getSmAccessToken(),
|
||||
//refresh token must be sent only from main session
|
||||
smTokens.getSmRefreshToken(),
|
||||
permissions,
|
||||
authInfo.getAuthData(),
|
||||
tokenAuthRole
|
||||
);
|
||||
} else {
|
||||
return SMAuthInfo.successChildSession(
|
||||
authId,
|
||||
permissions,
|
||||
authInfo.getAuthData()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void autoUpdateUserTeams(
|
||||
@@ -2057,6 +2072,7 @@ public class CBEmbeddedSecurityController implements SMAdminController, SMAuthen
|
||||
return getTokenPermissions(activeUserCredentials.getSmAccessToken());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SMAuthPermissions getTokenPermissions(@NotNull String token) throws DBException {
|
||||
String userId;
|
||||
String sessionId;
|
||||
|
||||
Reference in New Issue
Block a user