Child pages
  • Microsoft Office 365 Integration
Skip to end of metadata
Go to start of metadata

Introduction

This document shows a step-by-step recipe on how to properly configure OpenAM to Single Sign on to O365 via SAML 2.0.  OpenAM will be the IDP and O365 will be the SP.  Note this procedure assumes that you have OpenAM 11.x installed and that you know how federation works and understand the core concepts of SAML 2.0.  Furthermore it is assumed that you as O365 admin have already created the users.  Similarly the OpenAM Admin should already have created the corresponding users in OpenAM.  This means is that the users have to be pre-provisioned on both ends for this federation to work.  This is a key pre-requisite.

Note that for this exercise a new realm called “O365” is added, which will be explicitly called as a query parameter to the OpenAM login servlet. If your goal is to provide O365 integration with all realms then you can implement the configuration at the root level realm and hence would not need to provide the realm name as a query parameter. It is good to understand the login flow as it will make the configuration and if needed troubleshooting easier. 

The user types in the URL http://login.microsoftonline.com in their browser. 

  1. In the login form, you enter your login name which will be something like "username@demo.example.com".   You don't need to enter the password as the password is only required at the IDP.

  2. Note @demo.example.com will indicate to O365 that this is a federated login, and in particular case we are dong SP Initiated SSO.

  3. O365 internally looks up this user and the associated SAML metadata and then enters into SAML flow by redirecting to the registered IDP (OpenAM) with a SAML AuthN request.

  4. The redirection takes you to OpenAM login screen, where you enter your OpenAM (IDP) credentials.

  5. If everything goes well, OpenAM will send a SAML Response to the registered endpoint of the SP (O365).  This response will contain the require name identifier as well as an attribute called IDPEmail which will be used by O365 to look for the user in its internal repository.

  6. O365 verifies the SAML response, maps the user, and then allows the user to Single Sign On.

In the whole flow above the user experience is not a complicated. The user will first see the O365 login page and then the OpenAM login page and then logs into O365.  

Ingredients

The ingredients for this recipe are as follows:

OpenAM Configuration

Create hosted IDP using OpenAM's Wizard

Log into the console as "amadmin". On the dashboard under the "Common Tasks" tab

  • Click on "Create Hosted Identity Provider"
  • Choose the Realm from the drop down which in this case is /O365
  • Choose the "Signing Key" which in this case is the OOTB self signed "test"
  • Create a new Circle of Trust called "MSO365"

Register Remote SP

Import the SP (O365) metadata file.

  • Use wget or your browser to download the federationmetadata.xml file. Ideally this file can be imported into an Identity Provider as is. However OpenAM does not like the initial <signature> tag so edit this file and remove everything within the first <signature>...</signature> tags including the tags themselves.
  • Log into the console as "amadmin". On the dashboard under the "Common Tasks" click on "Register Remote Service Provider" and then complete the wizard to import the modified federationmetadata.xml file. Ensure that the SP is part of the "MSO365" circle of trust. This step completes the federation setup on OpenAM.

https://nexus.microsoftonline-p.com/federationmetadata/saml20/federationmetadata.xml

Provide Attribute Mapping

  • When the SAML assertion is sent back to O365, we need to provide O365 with an attribute called "IDPEmail" which will essentially be used as the "foreign key" to map the OpenAM user to the O365 user. This is done by defining an "Attribute Mapper" map "IDPEmail=mail" on the SP settings.

Pre-Provision

  • As emphasized in the Introduction, the federated user in OpenAM has to be pre-provisioned i.e. Auto-Federation will not work. This is because O365 requires a "persistent" nameid. An example of a typical user entry that is provisioned correctly to work O365 is pasted on the right column. The two attributes that OpenAM hold persistence information is "sun-fm-saml2-nameid-info" and "sun-fm-saml2-nameid-infokey". Key things to note is the entityID for the IDP which in this example is "http://am.demo.openrock.org:8080/openam" and the entityID for the SP which is "urn:federation:MicrosoftOnline".
  • Also note the value of the "mail" attribute which will be sent in the SAML assertion to the SP (O365) as an attribute statement. See the SAML request/response at the very end.

$ opendj/bin/ldapsearch -p 8089 -D "cn=directory manager" -w password  -b "dc=example,dc=com" uid=wahmed

dn: uid=wahmed,ou=people,dc=example,dc=com
givenName: Wajih
uid: wahmed
cn: Wajih Ahmed
sn: Ahmed
sun-fm-saml2-nameid-info: http://am.demo.openrock.org:8080/openam|urn:federation:MicrosoftOnline|
wahmed|
http://am.demo.openrock.org:8080/openam|urn:oasis:names:
tc:SAML:2.0:
nameid-format:persistent|wahmed|urn:federation:MicrosoftOnline|IDPRole|false
sun-fm-saml2-nameid-infokey: http://am.demo.openrock.org:8080/openam|urn:federation:MicrosoftOnline|wahmed
mail: wahmed@demo.openrock.org

Export the IDP Metadata

This will be required for the configuration in the next section.

  • After creating the IDP in OpenAM as outlined in the steps above, export its metadata using the exportmetadata.jsp. Note how the "realm" (if any) and "entityid" are used in the query parameters.
  • Ideally this exported metadata can be imported into any Service Provider. However in this case this file is used as a reference and used to copy the "endpoints" and "certificate" and then feed them to a powershell script.

https://am.example.com:8443/openam/saml2/jsp/
exportmetadata.jsp?
realm=/O365&entityid=
http://am.example.com:8080/openam

O365 Configuration

Prepare

  • First thing you want to do is to download and read the "Office 365 SAML 2.0 Federation Implementer's Guide". For brevity this will be called the "Guide" in this section. 
  • The key things to note is that you will need to use powershell from any AD machine which has the Azure AD Module for powershell installed.
Office 365 SAML 2.0 Federation Implementer’s Guide

Install the Azure AD Module

  • As stated earlier you should have the Azure AD Module installed. See the ingredients section above for the link to the module. This module requires that the Microsoft Service Sign-in Assistant installed first. Once you have downloaded and installed both components you will get a link on your desktop to launch the powershell.
  • Once this module is properly installed you will use the steps outlined in the Guide to connect and configure O365 to work with the IDP (OpenAM). For convenience the steps are outline in the next few rows as the Guide is not comprehensive.

Add your Domain to O365

  • Note this is not the same as the default domain which cannot be enabled for SSO.
  • You need to add a new domain which essentially represents your O365 service and will be used by your company to single sign on to O365. In my case i chose "demo.openrock.org" because i own the openrock.org domain.
  • During adding the new domain you need to verify that you actually own the domain. You do so by adding a new TXT or MX record for the domain to your DNS with a special value provided by O365. 
    • I got this value on the "Confirm Ownership of your domain", by choosing the "General Instructions" and copying the "Destination or Point to Address" column. In my case it was "MS=ms65748521".
    • Since i was using EC2 i created a DNS TXT recorded in Route 53 with the above value.
  • Finally ensure that the new domains appears under the "Domains" section of O365 settings.

Create Service Provider in O365 (Step 1)

  • Use "Connect-MsolService" command from the powershell to establish trust between OpenAM and O365 and subsequently create federated users. Refer to Page 7 of the Guide.
  • Notice use the O365 Administrative (default) account to log in.

Create Service Provider in O365 (Step 2)

  • Create a powershell script called openam.ps1 and then run it from the above powershell window in which you have already logged in using Connect-MsolService. Alternatively you can uncomment the "Connect-MsolService" line and then right click on the script to edit and run in Microsoft Powershell ISE. 
    • Note in order to run the powershell script i had to run "Set-ExecutionPolicy RemoteSigned" in the powershell window. 

Connect-MsolService

$dom = "demo.example.com"
$url = "https://am.example.com:8443/openam/SSOPOST/metaAlias/demo/idp"
$ecp="https://am.example.com:8443/openam/SSOSoap/metaAlias/demo/idp"
$entity = "http://am.example.com:8080/openam"
$logout = "https://am.example.com:8443/openam/IDPSloRedirect/metaAlias/demo/idp"
$cert = ".......Y0Q=="

Set-MsolDomainAuthentication -DomainName $dom -FederationBrandName
$dom -Authentication Federated -PassiveLogOnUri
$url -SigningCertificate $cert -IssuerUri $entity -ActiveLogOnUri
$ecp -LogOffUri $logout -PreferredAuthenticationProtocol SAMLP

Check Service Provider in O365

  • After running this script successfully run "Get-MsolDomainFederationSettings" command to ensure changes have been saved.

ActiveLogOnUri : https://am.demo.openrock.org:8443/openam/SSOSoap/metaAlias/idp
FederationBrandName : wfoo.net
IssuerUri : http://am.demo.openrock.org:8080/openam
LogOffUri : https://am.demo.openrock.org:8443/openam/IDPSloRedirect/metaAlias/idp
MetadataExchangeUri :
NextSigningCertificate :
PassiveLogOnUri : https://am.demo.openrock.org:8443/openam/SSOPOST/metaAlias/idp
SigningCertificate : MII......W0Y0Q==

Create corresponding user in O365

  • This done by running the "new-msoluser" cmdlet (in MS terminology). Once it is run check the console to see if the user exists and if needed assign a license to it. If you don't assign a license then you will not be able to log in.

new-msoluser -DisplayName Wajih -UserPrincipalName wahmed@demo.openrock.org -UsageLocation NO -BlockCredential $false -ImmutableId wahmed

 

Testing and Troubleshooting

Testing the Federation Setup

  • The most obvious way to test is to point your browser to http://login.microsoftonline.com and attempt to login as the user you added in the last section. In this particular case it was wahmed@demo.openrock.org. As soon as you type in and submit your user name (obviously no need to provide password), you will be redirected to the IDP (OpenAM). The flow is explained in the Introduction of this article. If it is successful then you should see your O365 home page.

Troubleshooting the SP (O365)

  • Use the "Microsoft Remote Connectivity Analyzer"
    • Note for me this did not work really well as the tool seems to have a bug. It complains about "The Metadata Exchange URL in the domain registration isn't valid. URL:" whereas this is an optional item so it should not fail here. But nevertheless the preceding tests should all pass.

Troubleshooting on the IDP (OpenAM)

  • The debug logs of OpenAM are much more useful in understanding what is going on and what could be wrong. Look for the "Federation" debug log under openam/openam/debug directory. Note you need to set "message" level debug to see useful information in this log.
    • For example if you see "Creating of NameID is not allowed per AuthnRequest" error then it means that the user is not "pre-provisioned" correctly in OpenAM.

IDPSSOUtil.sendResponseToACS: Response is: 
<samlp:Response ID="s209f765fd663ba9318c113b22b2ca12cecd090343"
InResponseTo="_ee1dd97e-fbf5-4142-a257-ed578859292e" Version="2.0"
IssueInstant="2014-09-04T19:02:49Z" Destination="https://login.microsoftonline.com/login.srf"><saml:Issuer>http://am.demo.openrock.org:8080/openam</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester">
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy">
</samlp:StatusCode></samlp:StatusCode>
<samlp:StatusMessage>Creation of NameID is not allowed per AuthnRequest.</samlp:StatusMessage>
</samlp:Status>
</samlp:Response>

SAML Request/Response

  • The first xml blob is the SAML AuthN request from the SP (O365)
  • The second larger xml blob is the SAML AuthN response from the IDP (OpenAM)
    • Notice the IDPEmail attribute which is required for mapping into OpenAM

IDPSSOFederate.getAuthnRequest: decoded SAMl2 Authn Request:
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" AssertionConsumerServiceIndex="0"
ID="_c5a2a1e4-c1f8-4ac2-b56b-0e4e5cb2221e" IssueInstant="2014-09-04T20:41:27Z"
Version="2.0">
<saml:Issuer>urn:federation:MicrosoftOnline</saml:Issuer>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
</samlp:AuthnRequest>


IDPSSOUtil.sendResponseToACS: Response is:
<samlp:Response ID="s2ade8787eb950f312031ffa955850fc150eb5c36b"
InResponseTo="_c5a2a1e4-c1f8-4ac2-b56b-0e4e5cb2221e"
Version="2.0" IssueInstant="2014-09-04T20:46:23Z"
Destination="https://login.microsoftonline.com/login.srf
<saml:Issuer>http://am.demo.openrock.org:8080/openam</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></samlp:StatusCode></samlp:Status><saml:Assertion Version="2.0"
ID="s286b54d8a8331da079e608536794f7c78dda02cf0"
IssueInstant="2014-09-04T20:46:23Z"<saml:Issuer>http://am.demo.openrock.org:8080/openam</saml:Issuer>
<saml:Subject>
<saml:NameID NameQualifier="http://am.demo.openrock.org:8080/openam" SPNameQualifier="urn:federation:MicrosoftOnline" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" SPProvidedID="wahmed">wahmed</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2014-09-04T20:56:23Z" InResponseTo="_c5a2a1e4-c1f8-4ac2-b56b-0e4e5cb2221e" Recipient="https://login.microsoftonline.com/login.srf" ></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject>
<saml:Conditions NotBefore="2014-09-04T20:36:23Z" NotOnOrAfter="2014-09-04T20:56:23Z"><saml:AudienceRestriction>
<saml:Audience>urn:federation:MicrosoftOnline</saml:Audience>
</saml:AudienceRestriction></saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-09-04T20:46:23Z" SessionIndex="s24a7f4d0f66d85d9c1dd3b881571c29e42f064801">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:
PasswordProtectedTransport</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="IDPEmail">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">wahmed@demo.openrock.org</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>

  • No labels

9 Comments

  1. Unknown User (sarris.overbosch@everett.nl)

    are you sure the IDPEmail is used link the logged in user with the O365 user, asking this because in my setup the value which is in the third field of the sun-fm-saml2-nameid-info (the nameID value) does seam to matter. I see you are filling it with wahmed which is your uid and Immutable Id, for my case I would fill in soverbosch but this doesn't work. When I replace soverbosch with sarris.overbosch it does work. So my question is basically what should be in the nameId and how to determine it?

    I tried it again with creating a new user both on O365 side and OpenSSO side. but it doesn't work. But maybe this is a problem which is only on OpenSSO 8u2 but have been looking at this problem for some time now and any help would be appreciated (using an trail small business O365 account)

    Found something: For the latest user I created the UserPrincipalName was thymen@somedomain.nl but the uid and ImutableId where toverbosch. When I changed the UserPrincipalName into toverbosch@somedomain.nl it started working! So there seams to be a relation between what is in the UserPrincipalName and in the NameID of the sun-fm-saml2-nameid-info. But then again, why is my first user behaving different as there the UserPrincipalName is in the form of soverbosch@somedomain.nl and the uid/ImutableId are soverbosch!

    1. Unfortunately i haven't tested with OpenSSO.  But with OpenAM 11.x it works as explained.  I actually tested it yesterday. I have my doubts about the IDPEmail but i was instructed to use it by a MS expert.  I can try without and see what happens...

    2. Unknown User (raffed)

      In my testing I have found that there is a relationship between the UPN and the ImmutableID values. Technically the ImutableID is the SAML Subject and Office 365 uses that the properly associate the SAML Response with the Azure AD user account.

      The UPN value is used for what I believe is Access Control or authorization within the O365 ecosystem. I came to this conclusion by doing a couple tests once I had a user provisioned and SAML Integration all setup and configured between O365 and OpenAM (version 11.0.2)

      1) Had matching UPN values between OpenAM and AzureAD but changed the ImmutableID in OpenAM. This resulted in an Error in O365 that basically said it could not find the user. This tells me that the SAML response subject must match the AzureAD users ImmutableID.

      2) Had a matching ImmutableID values between OpenAM and AzureAD but changed the UPN Value. This resulted in an Error in O365 of: "You don't have permission to access this page or perform this action". This tells me that the Azure STS (login.microsoftonline.com) properly found and matched up the user but then the app (Portal, Outlook WebApp, SharePoint etc.) could not match UPN in the response with a valid users UPN so it could check permission etc.

      So in the end yes both ImmutableID (SAML Subject) and IDPEmail (UPN) must both match up with the AzureAD user account.

  2. Unknown User (jgoers)

    Hi do you know if Office365 supports IDP initiated SAML - where OpenAM would just sent them the SAML response without first getting a SAML request?

    jeff

    1. I don't think so but i would recommend that you check with them.

    2. Unknown User (raffed)

      You can technically do IdP initiated auth to O365 and it works. In fact I found that when you do this, OpenAM will generate the persistent SAML Subject and populate the "sun-fm-saml2-nameid-info" and "sun-fm-saml2-nameid-infokey" values for you so you don't have to "pre-provision" these values in your directory. Very cool. However the trick is synchronizing this persistent ID to the Azure AD Immutable attribute which is another issue all together. 

      The issue is that there are use cases in O365 where a user will get a shared document sent to them via email. When they click the link this is all going to be a SP initiated flow not an IdP initiated flow. So in summary I would say that you are most likely going to support and deal with the SP Initiated flows for O365.

      1. Unknown User (janwillem.beusink@iwelcome.com)

        OpenAM supports IdP initiated SSO, however - to my knowledge - o365 does not.

        The trick is to send the user to a smart o365 landing page so that it starts a SP initiated SSO, with the domain prefilled.
        e.g. https://login.microsoftonline.com/PostToIDP.srf?msg=AuthnReq&realm=am.example.com

  3. Unknown User (raffed)

    I am struggling with how to deal with provisioning of the users into Azure AD and matching up the SAML Subject (nameid-format:persistent)  with the AzureAD users ImmutableID. Our directory of users is not Active Directory but an LDAP directory that the MSoft Dir Sync solution cannot integrate to. We have a lot of potential users we need to pre-provision into AzureAD and I am trying to avoid having to first set the persistent ID's in our directory and then match these values up with the ImmutableID in AzureAD.

    Typically when dealing with the persistent nameid-format the IdP will generate the persistent SAML subject IF the SP puts the AllowCreate=true in the initial SP initiated SAML request. From my testing O365 does NOT set the AllowCreate=true option and by default the IdP will not auto generate this persistent identifier with SP initiated authentication. Hence the need with OpenAM to "pre-provision" the users persistent ID that will be used.

    I did test out IdP initiated flow by removing the users persistent sun-fm-saml-nameid-info and sun-fm-saml2=nameid-infokey values  in our directory for O365 and then started the IdP initiated flow to see if it would create the persistent ID and store the values in the nameid-info and nameid-infokey attributes in the directory.

    Here is an example of the IdP initiated request I used: https://example.company.com/openam/saml2/jsp/idpSSOInit.jsp?metaAlias=/demo/idp&spEntityID=urn:federation:MicrosoftOnline

    With this flow, OpenAM DID auto generate a persistent identifier and populate the nameid-info and nameid-info keys in the directory. This is great but I really need OpenAM to do this with SP initiated flow and when the SP does NOT include the AllowCreate=true option. Is there any setting in OpenAM that would allow it to create the persistentID? If only O365 supported Just In Time Provisioning now I would be good to go with initial authentication of users. I could then figure out an out of authentication flow to keep the AzureAD users in sync with our LDAP directory.

    So I would love to hear how anyone else is dealing with the provisioning piece of integrating OpenAM with O365 over SAML.

    Thanks.
    Eric Raff 

  4. case sensitivity must match on users in OpenAM and Microsoft for NameID and/or IDPEmail