All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.edu.icm.unity.saml.sp.SAMLResponseConsumerServlet Maven / Gradle / Ivy

/*
 * Copyright (c) 2014 ICM Uniwersytet Warszawski All rights reserved.
 * See LICENCE.txt file for licensing information.
 */
package pl.edu.icm.unity.saml.sp;

import java.io.IOException;
import java.net.URISyntaxException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.hc.core5.net.URIBuilder;
import org.apache.logging.log4j.Logger;
import org.apache.xmlbeans.XmlException;

import eu.unicore.samly2.messages.RedirectedMessage;
import eu.unicore.samly2.messages.SAMLVerifiableElement;
import eu.unicore.samly2.messages.XMLExpandedMessage;
import pl.edu.icm.unity.base.utils.Log;
import pl.edu.icm.unity.engine.api.authn.remote.RemoteAuthenticationContextManagement.UnboundRelayStateException;
import pl.edu.icm.unity.engine.api.authn.remote.SharedRemoteAuthenticationContextStore;
import pl.edu.icm.unity.engine.api.utils.URIBuilderFixer;
import pl.edu.icm.unity.saml.SamlHttpResponseServlet;
import pl.edu.icm.unity.saml.SamlProperties.Binding;
import pl.edu.icm.unity.webui.authn.remote.RemoteRedirectedAuthnResponseProcessingFilter;
import xmlbeans.org.oasis.saml2.protocol.ResponseDocument;

/**
 * Custom servlet which awaits SAML authn response from IdP, which should be 
 * attached to the HTTP request.
 * 

* If the response is found it is confronted with the expected data from the SAML authentication context and * if is OK it is recorded in the context so the UI can catch up and further process the response. * * @author K. Benedyczak */ public class SAMLResponseConsumerServlet extends SamlHttpResponseServlet { private static final Logger log = Log.getLogger(Log.U_SERVER_SAML, SAMLResponseConsumerServlet.class); public static final String PATH = "/spSAMLResponseConsumer"; private final SamlContextManagement contextManagement; private final SharedRemoteAuthenticationContextStore remoteAuthnContextStore; public SAMLResponseConsumerServlet(SamlContextManagement contextManagement, SharedRemoteAuthenticationContextStore remoteAuthnContextStore) { super(true); this.contextManagement = contextManagement; this.remoteAuthnContextStore = remoteAuthnContextStore; } @Override protected void postProcessResponse(boolean isGet, HttpServletRequest req, HttpServletResponse resp, String samlResponse, String relayState) throws IOException { RemoteAuthnContext context; try { context = contextManagement.getAndRemoveAuthnContext(relayState); } catch (UnboundRelayStateException e) { log.warn("Got a request to the SAML response consumer endpoint, " + "with invalid relay state."); resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Wrong 'RelayState' value"); return; } Binding binding = isGet ? Binding.HTTP_REDIRECT : Binding.HTTP_POST; SAMLVerifiableElement verifiableMessage = isGet ? new RedirectedMessage(req.getQueryString()) : getDocumentSignedMessage(samlResponse); context.setResponse(samlResponse, binding, verifiableMessage); log.debug("SAML response for authenticator {} was stored in context, redirecting to originating endpoint {}", context.getAuthenticationStepContext().authnOptionId, context.getReturnUrl()); remoteAuthnContextStore.addAuthnContext(context); resp.sendRedirect(getRedirectWithContextIdParam(context.getReturnUrl(), relayState)); } private String getRedirectWithContextIdParam(String returnURL, String relayState) throws IOException { try { URIBuilder uriBuilder = URIBuilderFixer.newInstance(returnURL); uriBuilder.addParameter(RemoteRedirectedAuthnResponseProcessingFilter.CONTEXT_ID_HTTP_PARAMETER, relayState); return uriBuilder.build().toString(); } catch (URISyntaxException e) { throw new IOException("Can't build return URL", e); } } private XMLExpandedMessage getDocumentSignedMessage(String samlResponse) throws IOException { ResponseDocument parsedResponse = parseResponse(samlResponse); return new XMLExpandedMessage(parsedResponse, parsedResponse.getResponse()); } private ResponseDocument parseResponse(String samlResponse) throws IOException { try { return ResponseDocument.Factory.parse(samlResponse); } catch (XmlException e) { throw new IOException("The SAML response can not be parsed - XML data is corrupted", e); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy