This article will demonstrate how to configure an Apereo CAS Office365 SAML integration.
These instructions should be treated as an example and not as a production ready script. These changes should be first made in an Office365 test tenant before attempting in production. Tweak your steps and configuration as needed for your environment.
JSON Service Registry
The first step is to register a new service in your json service registry. It should look similar to the following.
A few things to note about the registered service:
- serviceId is urn:federation:MicrosoftOnline
- The metadata file must be generated yourself and retrieved locally. Our copy is located below the example service.
- The NameID or usernameAttribute is the Active Directory objectGUID. This is critical to not miss, else your integration will fail.
- The IDPEmail is the attribute name expected by Office365 in your list of released attributes.
- Make sure that urn:oasis:names:tc:SAML:2.0:nameid-format:persistent is a supported format in your CAS metadata.
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>{
"@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
"serviceId": "urn:federation:MicrosoftOnline",
"name": "office365",
"environments": [
"java.util.HashSet",
[
"prod"
]
],
"description": "Microsoft Office 365 / Entra",
"id": 1234,
"evaluationOrder": 1234,
"metadataLocation": "file:/etc/cas/config/metadata/o365-metadata.xml",
"encryptAssertions": false,
"signAssertions": true,
"signResponses": false,
"requiredNameIdFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
"usernameAttributeProvider": {
"@class": "org.apereo.cas.services.PrincipalAttributeRegisteredServiceUsernameProvider",
"usernameAttribute": "objectGUID"
},
"attributeReleasePolicy": {
"@class": "org.apereo.cas.services.ReturnMappedAttributeReleasePolicy",
"allowedAttributes": {
"@class": "java.util.TreeMap",
"userPrincipalName": "IDPEmail"
}
}
}Office 365 SAML Metadata
Do not assume this metadata reflects Microsoft’s current metadata. Consult their documentation for the latest. This only serves as an example.
<?xml version="1.0" encoding="utf-8"?>
<EntityDescriptor ID="_39351015-9337-4e1d-b5fd-aaf573be4936" entityID="urn:federation:MicrosoftOnline"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport">
<Signature
xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#_39351015-9337-4e1d-b5fd-aaf573be4936">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>S84IBgVoghBSDdaqFYyz4kGchy8=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>Lz8l3DgSS/qv3HhZDhwCsS6sf8vTbzesWLS66nmPzDodS9qJDs/1MEzuryVB7l0n8lKhyyKAbkSqeOelVpGHd6EjaMj7BNhLd9GxA6IGfKm5yQNw0K7Y6BvaDItQGRGpP/klerNWk8FH11mj5wQq706+luQwmoq0dtX/RADjiGHjW7YpnXdKAbf1prN7xchtv8hyjktYJ0S3rE0NZ7q9TjiQJ5UrVZgwK2zbCnwj3tGRqtFZHFogMvPZ1hVBc1ANhK6tqNOJ+440IwE6LHuFeT0xvOobNQpYWmV4eBC+RaGhWaTAzuw1j7T+CIZmiYORDlY7SC0Wv6TAmfYWcrJqTw==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC/TCCAeWgAwIBAgIQN/GPegnT8blP2EcSdMMbBzANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDEx5MaXZlIElEIFNUUyBTaWduaW5nIFB1YmxpYyBLZXkwHhcNMjEwMjE4MDAwMDAwWhcNMjYwMjE4MDAwMDAwWjApMScwJQYDVQQDEx5MaXZlIElEIFNUUyBTaWduaW5nIFB1YmxpYyBLZXkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXdLGU2Ll5RPdDUnKQ+f/HS5qiTay2cCh9U2AS6oDM6SOxVhYGtoeJ1VPebcLnpgLfhPxzrwWoVzXSEF+VRQbnYID2Jb4khjgyEeoThk3VqrThwhahpSbBg2vo06vIOp1TS2R1BiwHKTLoB1i1IJnaIFSC3BN6pY4flXWyLQt/5ABXElv2XZLqXM9Eefj6Ji40nLIsiW4dWw3BDa/ywWW0MsiW5ojGq4vovcAgENe/4NUbju70gHP/WS5D9bW5p+OIQi7/unrlWe/h3A6jtBbbRlXYXlN+Z22uTTyyCD/W8zeXaACLvHagwEMrQePDXBZqc/iX2kI+ooZr1sC/H39RAgMBAAGjITAfMB0GA1UdDgQWBBSrX2dm3LwT9jb/p+bAAdYQpE+/NjANBgkqhkiG9w0BAQsFAAOCAQEAeqJfYHnsA9qhGttXFfFpPW4DQLh5w6JCce7vGvWINr5fr1DnQdcOr+wwjQ/tqbckAL2v6z1AqjhS78kbfegnAQDwioJZ1olYYvLOxKoa6HF+b1/p0Mlub8Zukk2n1b2lKPBBOibOasSY7gQDwlIZi7tl9nMTxUfdYK+E5Axv7DVnmUCwcnnpV5/1SFdNyW2kWO4C68rrjMOvECfwrKkbfVJM8f9krEUBuoBF8dTDv7D2ZM4Q2buC70NbfaNWUX0yFvKI0IuTqk8RBfGTRQ4fZAbhMPaykEpBu6dNjTi5YOa0lNqFGS7Ax7leCh5x9lV8elcLkXs8ySo8AOQJk0hgIw==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<SPSSODescriptor WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<KeyInfo
xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIIC/TCCAeWgAwIBAgIQbgDHfi3t1JNGVqwD5/7lmjANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDEx5MaXZlIElEIFNUUyBTaWduaW5nIFB1YmxpYyBLZXkwHhcNMjAxMjIxMDAwMDAwWhcNMjUxMjIxMDAwMDAwWjApMScwJQYDVQQDEx5MaXZlIElEIFNUUyBTaWduaW5nIFB1YmxpYyBLZXkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFT0/0/2qQurnYa0LbJHF9YYozhEH6r9mCxVDBYbewSG4tGgrWpsewQ/96pcczGMQctMvU+h2eX38Hx/f9JAIDbuRQzQlsPhQS7DDZ6WlTXU+t8d/g2C7fpSoLs4KVdJih4xyjLUWj+BK/ijsRjBt4Riw9VbJH/DdWKyoSMbECEiE+s1RtLP/eYoMmNfxyQGqWirCNqVNBTlqzYQp4dgF0foYy4ktoxwmQOVoTcIMFYp1I4pFPI7CxuMLkfK0X7aTbM7YGphvMfJxJkjrQdyI7G5d1t4DNi3zkEbBT7FGAr6qPt3Kn9ralpqJKHdpEBA9N0vNwQo5XTYIhUbPQ16IRAgMBAAGjITAfMB0GA1UdDgQWBBRs7tPmfkksSr67KtElHjYZbeaCTjANBgkqhkiG9w0BAQsFAAOCAQEAJqwMZSjQJ36x+1sty6EeLKQLQewQwPaEC47Zut+8bXed6Q8jMZ0bfa/MM7XquEcabaMZLQuKLft44YXwXXQOfQrI2qjQr3eToJFlDT9hR0rfp9wQqttDxd6Aa6RWwDTgo5oKUQCTKLHhEy8uWzScK0eGt2d7TWTaDXjRSwNq6tM7fRhZs07tKBV3xfi9EQy/mlavAMFRBVm86NSo7AsOG1IOMq03U3ooCWAXh9PdvvHNfHhH19futAnC/HeOjwRF1Qc527aBMphYFQLdiThfmfmiE/AhQqCwZ2oE7uCJhBtR+Kb1ZGhjI35pHfsSqGiFa7Kr+5ave822PDcke89Mvg==</X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<KeyDescriptor use="signing">
<KeyInfo
xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIIC/TCCAeWgAwIBAgIQN/GPegnT8blP2EcSdMMbBzANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDEx5MaXZlIElEIFNUUyBTaWduaW5nIFB1YmxpYyBLZXkwHhcNMjEwMjE4MDAwMDAwWhcNMjYwMjE4MDAwMDAwWjApMScwJQYDVQQDEx5MaXZlIElEIFNUUyBTaWduaW5nIFB1YmxpYyBLZXkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXdLGU2Ll5RPdDUnKQ+f/HS5qiTay2cCh9U2AS6oDM6SOxVhYGtoeJ1VPebcLnpgLfhPxzrwWoVzXSEF+VRQbnYID2Jb4khjgyEeoThk3VqrThwhahpSbBg2vo06vIOp1TS2R1BiwHKTLoB1i1IJnaIFSC3BN6pY4flXWyLQt/5ABXElv2XZLqXM9Eefj6Ji40nLIsiW4dWw3BDa/ywWW0MsiW5ojGq4vovcAgENe/4NUbju70gHP/WS5D9bW5p+OIQi7/unrlWe/h3A6jtBbbRlXYXlN+Z22uTTyyCD/W8zeXaACLvHagwEMrQePDXBZqc/iX2kI+ooZr1sC/H39RAgMBAAGjITAfMB0GA1UdDgQWBBSrX2dm3LwT9jb/p+bAAdYQpE+/NjANBgkqhkiG9w0BAQsFAAOCAQEAeqJfYHnsA9qhGttXFfFpPW4DQLh5w6JCce7vGvWINr5fr1DnQdcOr+wwjQ/tqbckAL2v6z1AqjhS78kbfegnAQDwioJZ1olYYvLOxKoa6HF+b1/p0Mlub8Zukk2n1b2lKPBBOibOasSY7gQDwlIZi7tl9nMTxUfdYK+E5Axv7DVnmUCwcnnpV5/1SFdNyW2kWO4C68rrjMOvECfwrKkbfVJM8f9krEUBuoBF8dTDv7D2ZM4Q2buC70NbfaNWUX0yFvKI0IuTqk8RBfGTRQ4fZAbhMPaykEpBu6dNjTi5YOa0lNqFGS7Ax7leCh5x9lV8elcLkXs8ySo8AOQJk0hgIw==</X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://login.microsoftonline.com/login.srf" />
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://login.microsoftonline.com/login.srf" index="0" isDefault="true" />
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://login.microsoftonline.com/login.srf" index="1" />
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Location="https://login.microsoftonline.com/login.srf" index="2" />
</SPSSODescriptor>
<Extensions>
<alg:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
</Extensions>
</EntityDescriptor>CAS Properties
The attribute released as IDPEmail and the objectGUID should be configured in your ldap authentication handler. In our example it would look similar to this. Note that our example uses a cas.groovy file for properties.
cas.authn.ldap["0"].principalAttributeList="userPrincipalName,objectGUID"
Office365 Federation
To turn on federation in Office365 you should use a non federated admin for any production changes. This will ensure you can rollback your federation settings in the event you break your tenant. If the admin account is federated, it wouldn’t be able to rollback.
Create a PowerShell script to enable federation.
$domainname="test.example.com"
$IssuerUri="https://login.example.com/cas/idp/metadata"
$PassiveLogOnUri="https://login.example.com/cas/idp/profile/SAML2/POST/SSO"
$LogOffUri="https://login.example.com/cas/idp/profile/SAML2/POST/SLO"
$protocol="SAMLP"
$cert="<your signing certificate>"
Set-MsolDomainAuthentication –DomainName $domainname -Authentication Federated -PassiveLogOnUri $PassiveLogOnUri -IssuerUri $IssuerUri -LogOffUri $LogOffUri -PreferredAuthenticationProtocol SAMLP -SigningCertificate $cert Then verify that the identity provider values have been set.
Get-MsolDomainFederationSettings -domain test.example.com**Note that if your domain is already federated, you must first changed federation back to Managed. Then, federate again with the settings defined above. This step is only required if your domain is already federated.
Set-MsolDomainAuthentication –DomainName test.example.com -Authentication ManagedGraph instead of Msol
Microsoft’s Msol functionality will soon be deprecated. Rather than using the previously documented Msol functions, test with the new graph functions.
To get your Microsoft domain federation configuration run this PowerShell command.
Get-MgDomainFederationConfiguration -DomainID example.comTo remove your Microsoft domain federation configuration run this PowerShell command.
Remove-MgDomainFederationConfiguration -DomainID example.comTo update the authentication type to managed run this PowerShell command.
Update-MgDomain -DomainId <domain name> -AuthenticationType "Managed"To set new Microsoft domain federation configuration run this PowerShell command.
New-MgDomainFederationConfiguration -DomainID $domainname $IssuerURI -PassiveSignInURI $PassiveLogOnURI -PreferredAuthenticationProtocol $Protocol -SigningCertificate $certFor either of the remove or set functions you should use a global administrator that isn’t federated. Additionally, you may have to provide scopes when you authenticate.
Connect-MGGraph -Scopes "Domain.ReadWrite.All", "Directory.AccessAsUser.All"Each of these command should be tested in a test environment before running in production.
Conclusion – Apereo CAS Office365 SAML
This article has demonstrated how to perform a SAML integration with Office365 using the Apereo CAS IDP. Let us know in the comments if you have any questions. If you found this article helpful consider reading more of our content on Apereo CAS.
Leave a Reply