Using HTTP POST binding in OpenSAML 4
SAML messages can be sent using different methods, called bindings. There are four main standard bindings being used today, HTTP Redirect, HTTP POST, HTTP Artifact and SOAP.
This tutorial will walk you through how to send a message, specifically a authentication request, using HTTP POST in OpenSAML.
The HTTP POST binding
The Redirect binding explained here is a popular method of sending messages which relies on HTTP Redirects. A problem with the redirect binding is that the message is send inside URL parameters and URL parameters can not hold large amounts of data. This makes it suitable for SAML authentication request, which is quite small, but less suitable for large messages like SAML responses. The POST binding gives a solution to this.
The HTTP POST binding uses input fields in a HTML form to send SAML messages.
- When the SP or IdP want to send a message it responds to the current user with a HTML page with the SAML message encoded in a input field in a form.
- When the browser receives the HTML page a JavaScript or meta tag makes the browser automatically submit the form to the recipient of the message .
- When the user arrives with its submitted form at the receiver of the message, the receiver will pick the message from the request parameters and parse the message.
The HTML form explained
A typical POST binding HTML page look like this.
1<html>
2 <head>
3 <meta charset="utf-8" />
4 </head>
5 <body onload="document.forms[0].submit()">
6 <noscript>
7 <p>
8 <strong>Note:</strong> Since your browser does not support JavaScript,
9 you must press the Continue button once to proceed.
10 </p>
11 </noscript>
12 <form action="http://localhost:8080/opensaml-http-post/receiverPage" method="post">
13 <div>
14<input type="hidden" name="RelayState" value="teststate"/>
15<input type="hidden" name="SAMLRequest" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJUaGUgc2hvdWxkIGJlIHRoZSBlbmRwb2ludCB0aGF0IHNob3VsZCByZWNpZXZlIHRoZSByZXN1bHQgb2YgdGhlIGF1dGhlbnRpY2F0aW9uIiBEZXN0aW5hdGlvbj0iaHR0cDovL2xvY2FsaG9zdDo4MDgwL29wZW5zYW1sLWh0dHAtcG9zdC9yZWNlaXZlclBhZ2UiIElEPSJfODczNjcwZDBlNmZiYTI0MDkzOWIwYjQ5OTJiOGRlMzEiIElzc3VlSW5zdGFudD0iMjAyMS0xMC0xNlQxODo0OTowOC4wODBaIiBQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpiaW5kaW5nczpIVFRQLUFydGlmYWN0IiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPlRoaXMgc2hvdWxkIGJlIHRoZSBzZW5kZXIgZW50aXR5SWQ8L3NhbWwyOklzc3Vlcj48c2FtbDJwOk5hbWVJRFBvbGljeSBBbGxvd0NyZWF0ZT0idHJ1ZSIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiLz48L3NhbWwycDpBdXRoblJlcXVlc3Q+"/>
16 </div>
17 <noscript>
18 <div>
19 <input type="submit" value="Continue"/>
20 </div>
21 </noscript>
22 </form>
23 </body>
24</html>
There are two fields used in this binding
- SAMLRequest/SAMResponse - The encoded, unsigned message
- RelayState - The relay state, sent in the original request and send back in the response
Sending a message using OpenSAML 4
Because this binding is creating a webpage, OpenSAML uses Apache Velocity. The velocity library must be included in the Maven Pom. If not you will get the following errror
1java.lang.RuntimeException: net.shibboleth.utilities.java.support.component.ComponentInitializationException: VelocityEngine must be supplied
Add this to pom.xml
1<dependency>
2 <groupId>org.apache.velocity</groupId>
3 <artifactId>velocity-engine-core</artifactId>
4 <version>${velocity.version}</version>
5</dependency>
Creating message contexts to set the message, relay state and receiving end point. Creating Velocity engine to handle web site creation.
1MessageContext context = new MessageContext();
2
3context.setMessage(authnRequest);
4
5SAMLBindingContext bindingContext = context.getSubcontext(SAMLBindingContext.class, true);
6bindingContext.setRelayState("teststate");
7
8SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
9
10SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
11endpointContext.setEndpoint(URLToEndpoint(MESSAGE_RECEIVER_ENDPOINT));
12
13VelocityEngine velocityEngine = new VelocityEngine();
14velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
15velocityEngine.setProperty("classpath.resource.loader.class",
16 "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
17velocityEngine.init();
1HTTPPostEncoder encoder = new HTTPPostEncoder();
2
3encoder.setMessageContext(context);
4encoder.setHttpServletResponse(httpServletResponse);
5encoder.setVelocityEngine(velocityEngine);
6
7encoder.initialize();
8encoder.encode();
Receiving a message using OpenSAML 4
Using HTTPPostDecoder to decode the received message from the HTTPServletRequest
1HTTPPostDecoder decoder = new HTTPPostDecoder();
2decoder.setHttpServletRequest(req);
3
4decoder.initialize();
5decoder.decode();
6
7MessageContext messageContext = decoder.getMessageContext();
8authnRequest = (AuthnRequest) messageContext.getMessage();
Get it on Github!
The full running sample is available on Github at https://github.com/rasmusson/OpenSAML-sample-code under opensaml-http-post
Just clone it, run it, go nuts!
1git clone https://github.com/rasmusson/OpenSAML-sample-code/
2cd opensaml-http-post
3mvn tomcat:run
All messages are printed in the console
Browse to http://localhost:8080/opensaml-http-post/postPage
Summary
In this post we have looked at.
- The basics of the HTTP Post binding
- Sending a message using OpenSAML 4
- Receiving a message using OpenSAML 4