Merge pull request #1088 from patriot1burke/master

oidc and saml broker backchannel logout
This commit is contained in:
Bill Burke committed 2015-03-26 08:43:21 -04:00
commit d36ee0d0af
54 files changed
+899 -289

No files matched your search

+1 -1
View File
@@ -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();
@@ -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);
@@ -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);