Merge pull request #1088 from patriot1burke/master
oidc and saml broker backchannel logout
This commit is contained in:
commit
d36ee0d0af
54 files changed
+899
-289
No files matched your search
Regular → Executable
+1
-1
@@ -314,7 +314,7 @@ public class TokenEndpoint {
|
||||
|
||||
UserSessionProvider sessions = session.sessions();
|
||||
|
||||
UserSessionModel userSession = sessions.createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "oauth_credentials", false);
|
||||
UserSessionModel userSession = sessions.createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "oauth_credentials", false, null, null);
|
||||
event.session(userSession);
|
||||
|
||||
ClientSessionModel clientSession = sessions.createClientSession(realm, client);
|
||||
|
||||
@@ -90,8 +90,8 @@ public class AuthenticationManager {
|
||||
userSession.setState(UserSessionModel.State.LOGGING_OUT);
|
||||
|
||||
logger.debugv("Logging out: {0} ({1})", user.getUsername(), userSession.getId());
|
||||
expireIdentityCookie(realm, uriInfo, connection);
|
||||
expireRememberMeCookie(realm, uriInfo, connection);
|
||||
//expireIdentityCookie(realm, uriInfo, connection);
|
||||
//expireRememberMeCookie(realm, uriInfo, connection);
|
||||
|
||||
for (ClientSessionModel clientSession : userSession.getClientSessions()) {
|
||||
ClientModel client = clientSession.getClient();
|
||||
|
||||
Regular → Executable
+1
-1
@@ -116,7 +116,7 @@ public class HttpAuthenticationManager {
|
||||
event.error(Errors.USER_DISABLED);
|
||||
response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.ACCOUNT_DISABLED);
|
||||
} else {
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), authMethod, false);
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), authMethod, false, null, null);
|
||||
|
||||
// Propagate state (like kerberos delegation credentials etc) as attributes of userSession
|
||||
for (Map.Entry<String, String> entry : authState.entrySet()) {
|
||||
|
||||
@@ -131,23 +131,6 @@ public class ResourceAdminManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void logoutSession(URI requestUri, RealmModel realm, UserSessionModel session) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
try {
|
||||
// Map from "app" to clientSessions for this app
|
||||
MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ApplicationModel, ClientSessionModel>();
|
||||
putClientSessions(clientSessions, session);
|
||||
|
||||
logger.debugv("logging out {0} resources ", clientSessions.size());
|
||||
for (Map.Entry<ApplicationModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
|
||||
logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue(), executor);
|
||||
}
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void logoutUserFromApplication(URI requestUri, RealmModel realm, ApplicationModel resource, UserModel user, KeycloakSession session) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
@@ -179,6 +162,7 @@ public class ResourceAdminManager {
|
||||
|
||||
// Key is host, value is list of http sessions for this host
|
||||
MultivaluedHashMap<String, String> adapterSessionIds = null;
|
||||
List<String> userSessions = new LinkedList<>();
|
||||
if (clientSessions != null && clientSessions.size() > 0) {
|
||||
adapterSessionIds = new MultivaluedHashMap<String, String>();
|
||||
for (ClientSessionModel clientSession : clientSessions) {
|
||||
@@ -187,6 +171,7 @@ public class ResourceAdminManager {
|
||||
String host = clientSession.getNote(AdapterConstants.APPLICATION_SESSION_HOST);
|
||||
adapterSessionIds.add(host, adapterSessionId);
|
||||
}
|
||||
if (clientSession.getUserSession() != null) userSessions.add(clientSession.getUserSession().getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +187,7 @@ public class ResourceAdminManager {
|
||||
String host = entry.getKey();
|
||||
List<String> sessionIds = entry.getValue();
|
||||
String currentHostMgmtUrl = managementUrl.replace(APPLICATION_SESSION_HOST_PROPERTY, host);
|
||||
allPassed = sendLogoutRequest(realm, resource, sessionIds, client, 0, currentHostMgmtUrl) && allPassed;
|
||||
allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, client, 0, currentHostMgmtUrl) && allPassed;
|
||||
}
|
||||
|
||||
return allPassed;
|
||||
@@ -213,7 +198,7 @@ public class ResourceAdminManager {
|
||||
allSessionIds.addAll(currentIds);
|
||||
}
|
||||
|
||||
return sendLogoutRequest(realm, resource, allSessionIds, client, 0, managementUrl);
|
||||
return sendLogoutRequest(realm, resource, allSessionIds, userSessions, client, 0, managementUrl);
|
||||
}
|
||||
} else {
|
||||
logger.debugv("Can't logout {0}: no management url", resource.getName());
|
||||
@@ -265,7 +250,7 @@ public class ResourceAdminManager {
|
||||
// Propagate this to all hosts
|
||||
GlobalRequestResult result = new GlobalRequestResult();
|
||||
for (String mgmtUrl : mgmtUrls) {
|
||||
if (sendLogoutRequest(realm, resource, null, executor, notBefore, mgmtUrl)) {
|
||||
if (sendLogoutRequest(realm, resource, null, null, executor, notBefore, mgmtUrl)) {
|
||||
result.addSuccessRequest(mgmtUrl);
|
||||
} else {
|
||||
result.addFailedRequest(mgmtUrl);
|
||||
@@ -274,8 +259,8 @@ public class ResourceAdminManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean sendLogoutRequest(RealmModel realm, ApplicationModel resource, List<String> adapterSessionIds, ApacheHttpClient4Executor client, int notBefore, String managementUrl) {
|
||||
LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), adapterSessionIds, notBefore);
|
||||
protected boolean sendLogoutRequest(RealmModel realm, ApplicationModel resource, List<String> adapterSessionIds, List<String> userSessions, ApacheHttpClient4Executor client, int notBefore, String managementUrl) {
|
||||
LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), adapterSessionIds, notBefore, userSessions);
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getName(), managementUrl);
|
||||
ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build().toString());
|
||||
|
||||
@@ -615,8 +615,7 @@ public class AccountService {
|
||||
List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
|
||||
for (UserSessionModel s : sessions) {
|
||||
if (!s.getId().equals(auth.getSession().getId())) {
|
||||
new ResourceAdminManager().logoutSession(uriInfo.getRequestUri(), realm, s);
|
||||
session.sessions().removeUserSession(realm, s);
|
||||
AuthenticationManager.backchannelLogout(session, realm, s, uriInfo, clientConnection, headers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||
updateFederatedIdentity(federatedIdentity, federatedUser);
|
||||
|
||||
UserSessionModel userSession = this.session.sessions()
|
||||
.createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false);
|
||||
.createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false, federatedIdentity.getBrokerSessionId(), federatedIdentity.getBrokerUserId());
|
||||
|
||||
this.event.user(federatedUser);
|
||||
this.event.session(userSession);
|
||||
|
||||
@@ -344,7 +344,7 @@ public class LoginActionsService {
|
||||
switch (status) {
|
||||
case SUCCESS:
|
||||
case ACTIONS_REQUIRED:
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", remember);
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", remember, null, null);
|
||||
TokenManager.attachClientSession(userSession, clientSession);
|
||||
event.session(userSession);
|
||||
return authManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
|
||||
@@ -885,7 +885,7 @@ public class LoginActionsService {
|
||||
} else{
|
||||
event.user(user);
|
||||
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", false);
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", false, null, null);
|
||||
event.session(userSession);
|
||||
TokenManager.attachClientSession(userSession, clientSession);
|
||||
|
||||
|
||||
+10
-2
@@ -15,6 +15,7 @@ import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
@@ -23,6 +24,7 @@ import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.events.Event;
|
||||
import org.keycloak.events.EventQuery;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
@@ -42,6 +44,7 @@ import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
||||
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.LDAPConnectionTestManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.ResourceAdminManager;
|
||||
@@ -67,6 +70,12 @@ public class RealmAdminResource {
|
||||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
protected ClientConnection connection;
|
||||
|
||||
@Context
|
||||
protected HttpHeaders headers;
|
||||
|
||||
public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager) {
|
||||
this.auth = auth;
|
||||
this.realm = realm;
|
||||
@@ -297,8 +306,7 @@ public class RealmAdminResource {
|
||||
public void deleteSession(@PathParam("session") String sessionId) {
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm, sessionId);
|
||||
if (userSession == null) throw new NotFoundException("Sesssion not found");
|
||||
session.sessions().removeUserSession(realm, userSession);
|
||||
new ResourceAdminManager().logoutSession(uriInfo.getRequestUri(), realm, userSession);
|
||||
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.keycloak.representations.idm.MappingsRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.ResourceAdminManager;
|
||||
@@ -51,6 +52,7 @@ import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
@@ -87,6 +89,9 @@ public class UsersResource {
|
||||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
@Context
|
||||
protected HttpHeaders headers;
|
||||
|
||||
public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager) {
|
||||
this.auth = auth;
|
||||
this.realm = realm;
|
||||
@@ -321,8 +326,10 @@ public class UsersResource {
|
||||
if (user == null) {
|
||||
throw new NotFoundException("User not found");
|
||||
}
|
||||
new ResourceAdminManager().logoutUser(uriInfo.getRequestUri(), realm, user, session);
|
||||
session.sessions().removeUserSessions(realm, user);
|
||||
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
|
||||
for (UserSessionModel userSession : userSessions) {
|
||||
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -728,7 +735,7 @@ public class UsersResource {
|
||||
}
|
||||
|
||||
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", false);
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", false, null, null);
|
||||
//audit.session(userSession);
|
||||
ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
|
||||
clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
|
||||
Reference in new issue
Block a user