Skip to content

Commit

Permalink
adding POST binding for saml2 logout(MID-7132)
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed Jul 9, 2021
1 parent 1d07302 commit 361f7a7
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
import org.springframework.security.saml.provider.service.ServiceProviderService;
import org.springframework.security.saml.provider.service.config.LocalServiceProviderConfiguration;
import org.springframework.security.saml.saml2.authentication.AuthenticationRequest;
import org.springframework.security.saml.saml2.authentication.LogoutRequest;
import org.springframework.security.saml.saml2.authentication.NameIdPolicy;
import org.springframework.security.saml.saml2.metadata.IdentityProviderMetadata;
import org.springframework.security.saml.saml2.metadata.NameId;
import org.springframework.security.saml.saml2.metadata.ServiceProviderMetadata;
import org.springframework.security.saml.saml2.authentication.NameIdPrincipal;
import org.springframework.security.saml.saml2.metadata.*;

import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
Expand Down Expand Up @@ -119,9 +119,31 @@ public AuthenticationRequest authenticationRequest(IdentityProviderMetadata idp)
}
return request;
}

@Override
public LogoutRequest logoutRequest(IdentityProviderMetadata recipient, NameIdPrincipal principal) {
List<SsoProvider> ssoProviders = recipient.getSsoProviders();
return super.logoutRequest(recipient, principal).setDestination(
getPreferredEndpoint(
ssoProviders.get(0).getSingleLogoutService(),
getPreferredBinding(ssoProviders.get(0).getSingleLogoutService()),
-1
)
);
}
};
}

private Binding getPreferredBinding(List<Endpoint> singleLogoutService) {
for (Endpoint endpoint : singleLogoutService) {
if (endpoint.getBinding().equals(Binding.REDIRECT)
|| endpoint.getBinding().equals(Binding.POST)) {
return endpoint.getBinding();
}
}
return null;
}

@Override
protected String getAliasPath(LocalProviderConfiguration configuration) {
if (configuration instanceof MidpointSamlLocalServiceProviderConfiguration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,43 @@

import com.evolveum.midpoint.model.api.authentication.MidpointAuthentication;
import com.evolveum.midpoint.model.api.authentication.ModuleAuthentication;

import org.springframework.security.core.Authentication;
import org.springframework.security.saml.SamlAuthentication;
import org.springframework.security.saml.SamlException;
import org.springframework.security.saml.SamlTemplateEngine;
import org.springframework.security.saml.provider.SamlFilter;
import org.springframework.security.saml.provider.provisioning.SamlProviderProvisioning;
import org.springframework.security.saml.provider.service.ServiceProviderService;
import org.springframework.security.saml.provider.service.authentication.ServiceProviderLogoutHandler;
import org.springframework.security.saml.saml2.authentication.LogoutRequest;
import org.springframework.security.saml.saml2.authentication.NameIdPrincipal;
import org.springframework.security.saml.saml2.metadata.Binding;
import org.springframework.security.saml.saml2.metadata.IdentityProviderMetadata;
import org.springframework.security.saml.saml2.metadata.ServiceProviderMetadata;
import org.springframework.security.saml.spi.opensaml.OpenSamlVelocityEngine;
import org.springframework.web.util.HtmlUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.MediaType.TEXT_HTML_VALUE;
import static org.springframework.util.StringUtils.hasText;

/**
* @author skublik
*/
public class MidpointServiceProviderLogoutHandler extends ServiceProviderLogoutHandler {

private static final String POST_TEMPLATE = "/templates/saml2-post-binding.vm";

private SamlTemplateEngine samlTemplateEngine = new OpenSamlVelocityEngine();
private SamlProviderProvisioning<ServiceProviderService> provisioning;

public MidpointServiceProviderLogoutHandler(SamlProviderProvisioning<ServiceProviderService> provisioning) {
Expand All @@ -34,17 +57,56 @@ public SamlProviderProvisioning<ServiceProviderService> getProvisioning() {
}

protected void spInitiatedLogout(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException {
HttpServletResponse response,
Authentication authentication) throws IOException {

if (authentication instanceof MidpointAuthentication) {
ModuleAuthentication moduleAuthentication = ((MidpointAuthentication) authentication).getProcessingModuleAuthentication();
super.spInitiatedLogout(request, response, moduleAuthentication.getAuthentication());
if (moduleAuthentication.getAuthentication() instanceof SamlAuthentication) {
SamlAuthentication sa = (SamlAuthentication) moduleAuthentication.getAuthentication();
ServiceProviderService provider = provisioning.getHostedProvider();
IdentityProviderMetadata idp = provider.getRemoteProvider(sa.getAssertingEntityId());
LogoutRequest lr = provider.logoutRequest(idp, (NameIdPrincipal) sa.getSamlPrincipal());
if (lr.getDestination().getBinding().equals(Binding.REDIRECT)) {
super.spInitiatedLogout(request, response, sa);
} else if (lr.getDestination().getBinding().equals(Binding.POST)) {
processPostLogout(request, response, lr, idp, provider);
} else {
String message = "Unsupported binding for logout " + lr.getDestination().getBinding();
throw new IllegalArgumentException(message);
}
}
} else {
String message = "Unsupported type " + (authentication == null ? null : authentication.getClass().getName())
+ " of authentication for MidpointLogoutRedirectFilter, supported is only MidpointAuthentication";
throw new IllegalArgumentException(message);
}
}

private void processPostLogout(HttpServletRequest request, HttpServletResponse response,
LogoutRequest logoutRequest, IdentityProviderMetadata idp, ServiceProviderService provider) {
String encoded = provider.toEncodedXml(logoutRequest, false);
Map<String, Object> model = new HashMap<>();
model.put("action", logoutRequest.getDestination().getLocation());
model.put("SAMLRequest", encoded);
String relayState = getLogoutRelayState(request, idp);
if (hasText(relayState)) {
model.put("RelayState", HtmlUtils.htmlEscape(relayState));
}

response.setContentType(TEXT_HTML_VALUE);
response.setCharacterEncoding(UTF_8.name());
StringWriter out = new StringWriter();
samlTemplateEngine.process(
request,
POST_TEMPLATE,
model,
out
);
try {
response.getWriter().write(out.toString());
} catch (IOException e) {
throw new SamlException(e);
}
}
}

0 comments on commit 361f7a7

Please sign in to comment.