1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.saml2.binding.decoding;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.InputStream;
21
22 import org.opensaml.common.SAMLObject;
23 import org.opensaml.common.binding.SAMLMessageContext;
24 import org.opensaml.common.xml.SAMLConstants;
25 import org.opensaml.ws.message.MessageContext;
26 import org.opensaml.ws.message.decoder.MessageDecodingException;
27 import org.opensaml.ws.transport.http.HTTPInTransport;
28 import org.opensaml.xml.parse.ParserPool;
29 import org.opensaml.xml.util.Base64;
30 import org.opensaml.xml.util.DatatypeHelper;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34
35 public class HTTPPostDecoder extends BaseSAML2MessageDecoder {
36
37
38 private final Logger log = LoggerFactory.getLogger(HTTPPostDecoder.class);
39
40
41 public HTTPPostDecoder() {
42 super();
43 }
44
45
46
47
48
49
50 public HTTPPostDecoder(ParserPool pool) {
51 super(pool);
52 }
53
54
55 public String getBindingURI() {
56 return SAMLConstants.SAML2_POST_BINDING_URI;
57 }
58
59
60 protected boolean isIntendedDestinationEndpointURIRequired(SAMLMessageContext samlMsgCtx) {
61 return isMessageSigned(samlMsgCtx);
62 }
63
64
65 protected void doDecode(MessageContext messageContext) throws MessageDecodingException {
66 if (!(messageContext instanceof SAMLMessageContext)) {
67 log.error("Invalid message context type, this decoder only support SAMLMessageContext");
68 throw new MessageDecodingException(
69 "Invalid message context type, this decoder only support SAMLMessageContext");
70 }
71
72 if (!(messageContext.getInboundMessageTransport() instanceof HTTPInTransport)) {
73 log.error("Invalid inbound message transport type, this decoder only support HTTPInTransport");
74 throw new MessageDecodingException(
75 "Invalid inbound message transport type, this decoder only support HTTPInTransport");
76 }
77
78 SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
79
80 HTTPInTransport inTransport = (HTTPInTransport) samlMsgCtx.getInboundMessageTransport();
81 if (!inTransport.getHTTPMethod().equalsIgnoreCase("POST")) {
82 throw new MessageDecodingException("This message deocoder only supports the HTTP POST method");
83 }
84
85 String relayState = inTransport.getParameterValue("RelayState");
86 samlMsgCtx.setRelayState(relayState);
87 log.debug("Decoded SAML relay state of: {}", relayState);
88
89 InputStream base64DecodedMessage = getBase64DecodedMessage(inTransport);
90 SAMLObject inboundMessage = (SAMLObject) unmarshallMessage(base64DecodedMessage);
91 samlMsgCtx.setInboundMessage(inboundMessage);
92 samlMsgCtx.setInboundSAMLMessage(inboundMessage);
93 log.debug("Decoded SAML message");
94
95 populateMessageContext(samlMsgCtx);
96 }
97
98
99
100
101
102
103
104
105
106
107 protected InputStream getBase64DecodedMessage(HTTPInTransport transport) throws MessageDecodingException {
108 log.debug("Getting Base64 encoded message from request");
109 String encodedMessage = transport.getParameterValue("SAMLRequest");
110 if (DatatypeHelper.isEmpty(encodedMessage)) {
111 encodedMessage = transport.getParameterValue("SAMLResponse");
112 }
113
114 if (DatatypeHelper.isEmpty(encodedMessage)) {
115 log.error("Request did not contain either a SAMLRequest or "
116 + "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding.");
117 throw new MessageDecodingException("No SAML message present in request");
118 }
119
120 log.trace("Base64 decoding SAML message:\n{}", encodedMessage);
121 byte[] decodedBytes = Base64.decode(encodedMessage);
122 if(decodedBytes == null){
123 log.error("Unable to Base64 decode SAML message");
124 throw new MessageDecodingException("Unable to Base64 decode SAML message");
125 }
126
127 log.trace("Decoded SAML message:\n{}", new String(decodedBytes));
128 return new ByteArrayInputStream(decodedBytes);
129 }
130 }