Single Sign-on to Azure AD using SimpleSAMLphp
In my last mammoth post, I posted an update/re-write to an article originally written on the Azure website that used some libraries provided by Microsoft to enable custom PHP applications to sign-on to Azure AD using WS-Federation. In that post I described a method for installing and configuring SimpleSAMLphp to IIS that enables it to be used by any number of sites on the same server, all that’s required is to add a simple Virtual Directory to each site. If you want to configure SimpleSAMLphp on IIS, check that post out.
The intention with this post is to do away with Microsoft’s libraries altogether and use only SimpleSAMLphp in a more integrated way. The purpose is to avoid having to re-write a lot of functionality already provided by SimpleSAMLphp that’s likely to be missing from Microsoft’s libraries, and of course open up access to SimpleSAMLphp’s documented API.
I will assume you have configured SimpleSAMLphp already using the method documented in the last post. In order to proceed in this post, you also need to have configured an application within Azure Active Directory. Again, you can find instructions for that included in the previous post.
The largest difference with this post is, as I mentioned, better integration with SimpleSAMLphp – as such, there’s more configuration to complete within SimpleSAMLphp than there was in the previous post.
- We’ll import federation data from our Azure application in to SimpleSAMLphp.
- We’ll configure SimpleSAMLphp as a Service Provider.
- We’ll create a little code to get us authenticating.
- As mentioned, we need SimpleSAMLphp set up on the server as per my previous post. In this post, I’ve created a new website called sso.lewisroberts.com and configured the Virtual Directory. It’s all documented in the previous post so you can use that to get to this stage.
- We need an application configured in Azure Active Directory just as per my previous post. In this post, I’ve created a new application I’ve called sso.lewisroberts.com. There’s no special configuration required for the application.
Import federation data from Azure application to SimpleSAMLphp
- Open the Windows Azure Management portal and navigate to your application. Click View Endpoints in the grey banner at the bottom.
- In the App Endpoints window. Copy the URL for the Federation Metadata Document.
- Using your favourite browser, navigate to the location and save the metadata document. How you do this doesn’t really matter, as long as it’s just the XML you save.
- Open the federationmetadata.xml file in a text editor, select the entire contents (Ctrl+A) and then copy it to the clipboard.
- Open a browser and navigate to https://sso.lewisroberts.com/simplesaml
(Actually, you’ll obviously navigate to your own PHP application’s website, not mine.) Once there, click the Federation tab.
- On the Federation tab, look for Tools and then click XML to simpleSAMLphp metadata converter.
- Paste the entire federationmetadata.xml file’s contents in to the field and click the Parse button.
- The page should return almost immediately with some information similar to the following under the Converted metadata section. Copy the contents of the saml20-idp-remote field to your clipboard, or a file, it’s your choice.
- Navigate to your SimpleSAMLphp installation folder and find the metadata folder.
- Now open the saml20-idp-remote.php file.
Did you notice? The converted metadata returned from SimpleSAMLphp had the field set to saml20-idp-remote – the same name as the file we’re editing.
- Now copy the converted metadata contents in to the file. I’ve highlighted where this was pasted in to my own version of the file. Do note however that obviously the converted metadata extends beyond the bottom of the visible screen I show here. It should be a simple matter of pasting in the converted metadata. Save the file.
Configure SimpleSAMLphp as a service provider
- Navigate to your SimpleSAMLphp installation folder and open the config folder.
- Open authsources.php in your favourite text editor.
- There are a number of authentication sources preconfigured (but commented out) however the one we’re interested in (or rather, its general format) is default-sp. I’ve shown this (actually, the interesting bits) in its default state, below.
- In order to achieve compatibility with Azure AD, we need to make some small changes to default-sp. We could just create another authsource called something else but it’s easier to show what it looks like initially and then edited if we change default-sp. The next few steps will show where we make edits.
- Firstly, change the entityID value to reflect the name or URL of your Azure application.
- Next, enter the idp value. Where did I get this from? The very first line of the converted metadata actually gives you the IdP (Identity Provider) – in this case, Azure AD.
- discoURL stays as null.
- Next we must add some additional information that is required to communicate with Azure AD. Underneath discoURL, add the following two lines.
PHP12'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent','simplesaml.nameidattribute' => 'eduPersonTargetedID',
- We’re complete editing authsources.php so save and close the file.
Now that configuration of SimpleSAMLphp is complete, we can use SimpleSAMLphp to test authentication works as expected, without actually writing any code but we’ll get to that in a second.
- Navigate to https://sso.lewisroberts.com/simplesaml (remember, your own app, not mine, this is an example.) and then click the Authentication tab.
- Once there, click Test configured authentication sources
- We should see only two options, admin and default-sp. These were the only two authentication sources defined in authsources.php. Click default-sp.
- You will likely receive an error that looks as follows. This means that the Reply URL sent by SimpleSAMLphp to Azure AD as part of the authentication attempt isn’t one that is accepted by the application. So it’s not very happy. To fix this, we need to quickly visit the Azure Management portal and add this Reply URL to our application.
- First, copy the URL from the error. In this case, the URL is: https://sso.lewisroberts.com/simplesaml/module.php/saml/sp/metadata.php/default-sp
- In the Azure Management portal, find the application, scroll to Single Sign-On and add it to the list of Reply URLs. Save the configuration change but leave the management portal open in case you must make any more edits.
- Close the other browser showing the error, open another and repeat steps 1 to 3.
After clicking on default-sp now that we have added the Reply URL in to the Windows Azure portal, we should be shown the Sign in page.
Notice the URL we’re sent to. This is the actually the SAML-P Sign On Endpoint for the Azure application.
- Log in with a user account that’s in your Azure Active Directory.
- We should now be able to sign in without error and get redirected back to SimpleSAMLphp and shown a list of the claims that were sent along with the authentication.
- To test logging out, click Logout.
Custom PHP application code
So, all this configuration was just to get us to the point where we can create our own application code that allows us to authenticate with Azure AD. The reality is that our PHP “application” can be a single page.
Generally, the application will require an index.php file – the code for which is below. I’ll give a very brief breakdown of the first few lines, the rest is obvious.
require_once (dirname(__FILE__) . '/../simplesamlphp/lib/_autoload.php');
$as = new SimpleSAML_Auth_Simple('default-sp');
$attributes = $as->getAttributes();
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<h3>Welcome <strong>Authenticated User</strong>!</h3>
// Get a logout URL
$url = $as->getLogoutURL();
echo '<a href="' . htmlspecialchars($url) . '">Logout</a>';
This file will require authentication so, on line 2, it calls SimpleSAMLphp’s autoloader from the main installation of SimpleSAMLphp.
On line 3, we create a new object from the SimpleSAML_Auth_Simple class but notice here we specify the authsource default-sp – that’s correct, we’re associating this application with the default-sp auth source we created.
On line 4, we use the object and tell it we require authentication. If the user is authenticated, the script will proceed to the next line, if not however, they will begin the authentication process and be redirected to Azure AD to sign in. Once signed in, they will be redirected back to this page.
On line 6, we pull the attributes from the SAML token and store them in the $attributes array. These are then used later (line 21) to show the user their claims.
On line 25 we get a logout URL from the $as object and send that back to the interface so the user can click a link to log out.
- The user navigates to the web application. Given they’re not logged in, they’re automatically redirected to the Azure AD sign in page.
- The user lands at the Azure AD sign in page.
- The user logs in with a valid Azure AD account.
Notice as well that the page also says sso.lewisroberts.com – a bit of free branding.
- After successfully authenticating, the user is redirected back to the site where they can see their claims and a logout link.
- When clicking the Logout link, the user is logged out of their account.
A little something extra?
One thing I’ve wondered while doing all this was whether we could get additional claims through rather than just those few that are shown in the screenshots. Something like groups would be great. As it turns out, that feature was introduced at the back end of 2014. I’ll run through it very quickly in the context of our application but for more details (and how to handle users who might be members of more than 150 groups (in SAML)) you really should visit the blog of Dushyant Gill.
- In the Windows Azure management portal, navigate to your application and click Manage Manifest then Download Manifest.
- Download the manifest file and save it to disk. Leave the portal open, you’ll need it shortly.
- Open the file in any decent text editor. I’ve chosen to do it in Visual Studio code. Locate the groupMembershipClaims value.
Change this to one of SecurityGroup or All.
- SecurityGroup – The groups claim will contain the identifiers of all security groups that the user is a member of.
- All – The groups claim will contain the identifiers of all security groups and distribution lists that the user is a member of.
- I’ve chosen to just enable SecurityGroup option in the screenshot below. Save the file.
- Back on the portal site, Manage Manifest and then click Upload Manifest.
- Browse for the saved file and then click the tick icon to upload it.
- Dushyant’s post goes on to mention that you should grant additional permissions in the application. This is only really required if you are going to be dealing with “overage” scenarios which means users who are members of more than 150 groups, since these can’t be included in the SAML token. Read his blog post for more info. For our demo app purposes, our user is a member of only one group.
- So, I’ve created a group in my Azure AD and added the user to it. Note the Object ID, this is the value that will be shown in the claim.
- Now if we re-try our authentication (and without making any code changes to our index.php file) we see that the groups claim is carried through in to the application. Of course this means you can use it for security trimming etc. within your custom app.
Note: I noticed that there was another group id in the claim – I’m assuming this is related to this user’s status as a Global Administrator since if I authenticate as a user who is purely a member of the LocalAzureAD group, the only groups claim attribute is the Object ID of the LocalAzureAD group.
So, another not insignificant post ends and hopefully you’ve learned a little something along the way. Seeing that it’s possible to pull group claims through in to the application opens a lot of possibilities for developers of bespoke PHP applications and I’m sure it’ll be very handy to know in the future.
I think I’ve got one more post in me about SimpleSAMLphp and that is probably going to be integrating SimpleSAMLphp with ADFS 2012R2. That post will hopefully be shorter since we’ll be repeating a lot of the activities we’ve done above. For example, instead of importing the federation metadata from our Azure Application, we’ll import from the ADFS server and set that up in SimpleSAMLphp. We’ll configure our PHP “application” as a Relying Party Trust and get all the necessary information automatically from simpleSAMLphp and finally configure the ADFS server as the IdP for the application.
Until next time – probably tomorrow.