Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ELY-892 Invalidate sso session only from node that started logout #636

Merged
merged 1 commit into from Jan 23, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -28,6 +28,7 @@
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -107,55 +108,66 @@ public void put(SecurityIdentity identity) {

scope.registerForNotification(notification -> {
HttpScope sessionScope = notification.getScope(Scope.SESSION);
boolean invalidating = sessionScope.getAttachment(SESSION_INVALIDATING_ATTRIBUTE) != null;

Collection<Map.Entry<String, URI>> logoutTargets = Collections.emptyList();
try (SingleSignOn target = this.context.getSingleSignOnManagerManager().find(id)) {
if (target != null) {
Map.Entry<String, URI> localParticipant = target.removeParticipant(applicationId);
if (localParticipant != null) {
log.debugf("Removed local session [%s] from SSO [%s]", localParticipant.getKey(), target.getId());
}
if (sessionScope.getAttachment(SESSION_INVALIDATING_ATTRIBUTE) == null) {
Collection<Map.Entry<String, URI>> participants = target.getParticipants();
if (participants.isEmpty()) {
log.debugf("Destroying SSO [%s]. SSO is not associated with participants", target.getId());
target.invalidate();
} else if (notification.isOfType(INVALIDATED)) {
logoutTargets = participants;
}
}
}
}

if (!logoutTargets.isEmpty()) {
logoutTargets.forEach(participant -> {
String remoteSessionId = participant.getKey();
URI remoteURI = participant.getValue();
try {
URL participantUrl = remoteURI.toURL();
HttpURLConnection connection = (HttpURLConnection) participantUrl.openConnection();
this.context.configureLogoutConnection(connection);

connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setAllowUserInteraction(false);
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

StringBuilder parameterBuilder = new StringBuilder();

parameterBuilder.append(LOGOUT_REQUEST_PARAMETER).append("=").append(this.context.createLogoutParameter(remoteSessionId));

connection.setRequestProperty("Content-Length", Integer.toString(parameterBuilder.length()));

try (
OutputStream outputStream = connection.getOutputStream();
DataOutputStream wr = new DataOutputStream(outputStream);
) {
wr.writeBytes(parameterBuilder.toString());
}

connection.getInputStream().close();
} catch (Exception cause) {
log.warnHttpMechSsoFailedLogoutParticipant(remoteURI.toString(), cause);
}
});

Collection<Map.Entry<String, URI>> participants = target.getParticipants();
if (participants.isEmpty()) {
log.debugf("Destroying SSO [%s]. SSO is not associated with participants", target.getId());
target.invalidate();
} else {
if (notification.isOfType(INVALIDATED) && !invalidating) {
// If session was invalidated, logout remote participants
participants.forEach(participant -> {
String remoteSessionId = participant.getKey();
URI remoteURI = participant.getValue();
try {
URL participantUrl = remoteURI.toURL();
HttpURLConnection connection = (HttpURLConnection) participantUrl.openConnection();
this.context.configureLogoutConnection(connection);

connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setAllowUserInteraction(false);
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

StringBuilder parameterBuilder = new StringBuilder();

parameterBuilder.append(LOGOUT_REQUEST_PARAMETER).append("=").append(this.context.createLogoutParameter(remoteSessionId));

connection.setRequestProperty("Content-Length", Integer.toString(parameterBuilder.length()));

try (
OutputStream outputStream = connection.getOutputStream();
DataOutputStream wr = new DataOutputStream(outputStream);
) {
wr.writeBytes(parameterBuilder.toString());
}

connection.getInputStream().close();
} catch (Exception cause) {
log.warnHttpMechSsoFailedLogoutParticipant(remoteURI.toString(), cause);
}
});
try (SingleSignOn target = this.context.getSingleSignOnManagerManager().find(id)) {
if (target != null) {
// If all logout requests were successful, then there should be no participants, and we can invalidate the SSO
if (target.getParticipants().isEmpty()) {
log.debugf("Destroying SSO [%s]. SSO is no longer associated with any participants", target.getId());
target.invalidate();
}
}
Expand Down