What a seductive title, right?
Yeah, I agree. Federated authentication isn’t exactly a ripping yarn, but it is quite handy and offers excellent opportunities to leverage user authentication to a centralized repository. If you are looking for a quick turnkey solution for your WordPress Blog, however, you won’t find one. In fact, most of the documentation available surrounding SAML is either tailored to another language or dense enough to cure the stubbornest insomniac.
Before we launch into the how-tos, let’s start of with an SAML primer.
What is SAML?
Security Assertion Markup Language (SAML) is an open, standardized markup container to transmit authentication and authorization information between two parties. In short, it allows a user to access services within a particular provider when that provider may not even house the security checking mechanism to confirm that the user is allowed to access that resource.
SAML documents make use of some specific terms to identify persons and resources, the main ones revolve around three linked parties:
- The Principal – This is the person or process attempting to gain access to a thing. Usually a person trying to click a link.
- The Service Provider (SP) – This is the keeper of the stuff. The resource, server, datastore, etc who houses all the neat things that one must authenticate to access.
- The Identity Provider (IdP) – This is the keeper of the keys. The resource, server, etc. who houses (and verifies) login information.
Keep in mind that this is a greatly simplified glossary. SAML has the ability do and be much more than what is described above.
The upshot of all this is that it allows for Single Sign On for your website.
Let’s say you’d like to allow your users (Principals) to access a 3rd party service or resource (SPs) from your site (IdP). Well, SAML is designed to fulfill just that role. Configuration can be somewhat of a nightmare as the checking requires a detailed process of sending and receiving signed XML envelopes. It also requires you to have established some pre-configuration steps with whichever service provider you are linking to. However, once set up, it makes the user experience a delightfully seamless process.
The chart here shows the basic SAML process. In a nutshell, A Principal clicks a link owned by an SP, which then identifies the IdP and asks the IdP “who is this guy trying to access our stuff?” The IdP says “It’s cool man, he’s with me” and the Principal is directed to the resource.
Setting up SAML
The Service Provider you are attempting to link up to will need from you a URL that they can touch that will process their authentication request. Through that URL the SP will send you RelayState and SAMLrequest that you will need to parse and decode. Usually that means trying this:
$decoded_request = new SimpleXMLElement(gzinflate(base64_decode(rawurldecode($_GET['SAMLrequest']))));
Send a nicely formed XML document back to the SP in the standard SAML envelope format. It usually looks like this:
<?xml version="1.0" encoding="UTF-8" ?> <samp:Response xmlns:samp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" ID="'.$id.'" IssueInstant="'.$date.'" Version="2.0"> <samp:Status><samp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samp:Status> <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="An id sent to you by the SP" IssueInstant="The date"> <saml:Issuer>You, or specifically the IdP</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameidformat:persistent">User's Id</saml:NameID> </saml:Subject> <saml:Conditions NotBefore="Token is not valid before this date" NotOnOrAfter="Or after this date" > <saml:AudienceRestriction><saml:Audience>Usually the SP</saml:Audience></saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="The Date"><AuthnContext xmlns=""> <AAuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AAuthnContextClassRef> </AuthnContext></saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="firstname"> <saml:AttributeValue>Users First name (not required)</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="lastname"> <saml:AttributeValue>Users Last name (not required)</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="email"> <saml:AttributeValue>User's Email (not required)</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </Assertion> </samp:Response>
You’ll see two pieces here that may be of interest: The AuthContext node which lets the SP know how the user was authenticated on our end. Many variations exist. Consult the OASIS Spec Documentation for more info. Also notice the AttributeStatement node, which submits some extra info to the SP. This may or may not be requested from your SP, but it is a nice bonus to send this info over to automatically populate the SPs site. When the user clicks over they see clearly they have logged in as the SP knows who they are.
IMPORTANT: The xml envelope above must be digitally signed in most cases. That means, yes, you must have a security certificate available for processing and must send that certificate key along with this XML. Leave the heavy lifting of appending the security signature to XMLSecLibs – an immensely handy little PHP security library.
It may be cumbersome to set up, but in the end federated authentication is a great way to offer your users access to great third party products without burdening them with password fatigue or useability nightmares of saving multiple authentication records. Give it a try.