In this blog post, I will document the changes to integrate CA API Gateway with Office 365 tenant for Federation SSO. In this scenario, CA API Gateway is acting as an Identity Provider (IDP) and Office 365 tenant is acting as the Service Provider (SP).
Here’s the high level follow for a typical SAML2.0 Federation SSO:
Process Steps:
1. User goes to Office365 Tenant URL on the Browser.
2. Since the User is not Authenticated yet, there is no user Office365 User Session. Office365 generates the SAML SSO Request and redirects the user to the CA API Gateway URL with the SAML Request.
3. CA API Gateway validates the SAML Request and authenticates the user using Windows Integrated Authentication against the Windows Domain (Microsoft Active Directory)
4. User Authentication against Microsoft Active Directory (AD)is successful
5. If the User Authentication is successful, Gateway generates a SAML2.0 Token with the Attributes of the User from the Microsoft AD. Gateway then adds this SAML token in the message body with an Auto-Submit instruction to the Office365 Tenant URL and submits the request to the browser. Office365 Tenant now has the SAML Token for the authenticated user.
6. Office365 Tenant validates the SAML Token, extracts the user attributes from the SAML Token and the maps the user attributes with the Office365 AD to create a User Session. Generated user session is then sent to the Browser.
7. Browser then automatically sends this user session for all the subsequent resource requests to the Office365 Tenant.
Below are the commands required to be entered on the Windows Azure Active Directory module of Windows PowerShell. I have added few reference links for the Tenant commands.
$dom ='dummydomain.com'
$Brand = "Dummy Site"
$activeSO = "https://idpsite.com:443/sso/saml"
$PassiveSO = "https://idpsite.com:443/sso/saml"
$Issuer = "http://idpsite.com"
$cert = "MIIC9TCCAd2gAwIBAgIJAOjG+g1BNMLaMA0GCSqGSIb3DQEBDAUAMBgxFjAUBgNVBAMTDXNpZ24udGVzdC5jb20wHhcNMTYxMDIxMTkzOTIxWhcNMjExMDIwMTkzOTIxWjAYMRYwFAYDVQQDEw1zaWduLnRlc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmuJ6oUQItWDkF8Kf9wq6Q6zALvtvVdJKPz97eBSSp5IN+Hn6nPDbYGeb3DQEHxDLO23uUIEK6O4S/3mLBFJ8i+bHNk4J5ilKP0MJGrf1wIm1hD61YKoTFSBal9v5INkm6usXXWBibj1NKJBoazJKpNTx0OY1kgJ2qKPK9EMosCUiB/VxOONpajMmHgNyAEdiCWp8G6Y62bTxse73VsXDm/SASL4PeweIxApu/Sbr/eMw3v8oeyZFt3Fr1ovlz6nfLJ+R4m7OA5cTcaX7oeX+DuKLA7tJizxVPPLF9ROr+sN5ZmdohZMn6EbZssLv/+N6sP30MhnJVFn6P0yO66CTiwIDAQABo0IwQDAdBgNVHQ4EFgQUWRba0ivmwwWnFloObBoKSuNJ6UIwHwYDVR0jBBgwFoAUWRba0ivmwwWnFloObBoKSuNJ6UIwDQYJKoZIhvcNAQEMBQADggEBAIWr2uPNRd2vG7hts+BdAygUC+OsrwzIf/zLCnuDlu38GKJOf+7OhqYXoILcC8aNH+gWp+cv0pw5WhOiVPbMx/TNZ9yx0WUnbCouZdJOuyoS5thirEms0GsMRoBapkNYpBvPIZzJhvdcwUc2PJfCQ50tQL1L5+AnM72JEkyg8KkH5scrPtAG898GiDWbMFTnw4oktoB8+dl9VoZ6Clzdbz7oygPbOKyy/G05zvRQlcZHdF/y
gkey5fSDNUeP1Pvbav71ja6cB2WwjckS3ayyzEyYV0+6XloAthRA/taZhDhR2OLUw7tbVyiSCbIapQqAc7iYYl7hWwjSu7lV5ZlYih0="
Set-MsolDomainAuthentication -DomainName $dom -FederationBrandName $Brand -Authentication Federated -PassiveLogOnUri $PassiveSO -IssuerUri $Issuer -ActiveLogOnUri $activeSO -LogOffUri $PassiveSO -SigningCertificate $cert -PreferredAuthenticationProtocol Samlp
Make sure to substitute the following detail in these commands:
dom = Name of the Office365 domain
PassiveSO and activeSO = CA API Gateway IDP URL
Issuer = Issue value set by CA API Gateway in the SAML Response
cert = Public certificate of the certificate key pair used by CA API Gateway to sign the SAML response
Reference Links –
https://msdn.microsoft.com/en-us/library/azure/dn641269.aspx
Here’s the link to the Office365 SP Metadata URL –
https://nexus.microsoftonline-p.com/federationmetadata/saml20/federationmetadata.xml
CA API Gateway Service:
Here are few of the key changes that we need to make in the CA API Gateway SAML IDP Service for it work successfully with Office365:
1) ACS URL – Assertion 20, 58, 75,79 – We need to post the SAML Response to the Micorsoft URL - https://login.microsoftonline.com/login.srf. This value is derived from the Office365 SP Metadata attribute AssertionConsumerService.
2) Audience – Assertion 21, 58 – Audience in the SAML response should be set to urn:federation:MicrosoftOnline. This value is derived from the Office365 SP Metadata attribute entityID.
3) SamlRequest Issuer – Assertion 22, 47, 86 – We need to validate the SAML Request is sent by Office365 with Issuer value urn:federation:MicrosoftOnline
4) Immutable ID – Assertion 39 - We need to Query AD to get the Immutable ID of the authenticated user which needs to be sent in the SAML Response in NameID field. objectGUID attribute in the AD is the Immutable ID. This attribute has binary value. To query this value from AD, we need to append the LDAP attribute in the LDAP Query Assertion with a postfix “;binary”. See the below screenshot and the reference link from CA for extracting binary attribute.
1) SAML Request ID – Assertion 49, 51, 65, 76 – We need to extract the ID value from the SAML Request sent by Office365 to CA API Gateway. We need to send this ID value back to Office365 in the SAML Response in InResponseTo attribute of the samlp2:Response and saml2:SubjectConfirmationData elements.
2) SAML Assertion Attribute – Assertion 58 – SAML Assertion should have an attribute by the name IDPEmail and value set to the User’s email id and Name Identifier set to the objectGuid extracted from AD in step 4 above.
3) SessionIndex – Assertion 61 – We need to generate UUID and send in the SAML Response in the SessionIndex attribute of the saml2:AuthnStatement element.
4) NameID Format – Assertion 63 – We need to update the format of the NameID attribute to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
5) Remove SubjectLocality – Assertion 67 – We need to remove the element SubjectLocality from the SAML Response.
6) SAML Assertion Sign – Assertion 71,73,74 – Since we need to update the SAML Assertion with the changes mentioned in the points 7 through 9, we cannot select “Sign Assertion” in the Create SAML Token Assertion. We need to sign the SAML Assertion using “(Non-SOAP) Sign XML element” assertion. This sign assertion has an option of adding the signature as first or last child of the signed element. However, for SAML Assertion to be accepted by Office 365, SAML Assertion should have the saml2:Issuer element followed by ds:Signature element. Assertion 73 and 74 are used to do this sequencing. This sequencing of the signature resolved the below SSO error generated on the Office365 Tenant:
Error from attempted sign in:
Additional technical information:
Correlation ID: 12529wg9w-27d6-2496-w12k-qwxu14xe05jd
Timestamp: 2016-10-11 14:43:19Z
AADSTS50000: There was an error issuing a token.
Sample SAML Request generated by Office365:
<samlp:AuthnRequest ID="_9eb6887f-8b57-4c58-9ef1-e9c88248cf0b" Version="2.0" IssueInstant="2016-10-20T14:17:44.590Z" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">urn:federation:MicrosoftOnline</Issuer>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
</samlp:AuthnRequest>
Sample SAML Response:
<samlp2:Response InResponseTo="_9eb6887f-8b57-4c58-9ef1-e9c88248cf0b" Destination="https://login.microsoftonline.com/login.srf" ID="ResponseId_a31a330c4ba5c9cb3cc008174fa4c3a0" IssueInstant="2016-10-20T14:18:10.131Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp2="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer>http://idpsite.com</saml2:Issuer>
<samlp2:Status>
<samlp2:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp2:Status>
<saml2:Assertion ID="SamlAssertion-7a5b9c01049a0575cf20ed7e6371c728" IssueInstant="2016-10-20T14:18:10.118Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:Issuer>http://idpsite.com</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#SamlAssertion-7a5b9c01049a0575cf20ed7e6371c728">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>osu7asdfe23Aw5c24Eaasdfas2vySr78=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>VagV/DDfrAk6CZZxwW/ ……+3Sd3H6AxlKZZS9sgwg7dJxBsw==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIC9TCCAd2gAwIBAgIJAOjG+ ……. Ac7iYYl7hWwjSu7lV5ZlYih0=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="">E2nqyveqmcEiqQTEMKGcCQ==</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="_9eb6887f-8b57-4c58-9ef1-e9c88248cf0b" NotOnOrAfter="2016-10-20T14:23:10.119Z" Recipient="https://login.microsoftonline.com/login.srf"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2016-10-20T14:13:10.119Z" NotOnOrAfter="2016-10-20T14:23:10.119Z">
<saml2:AudienceRestriction>
<saml2:Audience>urn:federation:MicrosoftOnline</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AttributeStatement>
<saml2:Attribute Name="IDPEmail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue>testuser@dummydomain.com</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
<saml2:AuthnStatement AuthnInstant="2016-10-20T14:18:10.118Z" SessionIndex="f89db7e5-ae43-477f-aa47-ef96da4b4227">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</samlp2:Response>
See also: SAML_IDP_ForOffice365.xml