Merge pull request #4610 from hmlnarik/KEYCLOAK-5745-Extract-client-sessions-from-user-sessions
KEYCLOAK-5745 Separate user and client sessions in infinispan
This commit is contained in:
commit
248da4687a
61 files changed
+919
-443
No files matched your search
@@ -159,13 +159,13 @@ public class TokenManager {
|
||||
}
|
||||
|
||||
ClientModel client = session.getContext().getClient();
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
|
||||
// Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
|
||||
if (clientSession == null) {
|
||||
userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
|
||||
if (userSession != null) {
|
||||
clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
} else {
|
||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
|
||||
}
|
||||
@@ -400,7 +400,7 @@ public class TokenManager {
|
||||
public static AuthenticatedClientSessionModel attachAuthenticationSession(KeycloakSession session, UserSessionModel userSession, AuthenticationSessionModel authSession) {
|
||||
ClientModel client = authSession.getClient();
|
||||
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
if (clientSession == null) {
|
||||
clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
|
||||
}
|
||||
@@ -436,8 +436,9 @@ public class TokenManager {
|
||||
return;
|
||||
}
|
||||
|
||||
clientSession.setUserSession(null);
|
||||
clientSession.detachFromUserSession();
|
||||
|
||||
// TODO: Might need optimization to prevent loading client sessions from cache in getAuthenticatedClientSessions()
|
||||
if (userSession.getAuthenticatedClientSessions().isEmpty()) {
|
||||
sessions.removeUserSession(realm, userSession);
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ public class TokenEndpoint {
|
||||
|
||||
// Attempt to use same code twice should invalidate existing clientSession
|
||||
if (clientSession != null) {
|
||||
clientSession.setUserSession(null);
|
||||
clientSession.detachFromUserSession();
|
||||
}
|
||||
|
||||
event.error(Errors.INVALID_CODE);
|
||||
@@ -400,7 +400,7 @@ public class TokenEndpoint {
|
||||
|
||||
if (!result.isOfflineToken()) {
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm, res.getSessionState());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
updateClientSession(clientSession);
|
||||
updateUserSessionFromClientAuth(userSession);
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ public class UserInfoEndpoint {
|
||||
|
||||
|
||||
// Existence of authenticatedClientSession for our client already handled before
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(clientModel.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(clientModel.getId());
|
||||
|
||||
AccessToken userInfo = new AccessToken();
|
||||
tokenManager.transformUserInfoAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession);
|
||||
|
||||
@@ -400,7 +400,7 @@ public class SamlService extends AuthorizationEndpointBase {
|
||||
userSession.setNote(SamlProtocol.SAML_LOGOUT_CANONICALIZATION, samlClient.getCanonicalizationMethod());
|
||||
userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
|
||||
// remove client from logout requests
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
if (clientSession != null) {
|
||||
clientSession.setAction(AuthenticationSessionModel.Action.LOGGED_OUT.name());
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class SamlSessionUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
return userSession.getAuthenticatedClientSessions().get(parts[1]);
|
||||
return userSession.getAuthenticatedClientSessionByClient(clientUUID);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -395,7 +395,7 @@ public class AuthenticationManager {
|
||||
public static void backchannelLogoutUserFromClient(KeycloakSession session, RealmModel realm, UserModel user, ClientModel client, UriInfo uriInfo, HttpHeaders headers) {
|
||||
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
|
||||
for (UserSessionModel userSession : userSessions) {
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
if (clientSession != null) {
|
||||
AuthenticationManager.backchannelLogoutClientSession(session, realm, clientSession, null, uriInfo, headers);
|
||||
clientSession.setAction(AuthenticationSessionModel.Action.LOGGED_OUT.name());
|
||||
|
||||
@@ -172,7 +172,7 @@ class CodeGenerateUtil {
|
||||
}
|
||||
}
|
||||
|
||||
return userSession.getAuthenticatedClientSessions().get(codeJWT.getIssuedFor());
|
||||
return userSession.getAuthenticatedClientSessionByClient(codeJWT.getIssuedFor());
|
||||
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -42,7 +42,7 @@ public class UserSessionCrossDCManager {
|
||||
|
||||
// get userSession if it has "authenticatedClientSession" of specified client attached to it. Otherwise download it from remoteCache
|
||||
public UserSessionModel getUserSessionWithClient(RealmModel realm, String id, boolean offline, String clientUUID) {
|
||||
return kcSession.sessions().getUserSessionWithPredicate(realm, id, offline, userSession -> userSession.getAuthenticatedClientSessions().containsKey(clientUUID));
|
||||
return kcSession.sessions().getUserSessionWithPredicate(realm, id, offline, userSession -> userSession.getAuthenticatedClientSessionByClient(clientUUID) != null);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ public class UserSessionCrossDCManager {
|
||||
|
||||
return kcSession.sessions().getUserSessionWithPredicate(realm, id, false, (UserSessionModel userSession) -> {
|
||||
|
||||
Map<String, AuthenticatedClientSessionModel> authSessions = userSession.getAuthenticatedClientSessions();
|
||||
return authSessions.containsKey(clientUUID);
|
||||
AuthenticatedClientSessionModel authSessions = userSession.getAuthenticatedClientSessionByClient(clientUUID);
|
||||
return authSessions != null;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class UserSessionManager {
|
||||
}
|
||||
|
||||
// Create and persist clientSession
|
||||
AuthenticatedClientSessionModel offlineClientSession = offlineUserSession.getAuthenticatedClientSessions().get(clientSession.getClient().getId());
|
||||
AuthenticatedClientSessionModel offlineClientSession = offlineUserSession.getAuthenticatedClientSessionByClient(clientSession.getClient().getId());
|
||||
if (offlineClientSession == null) {
|
||||
createOfflineClientSession(user, clientSession, offlineUserSession);
|
||||
}
|
||||
@@ -97,14 +97,14 @@ public class UserSessionManager {
|
||||
List<UserSessionModel> userSessions = kcSession.sessions().getOfflineUserSessions(realm, user);
|
||||
boolean anyRemoved = false;
|
||||
for (UserSessionModel userSession : userSessions) {
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
if (clientSession != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.tracef("Removing existing offline token for user '%s' and client '%s' .",
|
||||
user.getUsername(), client.getClientId());
|
||||
}
|
||||
|
||||
clientSession.setUserSession(null);
|
||||
clientSession.detachFromUserSession();
|
||||
persister.removeClientSession(userSession.getId(), client.getId(), true);
|
||||
checkOfflineUserSessionHasClientSessions(realm, user, userSession);
|
||||
anyRemoved = true;
|
||||
@@ -154,7 +154,8 @@ public class UserSessionManager {
|
||||
|
||||
// Check if userSession has any offline clientSessions attached to it. Remove userSession if not
|
||||
private void checkOfflineUserSessionHasClientSessions(RealmModel realm, UserModel user, UserSessionModel userSession) {
|
||||
if (userSession.getAuthenticatedClientSessions().size() > 0) {
|
||||
// TODO: Might need optimization to prevent loading client sessions from cache
|
||||
if (! userSession.getAuthenticatedClientSessions().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ public class AccountFormService extends AbstractSecuredLocalService {
|
||||
if (authResult != null) {
|
||||
UserSessionModel userSession = authResult.getSession();
|
||||
if (userSession != null) {
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessions().get(client.getId());
|
||||
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
|
||||
if (clientSession == null) {
|
||||
clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ public class UserResource {
|
||||
UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);
|
||||
|
||||
// Update lastSessionRefresh with the timestamp from clientSession
|
||||
AuthenticatedClientSessionModel clientSession = session.getAuthenticatedClientSessions().get(clientId);
|
||||
AuthenticatedClientSessionModel clientSession = session.getAuthenticatedClientSessionByClient(clientId);
|
||||
|
||||
// Skip if userSession is not for this client
|
||||
if (clientSession == null) {
|
||||
|
||||
Reference in new issue
Block a user