merge conflicts
This commit is contained in:
commit
0ace5cd746
49 files changed
+626
-942
No files matched your search
@@ -142,7 +142,7 @@ public class OpenIDConnect implements LoginProtocol {
|
||||
ApacheHttpClient4Executor executor = ResourceAdminManager.createExecutor();
|
||||
|
||||
try {
|
||||
new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, app, null, userSession.getId(), executor, 0);
|
||||
new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, app, clientSession, executor, 0);
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.keycloak.Config;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.adapters.AdapterConstants;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
@@ -611,6 +612,17 @@ public class OpenIDConnectService {
|
||||
.build();
|
||||
}
|
||||
|
||||
String httpSessionId = formData.getFirst(AdapterConstants.HTTP_SESSION_ID);
|
||||
if (httpSessionId != null) {
|
||||
String httpSessionHost = formData.getFirst(AdapterConstants.HTTP_SESSION_HOST);
|
||||
logger.infof("Http Session '%s' saved in ClientSession for client '%s'. Host is '%s'", httpSessionId, client.getClientId(), httpSessionHost);
|
||||
|
||||
event.detail(AdapterConstants.HTTP_SESSION_ID, httpSessionId);
|
||||
clientSession.setNote(AdapterConstants.HTTP_SESSION_ID, httpSessionId);
|
||||
event.detail(AdapterConstants.HTTP_SESSION_HOST, httpSessionHost);
|
||||
clientSession.setNote(AdapterConstants.HTTP_SESSION_HOST, httpSessionHost);
|
||||
}
|
||||
|
||||
AccessToken token = tokenManager.createClientAccessToken(accessCode.getRequestedRoles(), realm, client, user, userSession);
|
||||
|
||||
try {
|
||||
|
||||
@@ -17,22 +17,23 @@ import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.representations.adapters.action.LogoutAction;
|
||||
import org.keycloak.representations.adapters.action.PushNotBeforeAction;
|
||||
import org.keycloak.representations.adapters.action.SessionStats;
|
||||
import org.keycloak.representations.adapters.action.SessionStatsAction;
|
||||
import org.keycloak.representations.adapters.action.UserStats;
|
||||
import org.keycloak.representations.adapters.action.UserStatsAction;
|
||||
import org.keycloak.services.util.HttpClientBuilder;
|
||||
import org.keycloak.services.util.ResolveRelative;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
import org.keycloak.util.StringPropertyReplacer;
|
||||
import org.keycloak.util.Time;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
@@ -40,17 +41,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class ResourceAdminManager {
|
||||
protected static Logger logger = Logger.getLogger(ResourceAdminManager.class);
|
||||
|
||||
public SessionStats getSessionStats(URI requestUri, KeycloakSession session, RealmModel realm, ApplicationModel application, boolean users) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
try {
|
||||
return getSessionStats(requestUri, session, realm, application, users, executor);
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
private static final String KC_SESSION_HOST = "${kc_session_host}";
|
||||
|
||||
public static ApacheHttpClient4Executor createExecutor() {
|
||||
HttpClient client = new HttpClientBuilder()
|
||||
@@ -59,49 +50,6 @@ public class ResourceAdminManager {
|
||||
return new ApacheHttpClient4Executor(client);
|
||||
}
|
||||
|
||||
public SessionStats getSessionStats(URI requestUri, KeycloakSession session, RealmModel realm, ApplicationModel application, boolean users, ApacheHttpClient4Executor client) {
|
||||
String managementUrl = getManagementUrl(requestUri, application);
|
||||
if (managementUrl != null) {
|
||||
SessionStatsAction adminAction = new SessionStatsAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, application.getName());
|
||||
adminAction.setListUsers(users);
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
logger.debugv("session stats for application: {0} url: {1}", application.getName(), managementUrl);
|
||||
ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_GET_SESSION_STATS).build().toString());
|
||||
ClientResponse<SessionStats> response = null;
|
||||
try {
|
||||
response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post(SessionStats.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
if (response.getStatus() != 200) {
|
||||
logger.warn("Failed to get stats: " + response.getStatus());
|
||||
return null;
|
||||
}
|
||||
SessionStats stats = response.getEntity();
|
||||
|
||||
// replace with username
|
||||
if (users && stats.getUsers() != null) {
|
||||
Map<String, UserStats> newUsers = new HashMap<String, UserStats>();
|
||||
for (Map.Entry<String, UserStats> entry : stats.getUsers().entrySet()) {
|
||||
UserModel user = session.users().getUserById(entry.getKey(), realm);
|
||||
if (user == null) continue;
|
||||
newUsers.put(user.getUsername(), entry.getValue());
|
||||
|
||||
}
|
||||
stats.setUsers(newUsers);
|
||||
}
|
||||
return stats;
|
||||
} finally {
|
||||
response.releaseConnection();
|
||||
}
|
||||
} else {
|
||||
logger.debug("no management url.");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getManagementUrl(URI requestUri, ApplicationModel application) {
|
||||
String mgmtUrl = application.getManagementUrl();
|
||||
if (mgmtUrl == null || mgmtUrl.equals("")) {
|
||||
@@ -111,95 +59,56 @@ public class ResourceAdminManager {
|
||||
// this is to support relative admin urls when keycloak and applications are deployed on the same machine
|
||||
String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, mgmtUrl);
|
||||
|
||||
// this is for resolving URI like "http://${jboss.home.name}:8080/..." in order to send request to same machine and avoid LB in cluster env
|
||||
// this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment
|
||||
return StringPropertyReplacer.replaceProperties(absoluteURI);
|
||||
}
|
||||
|
||||
public UserStats getUserStats(URI requestUri, RealmModel realm, ApplicationModel application, UserModel user) {
|
||||
public void logoutUser(URI requestUri, RealmModel realm, UserModel user, KeycloakSession keycloakSession) {
|
||||
List<UserSessionModel> userSessions = keycloakSession.sessions().getUserSessions(realm, user);
|
||||
logoutUserSessions(requestUri, realm, userSessions);
|
||||
}
|
||||
|
||||
protected void logoutUserSessions(URI requestUri, RealmModel realm, List<UserSessionModel> userSessions) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
try {
|
||||
return getUserStats(requestUri, realm, application, user, executor);
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public UserStats getUserStats(URI requestUri, RealmModel realm, ApplicationModel application, UserModel user, ApacheHttpClient4Executor client) {
|
||||
String managementUrl = getManagementUrl(requestUri, application);
|
||||
if (managementUrl != null) {
|
||||
UserStatsAction adminAction = new UserStatsAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, application.getName(), user.getId());
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
logger.debugv("session stats for application: {0} url: {1}", application.getName(), managementUrl);
|
||||
ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_GET_USER_STATS).build().toString());
|
||||
ClientResponse<UserStats> response = null;
|
||||
try {
|
||||
response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post(UserStats.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
// Map from "app" to clientSessions for this app
|
||||
MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ApplicationModel, ClientSessionModel>();
|
||||
for (UserSessionModel userSession : userSessions) {
|
||||
putClientSessions(clientSessions, userSession);
|
||||
}
|
||||
|
||||
try {
|
||||
if (response.getStatus() != 200) {
|
||||
logger.warn("Failed to get stats: " + response.getStatus());
|
||||
return null;
|
||||
}
|
||||
UserStats stats = response.getEntity();
|
||||
return stats;
|
||||
} finally {
|
||||
response.releaseConnection();
|
||||
}
|
||||
} else {
|
||||
logger.debug("no management url.");
|
||||
return null;
|
||||
}
|
||||
logger.debugv("logging out {0} resources ", clientSessions.size());
|
||||
logger.infov("logging out resources: " + clientSessions);
|
||||
|
||||
}
|
||||
|
||||
public void logoutUser(URI requestUri, RealmModel realm, String user, UserSessionModel session) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
try {
|
||||
List<ApplicationModel> resources;
|
||||
if (session != null) {
|
||||
resources = new LinkedList<ApplicationModel>();
|
||||
|
||||
for (ClientSessionModel clientSession : session.getClientSessions()) {
|
||||
ClientModel client = clientSession.getClient();
|
||||
if (client instanceof ApplicationModel) {
|
||||
resources.add((ApplicationModel) client);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resources = realm.getApplications();
|
||||
}
|
||||
|
||||
logger.debugv("logging out {0} resources ", resources.size());
|
||||
for (ApplicationModel resource : resources) {
|
||||
logoutApplication(requestUri, realm, resource, user, session != null ? session.getId() : null, executor, 0);
|
||||
for (Map.Entry<ApplicationModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
|
||||
logoutApplication(requestUri, realm, entry.getKey(), entry.getValue(), executor, 0);
|
||||
}
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void putClientSessions(MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions, UserSessionModel userSession) {
|
||||
for (ClientSessionModel clientSession : userSession.getClientSessions()) {
|
||||
ClientModel client = clientSession.getClient();
|
||||
if (client instanceof ApplicationModel) {
|
||||
clientSessions.add((ApplicationModel)client, clientSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void logoutSession(URI requestUri, RealmModel realm, UserSessionModel session) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
try {
|
||||
List<ApplicationModel> resources = new LinkedList<ApplicationModel>();
|
||||
for (ClientSessionModel clientSession : session.getClientSessions()) {
|
||||
ClientModel client = clientSession.getClient();
|
||||
if (client instanceof ApplicationModel) {
|
||||
resources.add((ApplicationModel) client);
|
||||
}
|
||||
}
|
||||
// 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 ", resources.size());
|
||||
for (ApplicationModel resource : resources) {
|
||||
logoutApplication(requestUri, realm, resource, null, session.getId(), executor, 0);
|
||||
logger.debugv("logging out {0} resources ", clientSessions.size());
|
||||
for (Map.Entry<ApplicationModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
|
||||
logoutApplication(requestUri, realm, entry.getKey(), entry.getValue(), executor, 0);
|
||||
}
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
@@ -214,46 +123,77 @@ public class ResourceAdminManager {
|
||||
List<ApplicationModel> resources = realm.getApplications();
|
||||
logger.debugv("logging out {0} resources ", resources.size());
|
||||
for (ApplicationModel resource : resources) {
|
||||
logoutApplication(requestUri, realm, resource, null, null, executor, realm.getNotBefore());
|
||||
logoutApplication(requestUri, realm, resource, (List<ClientSessionModel>)null, executor, realm.getNotBefore());
|
||||
}
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, String user, String session) {
|
||||
public void logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, List<UserSessionModel> userSessions) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
try {
|
||||
resource.setNotBefore(Time.currentTime());
|
||||
logoutApplication(requestUri, realm, resource, user, session, executor, resource.getNotBefore());
|
||||
|
||||
List<ClientSessionModel> ourAppClientSessions = null;
|
||||
if (userSessions != null) {
|
||||
MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ApplicationModel, ClientSessionModel>();
|
||||
for (UserSessionModel userSession : userSessions) {
|
||||
putClientSessions(clientSessions, userSession);
|
||||
}
|
||||
ourAppClientSessions = clientSessions.get(resource);
|
||||
}
|
||||
|
||||
logoutApplication(requestUri, realm, resource, ourAppClientSessions, executor, resource.getNotBefore());
|
||||
} finally {
|
||||
executor.getHttpClient().getConnectionManager().shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, ClientSessionModel clientSession, ApacheHttpClient4Executor client, int notBefore) {
|
||||
return logoutApplication(requestUri, realm, resource, Arrays.asList(clientSession), client, notBefore);
|
||||
}
|
||||
|
||||
public boolean logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, String user, String session, ApacheHttpClient4Executor client, int notBefore) {
|
||||
protected boolean logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, List<ClientSessionModel> clientSessions, ApacheHttpClient4Executor client, int notBefore) {
|
||||
String managementUrl = getManagementUrl(requestUri, resource);
|
||||
if (managementUrl != null) {
|
||||
LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), user, session, notBefore);
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
logger.debugv("logout user: {0} resource: {1} url: {2}", user, resource.getName(), managementUrl);
|
||||
ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build().toString());
|
||||
ClientResponse response;
|
||||
try {
|
||||
response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post(UserStats.class);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Logout for application '" + resource.getName() + "' failed", e);
|
||||
return false;
|
||||
|
||||
// Key is host, value is list of http sessions for this host
|
||||
MultivaluedHashMap<String, String> adapterSessionIds = null;
|
||||
if (clientSessions != null && clientSessions.size() > 0) {
|
||||
adapterSessionIds = new MultivaluedHashMap<String, String>();
|
||||
for (ClientSessionModel clientSession : clientSessions) {
|
||||
String adapterSessionId = clientSession.getNote(AdapterConstants.HTTP_SESSION_ID);
|
||||
if (adapterSessionId != null) {
|
||||
String host = clientSession.getNote(AdapterConstants.HTTP_SESSION_HOST);
|
||||
adapterSessionIds.add(host, adapterSessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
boolean success = response.getStatus() == 204;
|
||||
logger.debug("logout success.");
|
||||
return success;
|
||||
} finally {
|
||||
response.releaseConnection();
|
||||
|
||||
if (managementUrl.contains(KC_SESSION_HOST) && adapterSessionIds != null) {
|
||||
boolean allPassed = true;
|
||||
// Send logout separately to each host (needed for single-sign-out in cluster for non-distributable apps - KEYCLOAK-748)
|
||||
for (Map.Entry<String, List<String>> entry : adapterSessionIds.entrySet()) {
|
||||
String host = entry.getKey();
|
||||
List<String> sessionIds = entry.getValue();
|
||||
String currentHostMgmtUrl = managementUrl.replace(KC_SESSION_HOST, host);
|
||||
allPassed = logoutApplicationOnHost(realm, resource, sessionIds, client, notBefore, currentHostMgmtUrl) && allPassed;
|
||||
}
|
||||
|
||||
return allPassed;
|
||||
} else {
|
||||
// Send single logout request
|
||||
List<String> allSessionIds = null;
|
||||
if (adapterSessionIds != null) {
|
||||
allSessionIds = new ArrayList<String>();
|
||||
for (List<String> currentIds : adapterSessionIds.values()) {
|
||||
allSessionIds.addAll(currentIds);
|
||||
}
|
||||
}
|
||||
return logoutApplicationOnHost(realm, resource, allSessionIds, client, notBefore, managementUrl);
|
||||
}
|
||||
} else {
|
||||
logger.debugv("Can't logout {0}: no management url", resource.getName());
|
||||
@@ -261,6 +201,27 @@ public class ResourceAdminManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean logoutApplicationOnHost(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);
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
logger.infov("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getName(), managementUrl);
|
||||
ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build().toString());
|
||||
ClientResponse response;
|
||||
try {
|
||||
response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post(UserStats.class);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Logout for application '" + resource.getName() + "' failed", e);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
boolean success = response.getStatus() == 204;
|
||||
logger.debug("logout success.");
|
||||
return success;
|
||||
} finally {
|
||||
response.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public void pushRealmRevocationPolicy(URI requestUri, RealmModel realm) {
|
||||
ApacheHttpClient4Executor executor = createExecutor();
|
||||
|
||||
@@ -290,9 +251,9 @@ public class ResourceAdminManager {
|
||||
if (managementUrl != null) {
|
||||
PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), notBefore);
|
||||
String token = new TokenManager().encodeToken(realm, adminAction);
|
||||
logger.debugv("pushRevocation resource: {0} url: {1}", resource.getName(), managementUrl);
|
||||
logger.infov("pushRevocation resource: {0} url: {1}", resource.getName(), managementUrl);
|
||||
ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build().toString());
|
||||
ClientResponse response = null;
|
||||
ClientResponse response;
|
||||
try {
|
||||
response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post();
|
||||
} catch (Exception e) {
|
||||
|
||||
+4
-34
@@ -13,8 +13,6 @@ import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.representations.adapters.action.SessionStats;
|
||||
import org.keycloak.representations.adapters.action.UserStats;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||
@@ -27,7 +25,6 @@ import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
@@ -285,35 +282,6 @@ public class ApplicationResource {
|
||||
new ResourceAdminManager().pushApplicationRevocationPolicy(uriInfo.getRequestUri(), realm, application);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the application has an admin URL, query it directly for session stats.
|
||||
*
|
||||
* @param users whether to include users logged in.
|
||||
* @return
|
||||
*/
|
||||
@Path("session-stats")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public SessionStats getSessionStats(@QueryParam("users") @DefaultValue("false") boolean users) {
|
||||
logger.info("session-stats");
|
||||
auth.requireView();
|
||||
if (application.getManagementUrl() == null || application.getManagementUrl().trim().equals("")) {
|
||||
logger.info("sending empty stats");
|
||||
SessionStats stats = new SessionStats();
|
||||
if (users) stats.setUsers(new HashMap<String, UserStats>());
|
||||
return stats;
|
||||
}
|
||||
SessionStats stats = new ResourceAdminManager().getSessionStats(uriInfo.getRequestUri(), session, realm, application, users);
|
||||
if (stats == null) {
|
||||
logger.info("app returned null stats");
|
||||
} else {
|
||||
logger.info("activeUsers: " + stats.getActiveUsers());
|
||||
logger.info("activeSessions: " + stats.getActiveSessions());
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of user sessions associated with this application
|
||||
*
|
||||
@@ -363,7 +331,7 @@ public class ApplicationResource {
|
||||
@POST
|
||||
public void logoutAll() {
|
||||
auth.requireManage();
|
||||
new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application, null, null);
|
||||
new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +346,9 @@ public class ApplicationResource {
|
||||
if (user == null) {
|
||||
throw new NotFoundException("User not found");
|
||||
}
|
||||
new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application, user.getId(), null);
|
||||
|
||||
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
|
||||
new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application, userSessions);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.keycloak.models.cache.CacheUserProvider;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.representations.adapters.action.SessionStats;
|
||||
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.LDAPConnectionTestManager;
|
||||
@@ -323,28 +322,6 @@ public class RealmAdminResource {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any application that has an admin URL will be asked directly how many sessions they have active and what users
|
||||
* are involved with those sessions.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Path("session-stats")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Map<String, SessionStats> getSessionStats() {
|
||||
logger.info("session-stats");
|
||||
auth.requireView();
|
||||
Map<String, SessionStats> stats = new HashMap<String, SessionStats>();
|
||||
for (ApplicationModel applicationModel : realm.getApplications()) {
|
||||
if (applicationModel.getManagementUrl() == null) continue;
|
||||
SessionStats appStats = new ResourceAdminManager().getSessionStats(uriInfo.getRequestUri(), this.session, realm, applicationModel, false);
|
||||
stats.put(applicationModel.getName(), appStats);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* View the events provider and how it is configured.
|
||||
*
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.protocol.oidc.OpenIDConnect;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.representations.adapters.action.UserStats;
|
||||
import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.MappingsRepresentation;
|
||||
@@ -217,36 +216,6 @@ public class UsersResource {
|
||||
return ModelToRepresentation.toRepresentation(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* For each application with an admin URL, query them for the set of users logged in. This not as reliable
|
||||
* as getSessions().
|
||||
*
|
||||
* @See getSessions
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
@Path("{username}/session-stats")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Map<String, UserStats> getSessionStats(final @PathParam("username") String username) {
|
||||
logger.info("session-stats");
|
||||
auth.requireView();
|
||||
UserModel user = session.users().getUserByUsername(username, realm);
|
||||
if (user == null) {
|
||||
throw new NotFoundException("User not found");
|
||||
}
|
||||
Map<String, UserStats> stats = new HashMap<String, UserStats>();
|
||||
for (ApplicationModel applicationModel : realm.getApplications()) {
|
||||
if (applicationModel.getManagementUrl() == null) continue;
|
||||
UserStats appStats = new ResourceAdminManager().getUserStats(uriInfo.getRequestUri(), realm, applicationModel, user);
|
||||
if (appStats == null) continue;
|
||||
if (appStats.isLoggedIn()) stats.put(applicationModel.getName(), appStats);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* List set of sessions associated with this user.
|
||||
*
|
||||
@@ -258,7 +227,6 @@ public class UsersResource {
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<UserSessionRepresentation> getSessions(final @PathParam("username") String username) {
|
||||
logger.info("sessions");
|
||||
auth.requireView();
|
||||
UserModel user = session.users().getUserByUsername(username, realm);
|
||||
if (user == null) {
|
||||
@@ -345,8 +313,8 @@ 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);
|
||||
new ResourceAdminManager().logoutUser(uriInfo.getRequestUri(), realm, user.getId(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user