Redirect with AuthnRequest

This article discusses singing and sending in OpenSAML 2. If you're looking for an article on OpenSAML 4, you will find it here and if you're looking for an article on OpenSAML 3, you will find it here

In this post I will show you how to start the SAML Single sign-on process by sending a authentication request using OpenSAML. The process starts with a redirect from the SP(The one wanting to authenticate someone) to the IdP(The one authenticating). To start the authentication the SP sends a SAML AuthnRequest as parameter in the redirect. The AuthnRequest message identifies the SP and can contain information about how the SP wants the user to be authenticated. Here is an example how to send the AuthnRequest using OpenSAML. The example uses the HTTPRedirectDeflateEncoder to encode, sign and redirect which makes everything way easier, especially considering encoding and signing.

 1//IPR Ergogroup AS
 2public void doAuthenticationRedirect(final HttpServletResponse response, final HttpSession currentSession, final String gotoURL, final SAMLMetaData metaData) throws IllegalArgumentException, SecurityException, IllegalAccessException {
 3  AuthnRequest authnRequest = generateAuthnRequest(metaData);
 4 
 5  SAMLUtil.logSAMLObject(authnRequest);
 6 
 7  // Save the request ID to session for future validation
 8  currentSession.setAttribute("AuthnRequestID", authnRequest.getID());
 9  currentSession.setAttribute("goto", gotoURL);
10 
11  HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(response, true);
12  BasicSAMLMessageContext<SAMLObject, AuthnRequest, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, AuthnRequest, SAMLObject>();  
13  context.setPeerEntityEndpoint(getEndpointFromMetaData());
14  context.setOutboundSAMLMessage(authnRequest);
15  context.setOutboundSAMLMessageSigningCredential(getSigningCredential());
16  context.setOutboundMessageTransport(responseAdapter);
17 
18  HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
19 
20  try {
21   encoder.encode(context);
22  } catch (MessageEncodingException e) {
23   logger.error(e.getMessage(), e);
24  }
25 }
26 
27 private AuthnRequest generateAuthnRequest(final SAMLMetaData metaData) throws IllegalArgumentException, SecurityException, IllegalAccessException {
28 
29  AuthnRequest authnRequest = SAMLUtil.buildSAMLObjectWithDefaultName(AuthnRequest.class);
30 
31  authnRequest.setForceAuthn(true);
32  authnRequest.setIsPassive(false);
33  authnRequest.setIssueInstant(new DateTime());
34  for (SingleSignOnService sss : metaData.getIdpEntityDescriptor().getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) {
35   if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
36    authnRequest.setDestination(sss.getLocation());
37   }
38  }
39  authnRequest.setProtocolBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
40 
41  String deployURL = getDeployURL();
42  if (deployURL.charAt(deployURL.length() - 1) == '/') {
43   deployURL = deployURL.substring(0, deployURL.length() - 1);
44  }
45  authnRequest.setAssertionConsumerServiceURL(deployURL + SAMLMetaData.CONSUMER_PATH);
46 
47  authnRequest.setID(SAMLUtil.getSecureRandomIdentifier());
48 
49  Issuer issuer = SAMLUtil.buildSAMLObjectWithDefaultName(Issuer.class);
50  issuer.setValue(getSPEntityId());
51  authnRequest.setIssuer(issuer);
52 
53  NameIDPolicy nameIDPolicy = SAMLUtil.buildSAMLObjectWithDefaultName(NameIDPolicy.class);
54  nameIDPolicy.setSPNameQualifier(getSPEntityId());
55  nameIDPolicy.setAllowCreate(true);
56  nameIDPolicy.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:transient");
57 
58  authnRequest.setNameIDPolicy(nameIDPolicy);
59 
60  RequestedAuthnContext requestedAuthnContext = SAMLUtil.buildSAMLObjectWithDefaultName(RequestedAuthnContext.class);
61  requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);
62 
63  AuthnContextClassRef authnContextClassRef = SAMLUtil.buildSAMLObjectWithDefaultName(AuthnContextClassRef.class);
64  authnContextClassRef.setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport");
65 
66  requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef);
67  authnRequest.setRequestedAuthnContext(requestedAuthnContext);
68 
69  return authnRequest;
70 }
Resulting AuthnRequest

 1<saml2p:authnrequest 
 2        assertionconsumerserviceurl="https://mySP.test.com/saml/consumer" 
 3        destination="http://myIDP.test.com:80/opensso/SSORedirect/metaAlias/idp" 
 4        forceauthn="true" 
 5        id="_07dfa23f929c647c0b4503e8c13a04f7" 
 6        ispassive="false" 
 7        issueinstant="2011-01-20T12:43:52.208Z" 
 8        protocolbinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" 
 9        version="2.0" 
10        xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
11    <saml2:issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
12        my-alias
13    </saml2:issuer>
14    <saml2p:nameidpolicy
15            allowcreate="true" 
16            format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" 
17            spnamequalifier="my-alias">
18        <saml2p:requestedauthncontext comparison="minimum">
19            <saml2:authncontextclassref xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
20                urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
21            </saml2:authncontextclassref>
22        </saml2p:requestedauthncontext>
23    </saml2p:nameidpolicy>
24</saml2p:authnrequest>