OpenAM as an identity provider for Office 365 (WSFed)

This post will run through the step necessary to configure OpenAM 13.5 to be an identity provider for Office 365 and Azure using WS-Federation.

One of the new features in OpenAM 13.5 is support for WS-Federation Active Requestor Profile.  This will enable OpenAM to support a greater range of Office 365 rich clients and Azure authentication scenarios when acting as an IDP.

Why WS-Federation?

 Office 365 and Azure support WS-Federation, SAML2 and in some cases OpenID Connect for integration with third party identity providers. While SAML2 (specifically SAML2 ECP) can be used for federation, it is only supported in newer Microsoft rich clients. WS-Federation must be used to support slightly older products such as Lync, Outlook 2011 (Mac) and Office 2010 (Windows). In particular, to support Lync and support adding an email account in Outlook 2010/2011, WS-Federation active requestor profile must be enabled.

What Works

 Using my completely informal testing procedure on my two laptops, an iPad and a Nexus tablet – I’ve managed to get the following results with the configuration below.

platform test result
MacOS 10.11.5 Office 2011 Office setup from Word ok
Lync for Mac 2011 SignIn ok
Outlook 2011 E-Mail account setup & signin ok
Office 2011 Document Connection ok
Office 2016 SignIn ok
Chrome web Sign In ok
Safari Web Sign In ok
Windows 8.1 Office 2013 CTR Setup ok
Skype For Business Sign In ok
Outlook 2013 E-Mail account setup ok
OneDrive SignIn ok
IE web Sign In ok
FireFox web SIgn In ok
Chrome web Sign In ok
Apple iPad IOS 9.3.5 Microsoft Word SignIn ok
Skype For Business Sign In ok
Outlook E-Mail account setup ok
OneDrive for business Sign In ok
Safari Web Sign In ok
Apple Mail, contacts, calendar Account setup & signin ok
Nexus Tablet Android 5.3 Microsoft Word SignIn ok
Outlook E-Mail account setup ok
OneDrive for business Sign In ok
Chrome web Sign In ok
Gmail, calendar, contacts, device management ok
Skype For Business Sign In ok

Overview of the steps

I’ll go through everything that is needed to configure OpenAM 13.5 to work with Office 365.
  1. Configuring a DNS zone for Office 365.
  2. Setting up the required DNS records for that zone.
  3. Making sure that the active directory domain is properly configured with the right UPN suffixes for the user accounts.
  4. Setting up Windows Desktop SSO (Integrated Windows Authentication) to work with OpenAM.
  5. Using PowerShell to configure Office365 to use an external identity provider.
  6. Setting up OpenAM with the WS-Federation entities for Office 365.
  7. Setting up an account in Office365 and setting it to “federated” mode.

Configuration Overview

In this configuration, our public DNS zone is test365.forgepoc.com and we’ll have users with the email address something@test365.forgepoc.com. They’ll have accounts in an internal Active Directory domain. In common with best practice for Active Directory, the DNS zone of the AD domain in this exercise uses a subdomain of the public DNS zone, test365corp.test365.forgepoc.com.

You don’t need Active Directory to make this work, you could use any database such as OpenDJ. But as Office 365 is typically used on Windows desktops in an Active Directory domain, I’m using it here.

The reverse proxy will be configured with a public trusted SSL certificate (required for WS-Federation active requestor profile to work with Office 365) and act as an SSL termination point for OpenAM. The host will be called login.test365.forgepoc.com.

You don’t need a proxy in order to use OpenAM as an IDP for Office 365, but it is highly recommended.

Requirements

  1. A Windows Active Directory domain (see my blog post on setting up one of these).
  2. An OpenAM instance on any supported operating system, configured to use Active Directory for authentication and profile attributes (see my blog post here on setting up and active directory dataStore). OpenAM should be setup with SSL internally.
  3. A reverse proxy in between OpenAM and the internet, capable of supporting SSL termination (I’m using NginX).
  4. A Windows Active Directory domain configured with network connectivity to the OpenAM instance.
  5. A business Office 365 subscription capable of federating with third party identity providers. in this example, I used a business premium subscription.
  6. An SSL certificate issued from a public trusted certificate authority such as goddaddy.
  7. A public DNS zone which you can configure with the DNS records required for use with Office 365.
  8. Windows machines and devices for testing.
Note: Currently WSFed Active Requestor profile is only supported in the top level realm in OpenAM. There is an open issue for this here. Alternatively you can set up OpenAM to federate with office 365 using SAML2 ECP, but this only works with newer MS rich clients.

Configuring a DNS zone for Office 365

Microsoft make this extremely easy using the admin section of the Office 365 dashboard. Here I’m choosing to set this up myself because I already own the domain forgepoc.com and I have other stuff on it. However, it is much easier to allow Office 365 to act as your DNS service. Doing so automatically configures the required DNS records.To do it the manual way, log in to your Office 365 subscription and select the admin center:

From the left hand menu select settings > Domains.
Click “add a domain” and enter your domain name.

In common with obtaining SSL certificates, you have to verify ownership of your DNS domain by adding a specific TXT record to it.

Now add the required DNS records. It’s important that these are accurate, but luckily Microsoft provide a test tool to verify they are set correctly. Here is a screenshot of the records for my DNS Zone test365.forgepoc.com from my DNS provider:

CNAME Records
Host Name               Points To    
lyncdiscover            webdir.online.lync.com    
msoid                   clientconfig.microsoftonline-p.net    
sip                     sipdir.online.lync.com    
enterpriseregistration  enterpriseregistration.windows.net    
enterpriseenrollment    enterpriseenrollment.manage.microsoft.com    
autodiscover            autodiscover.outlook.com    

MX Records                
Host Name               Points To                                           Priority    
@                       test365-forgepoc-com.mail.protection.outlook.com    0    

SRV Records
Host Name               Points To                                           Port    Weight    Priority    
_sip._tls               sipdir.online.lync.com                              443     1        100    
_sipfederationtls._tcp  sipfed.online.lync.com                              5061    1        100    

TXT Records
Host Name               Value    
@                       v=spf1 include:spf.protection.outlook.com -all

Configuring your proxy

A proxy is not required to get Office 365 up and running with OpenAM, but it is recommended. You’ll need some sort of proxy configuration if you plan to use multiple OpenAM servers in a HA deployment behind a load balancer.

For WSFED to work correctly behind a proxy, we need to set the host header on the proxy. Here is my NginX site configuration:

 

location / {
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host;
    proxy_pass https://login.test365corp.o365.forgepoc.com:8443;
    proxy_redirect default;
}
In the apache web server, you can achieve the same thing by setting the proxy_pass, proxy_pass reverse and ProxyPreserveHost directives.
<VirtualHost *:443>
    ServerName login.test365.forgepoc.com:443
 ProxyRequests off
 ProxyPass / https://login.test365corp.test365.forgepoc.com:8443/
 ProxyPassReverse / https://login.test365corp.test365.forgepoc.com:8443/
 ProxyPreserveHost On

    ...

</VirtualHost>

Configuring Active Directory UPN suffixes – optional, but recommended

If you have an existing Active Directory domain then it is likely that this will be configured already and you can skip this section. However, if you’ve set up an AD domain to do some basic tests and integration work, then read on.

Let’s say I make a user in active directory for Charlie Brown. I use the wizard in Active Directory users and computers and give him first name Charlie, last name Brown, username charlie.brown. Charlie will then be able to put in any of the following into the username prompt when logging on to a domain joined machine:

  • samAccountName: charlie.brown
  • cn: charlie brown
  • dn: CN=charlie brown,OU=user accounts,OU=test365corp,DC=test365corp,DC=o365,DC=forgepoc,DC=com
  • UPN: charlie.brown@test365corp.test365.forgepoc.com

Active Directory has a concept of user principal names (UPN) – a means of allowing a user account to be referenced by an email address style username that can have a different domain part to the DNS domain of the active directory domain. A UPN consists of the samAccountName and a DNS domain specified by an administrator.

Now let’s say mike wants to log on to his laptop with his email address, charlie.brown@test365.forgepoc.com. To do that, the Windows sysadmin needs to define an additional UPN suffix in the domain.

In office 365, if users authenticate to services directly with office 365 (WSFed active profile) then the user has to authenticate with their UPN. Therefore it makes sense to set the user’s active directory UPN to be the same as their office 365 UPN, which would normally be their email address. That way, users only need to remember one username.

In this example, we’ll configure a UPN suffix for the external DNS domain test365.forgepoc.com. Open Active Directory Domains and Trusts (domain.msc) and right click on the root node in the left pane:

Add the UPN suffix:

Quickstart OpenAM configuration using ssoadm batch commands

If you know OpenAM well, here are some ssoadm batch commands that will get you setup quickly. Use the metadata files from below and skip the remaining sections on configuring OpenAM.
create-datastore -e / -m ActiveDirectory -t LDAPv3ForAD -a "sun-idrepo-ldapv3-config-ldap-server=svr1.test365corp.test365.forgepoc.com:636" "sun-idrepo-ldapv3-config-authid=CN=ldapUser,CN=Users,DC=test365corp,DC=test365,DC=forgepoc,DC=com" "sun-idrepo-ldapv3-config-authpw=SOMEPASSWORD" "sun-idrepo-ldapv3-config-connection-mode=LDAPS" "sun-idrepo-ldapv3-config-organization_name=DC=test365corp,DC=test365,DC=forgepoc,DC=com" "sun-idrepo-ldapv3-config-people-container-name=ou" "sun-idrepo-ldapv3-config-people-container-value=test365corp" "sun-idrepo-ldapv3-config-psearchbase=CDC=test365corp,DC=test365,DC=forgepoc,DC=com"
create-auth-instance -e / -t AD -m ActiveDirectoryModule
update-auth-instance -e / -m ActiveDirectoryModule -a "iplanet-am-auth-ldap-bind-dn=cn=ldapAuth,cn=users,DC=test365corp,DC=test365,DC=forgepoc,DC=com" "iplanet-am-auth-ldap-bind-passwd=SOMEPASSSWORD" "iplanet-am-auth-ldap-server=svr1.test365corp.test365.forgepoc.com:636" "openam-auth-ldap-connection-mode=LDAPS" "iplanet-am-auth-ldap-user-naming-attribute=cn" "iplanet-am-auth-ldap-base-dn=DC=test365corp,DC=test365,DC=forgepoc,DC=com" "iplanet-am-auth-ldap-user-search-attributes=mail" "iplanet-am-auth-ldap-user-search-attributes=cn" "iplanet-am-auth-ldap-return-user-dn=true"
create-auth-cfg -e / -m employeeChain
update-auth-cfg-entr -e / -m employeeChain -a "ActiveDirectoryModule|REQUIRED"
set-realm-svc-attrs -e / -s iPlanetAMAuthService -a "iplanet-am-auth-org-config=employeeChain"
import-entity -e / -c wsfed -m /home/centos/idpMeta.xml -x /home/centos/idpMetaExtended.xml
import-entity -e / -c wsfed -m /home/centos/spMeta.xml -x /home/centos/spMetaExtended.xml
create-site -s site1 -i https://login.test365.forgepoc.com:443/openam
add-site-members -s site1 -e https://login.test365corp.test365.forgepoc.com:8443/openam

Configure OpenAM to work behind a proxy

Use the deployment menu in OpenAM 13.5 to add a site to the deployment. Make the site URL the URL of your proxy. Once done, add your OpenAM server(s) to that site.

Configuring OpenAM authentication services

I’m assuming here that you’ve already got an Active Directory dataStore setup in the top level realm.
Head over to authentication and create an Active Directory authentication module. Make sure to configure this as described here, it is required for WS-Federation active requestor profile to work later on.
Set up the module as described below. Below, I’ve allowed users to log on with mail as well as their usual login method, assuming that the mail attribute in the user account matches the UPN of the account setup in office 365.

However, if you have UPN sufixes setup in your AD domain (as described in my instructions above) you’ll probably want to use userPrincipalName instead of mail:

Add this module to a chain and set it to be the default organisation login chain for your realm:

Create your WS-Federation hosted IDP and Remote SP

Manually creating WSFED entities in OpenAM is a bit tedious so I’ve provided some ready made entities for you to use here. I am assuming these will be added to the top level realm – you’ll need to adjust your endpoints to match your realm if you’ve used something different. I am also assuming that we’ll use the default OpenAM test certificate for token signing. You should use something different in production.

Go to the Federation section in OpenAM and create a circle of trust called cot:

Import these entities using the import entity button, making sure to add them to the correct realm:

You should now have a list of entities that looks something like this:

Set up your Azure tenant using PowerShell

If you haven’t done it already, install the Azure Powershell cmdlets on a Windows machine that you have access to.
Authenticate using Connect-MsolService:

Then use the Set-MsolDomainAuthentication cmdlet to setup your domain and make sure to set the signing certificate to the cert you are signing your assertions with:

$BrandName   = "ForgeRock test365"
$dom         = "test365.forgepoc.com"

$IssuerUri   = "urn:uri:test365forgepocemployeestlr"
$PassiveUri  = "https://login.test365.forgepoc.com:443/openam/WSFederationServlet/metaAlias/wsidp"
$ActiveUri   = "https://login.test365.forgepoc.com:443/openam/WSFederationServlet/sts/metaAlias/wsidp"
$MexUri      = "https://login.test365.forgepoc.com:443/openam/WSFederationServlet/ws-trust/mex/metaAlias/wsidp"

$Protocol    = "WsFed"

$SigningCert = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Set-MsolDomainAuthentication `
-Authentication Managed `
-DomainName $dom

Set-MsolDomainAuthentication `
-Authentication Federated `
-DomainName $dom `
-FederationBrandName $BrandName `
-PassiveLogOnUri $PassiveUri `
-ActiveLogOnUri $ActiveUri `
-MetadataExchangeUri $MexUri `
-SigningCertificate $SigningCert `
-IssuerUri $IssuerUri `
-LogOffUri $PassiveUri `
-PreferredAuthenticationProtocol $Protocol

Enabling “modern authentication” on the Azure Exchange and Skype services

Until recently, I had all Windows, MacOS, IOS and Android rich clients working, apart from one: Skype for business for Android. I was about to start analysing the network traffic, when my colleague Peter Major directed my to a community forum question from the user Steven Van Geel.

Even though Steven’s question was related to using Android Skype for business with OpenAM as a an Office 365 IDP using SAML2 ECP, the fix he describes also corrects the behaviour with the android app with a WsFed Active profile IDP. Turning on Microsoft “modern authentication” on the Skype for business online tenant allows the Skype client to authenticate.

I have not had a chance to had a look at why this is and why it only affects the Android Skype client. I will update this blog post when I find out. It is highly possible that this may be required for other clients in future as Microsoft gradually move services onto their “Modern Authentication” standard. Note that modern authentication can be turned on for Skype and for Exchange (Outlook).

For now, here are some brief instructions for enabling this. These are pretty similar to the steps for setting up the Azure online domain. First you need to install the Skype for Business PowerShell management cmdlets.

Then run the following to authenticate to your Skype Online (aka Lync Online) tenant:

 

$credential = Get-Credential
$session = New-CsOnlineSession -Credential $credential
Import-PSSession $session
Get-Module
Then turn on Modern Authentication as described in this article:
Set-CsOAuthConfiguration -ClientAdalAuthOverride Allowed

Setting up your first user

All that is left to do now is to configure a user to sign on to Office 365. Office 365 requires that accounts which federate with Office 365 also have an account entry set up in Office 365 itself. Certain properties have to be set on that account, such as the UPN and what licenses are assigned to the user. Microsoft provide the tools DirSync and Azure AD Connect that automatically synchronise on-prem Active Directory with Office 365. These are cut down versions of their identity Management Solution, “ForeFront Identity Manager” (FFIM – now EOL). ForgeRock have an Identity Management product, OpenIDM which has a powerful PowerShell connector. This can be configured to automatically provision accounts to Office 365 (see example scripts here and the IDM trunk docs here), but this is outside the scope of this post.

Here, I’ll show how to manually set up an account.

Assuming you have the following user in Active Directory:

The following PowerShell will set up that user in office 365 by copying the attributes from the same user in Active Directory.
$user = Get-ADUser charlie.brown
MSOnlineExtendedNew-MsolUser `
-DisplayName $user.Name `
-FirstName $user.GivenName `
-ImmutableId ([System.Convert]::ToBase64String(($user.ObjectGUID).ToByteArray())) `
-LastName $user.Surname `
-LicenseAssignment (Get-MsolAccountSku | select -ExpandProperty AccountSkuId) `
-UsageLocation GB `
-UserPrincipalName $user.UserPrincipalName

So how does this PowerShell work? We get the charlie.brown user from AD then pass the properties from it to the New-MsolUser method. We use the Get-MsolAccountSku method to find the SKU of the license we need to assign to the user. We also convert the Active Directory ObjectGUID property into the base64 format expected in Office 365.

Note: If the UPN of your user doesn’t match the name that they may fill in on something like the email account setup in Outlook, then you may want to change the userPrincipalName to use the mail attribute instead.

 

Conclusion

You should now be able to log on to Office 365 using all of the methods described above. There are some issues that you may encounter with this approach which you can track our progress on here.

What next? You may want to look at integrating this with with Integrated Windows Authentication (aka Kerberos, Windows Desktop SSO). I’ve done a blog post on that.

In a future blog post, I’ll look at doing the same thing with SAML2 ECP and the pros/cons of using that instead.

This blog post was first published @ http://authntoz.blogspot.no/, included here with permission from the author.

SAML2 as ForgeRock OpenAM 13 Authentication Module Instance

This blog post was first published @ www.fedji.com, included here with permission.

Well, you’ve possibly heard about the release of newer version of the ForgeRock Identity Platform with several enhanced capabilities. If not, you can read about it all here. One of the new features in the Access Management component of ForgeRock Identity Platform is SAML2 Authentication Module. What that offers is, after configuring Federation, we could supply all the required details like the IDP entity, the binding method etc. in an Authentication Module instance of the ForgeRock Access Management solution and use it just like any other Authentication Module (LDAP, Database, HOTP etc.). Let’s see how that’s done in a video demonstration that follows this write up. And, by the way, if you’d like to get a quick idea what’s new in the newer version of ForgeRock Access Management solution, read the release notes here.

We’ve already discussed OpenAM Federation on this space before. Here’s list of links from the past:

ForgeRock OpenAM Federation Using SAML v2
Using SAML Assertion Attributes in ForgeRock OpenAM

While the following video walks through the OpenAM Federation Configuration from the scratch, if you feel there are details missing in it, please feel free to have a look at the web logs mentioned above. The main focus of the screen-cast below is only to see how SAML2 is used as an Authentication Module instance in the version 13 of ForgeRock OpenAM.

The following illustration might give a quick idea on what’s demonstrated in the video embedded below this post.

OpenAMFederation
Now on to the screen-cast. Enjoy!

Using SAML Assertion Attributes in ForgeRock OpenAM – Episode 03/04 : Configuring Transient Federation in ForgeRock OpenAM

This blog post was first published @ www.fedji.com, included here with permission.

This is the third episode from a four part video made on using SAML v2 Assertion attributes in an application protected by ForgeRock OpenAM. In the interest of continuity and also to get the context accurately, it may make sense to read/view the blog posts in the following order:

1. Protecting a J2EE Application with ForgeRock OpenAM
2. Configuring Federation in ForgeRock OpenAM
3. Configuring Transient Federation in ForgeRock OpenAM
4. Using SAMLv2 Assertion Attributes

Let me throw a picture at you:

image04

The diagram is a slightly modified version of the one that you would have seen in my earlier blog entry. It has one additional user in the Identity Provider (which of course seems like a world famous detective and that’s no coincidence), but no corresponding entry in the Service Provider. In the Identity Federation Configuration earlier, we saw how a user with an id ‘demo’ in the Identity Provider linked her account with her id in the Service Provider. But there can be situations, when we may want to use Federation with identities only at the IDP, still gaining access to the applications protected by the SP. That’s where Transient Federation comes into play. It maps the identities from IDP to an anonymous user in the SP (many to one mapping).

Enjoy!

Using SAML Assertion Attributes in ForgeRock OpenAM – Episode 02/04 : Configuring SAML 2.0 Federation in ForgeRock OpenAM

This blog post was first published @ www.fedji.com, included here with permission.

This is the second entry from a series of four blog entries made around using SAML v2 Assertion attributes in an application protected by ForgeRock OpenAM. Reading/viewing this as an independent entry may not be a futile exercise, but it may seem more effective if the following order is followed while going through this topic:

1. Protecting a J2EE Application with ForgeRock OpenAM
2. Configuring Federation in ForgeRock OpenAM
3. Configuring Transient Federation in ForgeRock OpenAM
4. Using SAMLv2 Assertion Attributes

At end of this episode, the following is what you get:

image03

So the diagram above shows a Circle of Trust established between two entities (an Identity Provider and a Service Provider), each of which is an OpenAM instance running in two different Linux Containers. In this scenario, a user (with id ‘demo’) has profile in both IDP and SP, and by virtue of Identity Federation, she manages to link those accounts, after which once she authenticates against the IDP, IDP can send a assertion to SP, validating the authenticity of the user.

Enjoy!

ForgeRock OpenAM Federation Using SAMLv2

This blog post was first published @ www.fedji.com, included here with permission.

If you experience Deja Vu by looking at the illustration just below, chances are that you’ve hit my blogs before, in particular on this entry, where we looked at ForgeRock OpenAM as an Identity Provider and ForgeRock OpenIG as a Service Provider.

A friend asked me if I could demonstrate a very simple configuration of Federation using two ForgeRock OpenAM instances, one acting as an Identity Provider (a.k.a IDP) and another one taking up the role of a Service Provider (a.k.a SP). It wasn’t difficult to do one, so here we have it embedded towards the end of this post.

OpenAMFederation

So what do we have here:

– A Circle of Trust which has two OpenAM instances, one of which acting as an Identity Provider and another one as Service Provider
– User always authenticates against the Identity Provider
– The authentication process is intiated either by the IDP (known as IDP initiated SSO) or by the SP (SP initiated SSO)
– Once the user is authenticated successfully, IDP sends across a piece of security information to the SP (known as assertion) that could contain user attributes
– SP then gives the user access to protected resources

In the demonstration that follows, because ‘Auto Federation’ is not enabled, during the first login the user will be prompted for credentials both by the IDP and the SP. Once the account linking is done, it’s only the IDP who would challenge the user.

If the illustration and the briefing above hasn’t given you the complete picture, the video below might give a better one.

Enjoy!

ForgeRock OpenIG as SAML 2.0 Service Provider

This blog post was first published @ www.fedji.com, included here with permission.

This post is based on the ForgeRock Documentation on configuring OpenIG as SAML 2.0 Service Provider. The video logs embedded just below this write up is a visual representation of what is already there in the document that I mentioned above. For a detailed study, please read through the documentation and then sit back, relax and watch the demonstration in the screen-cast below

SAML 2.0 as you probably know is a standard to exchange information between a SAML authority (a Identity Provider a.k.a IDP) and a SAML Consumer (a Service Provider a.k.a SP). In the demonstration that follows ForgeRock OpenAM acts as an Identity Provider and ForgeRock OpenIG acts as a Service Provider. So the authentication of a user is done by the IDP, who will then send a piece of information (Assertion) to the SP that could contain the attributes of user from the user’s profile in the IDP DataStore. SP will then use the information thus obtained (Assertion) to take further action (like giving access to the user etc.)

There are two ways of getting this done:
(i) SP initiated SSO
(ii) IDP initiated SSO

In simple words, in a SP initiated SSO, the user contacts the Service Provider, who in turns gets in touch with the Identity Provider, who would validate the user credentials and then exchange a piece of information (Assertion) that could contain the user attributes to the Service Provider. Whereas a IDP initiated SSO, the IDP will authenticate the user, and would then send an unsolicited message (Assertion) to the SP, who would then take further action (like giving access to the user etc.)

The following two illustrations might give a rough idea:

SAM2UsingOpenIG

In our story (above in the illustration and below in the video), a user authenticates against ForgeRock OpenAM (IDP), who will send then an assertion (containing user’s mail and employeenumber attribute) to ForgeRock OpenIG (Service Provider), who will apply filters (like extracting the attributes from assertion and posting it as username and password) to post the user’s credentials to a protected application (Minimal HTTP Server)

If you’ve got a vague picture on what’s discussed above, I’d believe it’ll be clearer after watching the video below:

Enjoy!

Setting up Java Fedlet with Shibboleth IdP

The Java Fedlet is basically a lightweight SAML Service Provider (SP) implementation that can be used to add SAML support to existing Java EE applications. Today we are going to try to set up the fedlet sample application with a Shibboleth IdP (available at testshib.org).

Preparing the fedlet

There is two kind of Java fedlet in general: configured and unconfigured. The configured fedlet is what you can generate on the OpenAM admin console, and that will basically preconfigure the fedlet to use the hosted OpenAM IdP instance, and it will also set up the necessary SP settings. The unconfigured fedlet on the other hand is more like starting from scratch (as the name itself suggests :) ) and you have to perform all the configuration steps manually. To simplify things, today we are going to use the configured fedlet for our little demo.

To get a configured fedlet first you have to install OpenAM of course. Once you have an OpenAM set up, Create a new dummy Hosted IdP (to generate a fedlet it is currently required to also have a hosted IdP):

  • On the Common Tasks page click on Create Hosted Identity Provider.
  • Leave the entity ID as the default value.
  • For the name of the New Circle Of Trust enter cot.
  • Click on the Configure button.

Now to generate the configured fedlet let’s go back to the Common Tasks page and click on Create Fedlet option.

  • Here you can set the Name to any arbitrary string, this will be the fedlet’s entity ID. For the sake of simplicity let’s use the fedlet’s URL as entity ID, e.g., http://fedlet.example.com:18080/fedlet.
  • The Destination URL of the Service Provider which will include the Fedlet setting on the other hand needs to be the exact URL of the fedlet, so for me this is just a matter of copy paste: http://fedlet.example.com:18080/fedlet.
  • Click on the Create button.

This will generate a fedlet that should be available under the OpenAM configuration directory (in my case, it was under ~/openam/myfedlets/httpfedletexamplecom18080fedlet/Fedlet.zip), let’s grab this file and unzip it to a convenient location. Now we need to edit the contents of the fedlet.war itself and modify the contents of the files under the conf folder. As a first step open sp.xml and remove the RoleDescriptor and XACMLAuthzDecisionQueryDescriptor elements from the end of the XML.

At this point in time, we have everything we need for REGISTERing our fedlet on the testshib.org site, so let’s head there and upload our metadata (sp.xml), but in order to prevent clashes with other entity configurations, we should rename the sp.xml file to something more unique first, like fedlet.example.com.xml.

After successful registration the next step is to grab the testshib IdP metadata and add it to the fedlet as idp.xml, but there are some small changes we need to make on the metadata, to make it actually work with the fedlet:

  • Remove the EntitiesDescriptor wrapping element, but make sure you copy the xmlns* attributes to the EntityDescriptor element.
  • Since now the XML has two EntityDescriptor root elements, you should only keep the one made for the IdP (i.e. the one that has the “https://idp.testshib.org/idp/shibboleth” entityID), and remove the other.

The next step now is that we need to update the idp-extended.xml file by replacing the entityID attribute’s value in the EntityConfig element to the actual entity ID of the testshib instance, which should be https://idp.testshib.org/idp/shibboleth.

After all of this we should have all the standard and extended metadata files sorted, so the last thing to sort out is to set up the Circle Of Trust between the remote IdP and the fedlet. To do that we need to edit the fedlet.cot file and update the sun-fm-trusted-providers property to have the correct IdP entity ID:

cot-name=cot
sun-fm-cot-status=Active
sun-fm-trusted-providers=https://idp.testshib.org/idp/shibboleth,http://fedlet.example.com:18080/fedlet
sun-fm-saml2-readerservice-url=
sun-fm-saml2-writerservice-url=

It’s time to start the testing now, so let’s repackage the WAR (so it has all the updated configuration files) and deploy it to an actual web container. After deploying the WAR, let’s access it at http://fedlet.example.com:18080/fedlet. Since there is no fedlet home directory yet, the fedlet suggests to click on a link to create one based on the configuration in the WAR file, so let’s click on it and hope for the best. :)

Testing the fedlet

If we did everything correctly, we end up on a page finally where there are some details about the fedlet configuration, and there are also some links to initiate the authentication process. As a test let’s click on the Run Fedlet (SP) initiated Single Sign-On using HTTP POST binding one, and now we should be facing the testshib login page where you can provide one of the suggested credentials. After performing the login an error message is shown at the fedlet saying Invalid Status code in Response. After investigating a bit further, the debug logs tells us what’s going on under ~/fedlet/debug/libSAML2:

SPACSUtils.getResponse: got response=<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_0b33f19185348a26fffe9c3a1aa6e652" InResponseTo="s2be040cf929456a64f444527dfc1d7413ce178531" Version="2.0" IssueInstant="2013-12-04T18:39:32Z" Destination="http://agent.sch.bme.hu:18080/fedlet/fedletapplication"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://idp.testshib.org/idp/shibboleth</saml:Issuer><samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
</samlp:StatusCode>
<samlp:StatusMessage xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
Unable to encrypt assertion
</samlp:StatusMessage>
</samlp:Status></samlp:Response>

Now we can also look into the testshib logs (see TEST tab), and that will tell us what was the real problem:

Could not resolve a key encryption credential for peer entity: http://fedlet.example.com:18080/fedlet

So this just tells us that the Shibboleth IdP tries to generate an encrypted assertion for our fedlet instance, however it fails to do so, because it is unable to determine the public certificate for the fedlet. This is happening because the basic fedlet metadata does not include a certificate by default, to remedy this let’s do the followings:

  • Acquire the PEM encoded certificate for the default OpenAM certificate:
    $ keytool -exportcert -keystore ~/openam/openam/keystore.jks -alias test -file openam.crt -rfc
  • Drop the BEGIN and the END CERTIFICATE lines from the cert, so you only have the PEM encoded data, and then you’ll need to add some extra XML around it to look something like this:
    <KeyDescriptor>
    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:X509Data>
    <ds:X509Certificate>
    MIICQDCC...
    </ds:X509Certificate>
    </ds:X509Data>
    </ds:KeyInfo>
    </KeyDescriptor>
    
  • Add the KeyDescriptor under the SPSSODescriptor as a first element.
  • Upload the updated SP metadata with the same filename (fedlet.example.com.xml) again at the testshib site.

Since the decryption process requires the presence of the private key of the certificate, we need to ensure that the private key is available, so let’s do the followings:

  • Copy the ~/openam/openam/keystore.jks file to the fedlet home directory
  • Visit the http://fedlet.example.com:18080/fedlet/fedletEncode.jsp page and enter changeit (the password of the default keystore and private key as well).
  • Grab the encrypted value and create ~/fedlet/.storepass and ~/fedlet/.keypass files containing only the encrypted password.
  • Open up ~/fedlet/sp-extended.xml and ensure that the encryptionCertAlias setting has the value of test.
  • Restart the container, so the changes are picked up.

At this stage we should retry the login process again, and if nothing went wrong you can see all the nice details of the received SAML assertion from testshib.org! It Works! :)

Federation with Shibboleth SP (Apache module)

When you want to achieve Federation between different organizations, you often find yourself in a situation where the products used by the parties are different. Before we go any further I should make the terminology clear:
Identity Provider (IdP): The IdP holds all information about the user (for example in LDAP), and also it is the IdP’s job to authenticate the users, and decide on what kind of informations it shares about the users with other providers.
Service Provider (SP): The easiest way to think about the SP as an extra layer in front of the webapplication. The SP’s job is to authorize pagerequests, and if there is no authenticated session at the SP, initiate an authentication request to the IdP.

Today the goal is to achieve SSO between an OpenAM IdP and a Shibboleth SP with the simplest settings as possible.
This tutorial assumes that you already have a configured OpenAM instance running under idp.example.com.

Configure the IdP

  • Log in to the admin console and on the Common Tasks pane click on the Create Hosted Identity Provider link.
  • Select No for Do you have metadata for this provider
  • Use http://idp.example.com:8080/openam as Name
  • Select the default test Signing Key
  • Use cot as the name of the New Circle of Trust
  • Leave the Attribute mapping table empty
  • Press the Configure then the Finish button

Install and configure Shibboleth SP (on Ubuntu)

This tutorial was done with Ubuntu 11.04. If you have other OS/version it’s possible that the paths/steps will be different for you.

  • Install the Shibboleth SP Apache module:
    apt-get install libapache2-mod-shib2
  • Open the /etc/shibboleth/shibboleth2.xml configuration file using a text editor
  • In SPConfig -> InProcess -> ISAPI -> change the Site tag to:
    <Site id="1" name="sp.example.com"/>
    
  • In SPConfig -> RequestMapper -> RequestMap change the Host tag to:
    <Host name="sp.example.com" applicationId="sp.example.com" />
    
  • In SPConfig change the ApplicationDefaults opening tag to:
    <ApplicationDefaults id="default" policyId="default" 
    entityID="http://sp.example.com/shibboleth" 
    REMOTE_USER="eppn persistent-id targeted-id" 
    signing="false" encryption="false">
    
  • In SPConfig -> ApplicationDefaults -> Sessions change the /Login SessionInitiator‘s opening tag to:
    <SessionInitiator type="Chaining" Location="/Login" 
    isDefault="true" id="Intranet" relayState="cookie" 
    entityID="http://idp.example.com:8080/openam">
    
  • In SPConfig -> ApplicationDefaults -> MetadataProvider create a MetadataProvider:
    <MetadataProvider type="XML" file="idp.xml" />
    
  • In SPConfig -> ApplicationDefaults create an ApplicationOverride:
    <ApplicationOverride id="sp.example.com" 
    entityID="http://sp.example.com/shibboleth" /> 
  • Save the configuration file
  • Make sure that the files referred in SPConfig -> ApplicationDefaults -> CredentialResolver actually exist, and if necessary, generate a self signed certificate (using this guide for example).
  • Open http://idp.example.com:8080/openam/saml2/jsp/exportmetadata.jsp in your browser and save the XML as /etc/shibboleth/idp.xml (as configured in the MetadataProvider tag). (See this post for more information about exporting metadata.)
  • Open the /etc/shibboleth/attribute-map.xml config file and add the following line:
    <Attribute name="urn:oid:0.9.2342.19200300.100.1.1" id="HTTP_UID"/>
    

Prepare the Apache configuration

You need to configure Apache as well to make this setup work:

  • Make sure, that there is an sp.example.com VirtualHost in your Apache config
  • If you want to use .htaccess you need to enable the AllowOverride AuthConfig in the VirtualHost config
  • Create an index.php file in your docroot containing:
    <?php
    phpinfo();
    ?>
    
  • Create a .htaccess file in your docroot containing:
    AuthType shibboleth
    ShibRequireSession On
    require shibboleth
    
  • Enable the Apache Shibboleth module:
    a2enmod shib2
    
  • Restart Apache:
    /etc/init.d/apache2 restart
    

Registering the SP at the IdP

If you’ve done everything right so far, then you can access your Shibboleth SP Metadata at http://sp.example.com/Shibboleth.sso/Metadata. In case the Metadata does not contain a certificate check the logs at /var/log/shibboleth/shibd.log, also please remember that whenever you change the Shibboleth config you need to restart the Shibboleth service:

/etc/init.d/shibd restart

NOTE: OPENAM-792 can cause you troubles while importing the metadata. Make sure you either have the fix for this issue, or you have removed the Extensions tag from the Metadata before uploading it.

If everything is OK with your Metadata open the OpenAM admin console and click on the Register Remote Service Provider link on the Common Tasks pane.

  • You can either upload the Metadata or provide the URL on the config page.
  • Leave the attribute mapping empty
  • Click on the Configure button
  • Go to the Federation page then open the SP’s page in the Entity Providers table
  • Go to the Assertion Processing tab
  • In the Attribute Map list add the following value:
    urn:oasis:names:tc:SAML:2.0:attrname-format:uri|
    urn:oid:0.9.2342.19200300.100.1.1=uid
    
  • Save the configuration and log out

How to test

You just need to open a random URL under sp.example.com, and the htaccess config you created will make sure that the user is authenticated at the IdP. Opening such URLs should result in a redirect to the IdP presenting a login screen for you. After submitting the valid credentials you should be redirected back to the SP application to the originally requested URL. On the phpinfo page you should see the HTTP_UID server variable holding the user’s name.

In case you want to use the REMOTE_USER CGI variable in your applications, you can achieve that by modifying the Shibboleth configuration: in SPConfig -> ApplicationDefaults add HTTP_UID to the beginning of the REMOTE_USER attribute.