package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; import java.io.ByteArrayInputStream; import java.io.InputStream; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import org.opensaml.messaging.decoder.MessageDecodingException; import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder; import com.google.common.base.Strings; import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.codec.Base64Support; /** * SAML2 Post-Binding decoder with same EAAF specific hardening regarding http * request-parameter processing. * * @author tlenz * */ @Slf4j public class EaafHttpPostDecoder extends HTTPPostDecoder { @Override protected InputStream getBase64DecodedMessage(final HttpServletRequest request) throws MessageDecodingException { log.debug("Getting Base64 encoded message from request"); String encodedMessage = getLastParameterFromRequest(request, "SAMLRequest"); if (Strings.isNullOrEmpty(encodedMessage)) { encodedMessage = getLastParameterFromRequest(request, "SAMLResponse"); } if (Strings.isNullOrEmpty(encodedMessage)) { log.info("Request did not contain either a SAMLRequest or " + "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding."); throw new MessageDecodingException("No SAML message present in request"); } log.trace("Base64 decoding SAML message:\n{}", encodedMessage); final byte[] decodedBytes = Base64Support.decode(encodedMessage); if (decodedBytes == null) { log.info("Unable to Base64 decode SAML message"); throw new MessageDecodingException("Unable to Base64 decode SAML message"); } log.trace("Decoded SAML message:\n{}", new String(decodedBytes)); return new ByteArrayInputStream(decodedBytes); } /** * Always read the last parameter with this name from request to get a strict deterministic behavior. *

* If more than one parameters with the same name exists, * this method always select the last parameter value. * * @param request Incoming http request * @param paramName Name of the http parameter * @return the last parameter value with this name, or null if the parameter not exists */ @Nullable private String getLastParameterFromRequest(@Nonnull HttpServletRequest request, @Nonnull String paramName) { final String[] values = request.getParameterValues(paramName); if (values != null && values.length > 0) { return values[values.length - 1]; } return null; } }