Simple Shibboleth ECP test

Update: I’ve published an even easier way to test ECP on GitHub at https://github.com/unikent-ms1/simple-soap-ecp-test

Shibboleth (well, SAML2 via Shibboleth) provides a mechanism for non-browser clients to go through an Authentication/Authorisation (AuthNZ) directly with a Service Provider (SP) by making a SOAP callback to a trusted Identity Provider (IdP) on behalf of the client. This mechanism is called Enhanced Client or Proxy (ECP).

While attempting to get this enabled and working, it became apparent that there is very little in the way of test-rigs for this mechanism… so I came up with a simple (bodgy) method and then, later, wrote a JMeter rig to test it more extensively.

Note: the method described here only covers the “Basic Auth” method of using ECP. There are others of which I have, thus far, no experience.

At a very basic level, an ECP callback is just an HTTP SOAP request with some HTTP Basic Auth credentials included. I crafted a SAML2 AuthN request, wrapped it in the appropriate SOAP glue and sent it to the web server hosting the ECP endpoint using curl.

Save the below XML document to a text file and replace the bits marked with double-underscores as follows:

  • __RANDOM_STRING__: This can be literally anything so long as it’s unique between requests. I started off with an MD5 of a file and manually incremented the last character each time I used it
  • __AssertionConsumerServiceURL__: This is the URL specified in the metadata of the SP you’re impersonating for the AssertionConsumerService attribute with binding urn:oasis:names:tc:SAML:2.0:bindings:PAOS
  • IssueInstant: This is the current time. It’s up to the IdP to check this but set it to something within a few minutes of now in the format I’ve used and it should be ok. Just remember to keep it close to now :)If using JMeter then Charles Tompkins of University of Florida suggests using the following macro:
    ${__javaScript(var z=new Date(); $DATE=z.toISOString();,DATE)}
  • __REMOTE_ENTITYID__: This is the EntityID of the SP you’re impersonating
<SOAP-ENV:Envelope 
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ecp="urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp">
    <SOAP-ENV:Header>
     </SOAP-ENV:Header>
     <SOAP-ENV:Body> 
        <samlp:AuthnRequest
		ID="__RANDOM_STRING__" 
		ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS"
		AssertionConsumerServiceURL="__AssertionConsumerServiceURL__"
		IssueInstant="__2013-01-01T00:00:00Z__"
		Version="2.0"
	>
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		__REMOTE_ENTITYID__
	</saml:Issuer>
	<samlp:NameIDPolicy AllowCreate="1"/>
	</samlp:AuthnRequest>       
     </SOAP-ENV:Body> 
</SOAP-ENV:Envelope>

Save that as something like soap.xml and proceed to curl

Invoking curl in such a way that this works takes a little effort:

curl -k \
  -d @soap.xml \
  -H "Content-Type: application/vnd.paos+xml" \
  --basic -u user:password \
  https://idp.example.com/idp/profile/SAML2/SOAP/ECP \
  | xmllint --pretty 1 -

If you’ve got the URL and credentials correct then should get some sort of XML response back (I’ve found that it’s a lot more readable if you pass it through xmllint to pretify it). Hopefully this will be a Response object but may be an error.

You can add “--trace-ascii -” to the curl command to get a more verbose output of what’s going on.

Remember to change the ID attribute each time you use it and keep an eye on the IssueInstant – if it’s more than a few minutes off then it’ll probably get rejected.

For more information about the guts of ECP (and SAML2 more generally) see the specification

3 responses to “Simple Shibboleth ECP test

  1. Hi Peter,

    Sorry for the lack of reply. As far as I know it’s still valid — our config hasn’t changed and is definitely still receiving a Basic Auth headers (Apache is processing them and our Shib wouldn’t know how to) however I can’t actually see the raw packets easily.

    Are you still having issues?

  2. Hi,

    is this information still up-to-date? If I configure our Office 365 domain with “ActiveLogOnUri” set to our ECP endpoint (https://ouridp/idp/profile/SAML2/SOAP/ECP), we get requests sent to this URI like this:
    POST /idp/profile/SAML2/SOAP/ECP HTTP/1.0
    Connection: Keep-Alive
    Content-Type: application/soap+xml
    Accept: */*
    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.1; …..
    Content-Length: 1592
    Host: ouridp

    http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
    https://ouridp:443/idp/profile/SAML2/SOAP/ECP
    MYREQUESTID

    a-username@ourfederateddomain
    thepassword

    2014-12-05T12:55:44Z
    2014-12-05T12:55:44Z

    http://schemas.xmlsoap.org/ws/2005/02/trust/Issue

    urn:federation:MicrosoftOnline

    http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey

    Nothing of an “Authorization” header with the Basic Auth data, but username + password as a soap header ().

    Is there a setting which enables sending the Basic Auth headers?

    Thank you very much in advance!

Leave a Reply