• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Mister PKI

SSL Certificates * SSL Tools * Certificate Decoder

  • PKI Training
  • OpenSSL
  • Keytool
  • PKI Tools
    • Apereo CAS
    • SAML
    • OpenID Connect
  • Get expert help

Apereo CAS Office365 SAML

February 17, 2025 by Mister PKI Leave a Comment

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 Managed

Graph 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.com

To remove your Microsoft domain federation configuration run this PowerShell command.

Remove-MgDomainFederationConfiguration -DomainID example.com

To 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 $cert

For 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.

Apereo CAS,  Identity Management,  saml

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Popular Posts

PKCS12

openssl s_client

Keytool

Keytool list

ECDSA vs RSA

OpenSSL

PKCS7

Certificate Decoder

PKI for DevOps Engineers – Free Training Series

PKI for DevOps Training Hub

Lesson 1 – How TLS and PKI Work

Lesson 2 – Understanding X.509 Certificates

Lesson 3 – Certificate Chains Explained

Lesson 4 – Debug TLS with OpenSSL

Lesson 5 – Verify Certificate Chains

Lesson 6 – Creating CSRs with OpenSSL

Lesson 7 – Working with PKCS12 Certificates

Lesson 8 – Java Keystores and keytool

Lesson 9 – Certificate Expiration Monitoring

Lesson 10 – Automating Certificate Renewal

Lesson 11 – Common TLS Errors

Lesson 12 – PKI Architecture for DevOps

Recent Posts

  • Apache mod_auth_cas: Protect Web Applications with Apereo CAS and Docker
  • Apache mod_auth_mellon: Configure SAML SSO & Docker
  • Configure OpenID Connect (OIDC) in Apereo CAS 7.3 and 8
  • Certificate Ownership Is an Operating Model Problem, Not a Tooling Problem
  • OpenSSL dgst: Create Checksums and Verify Digital Signatures

Footer

  • Twitter
  • YouTube
Mister PKI

Practical security engineering for the systems that establish trust.

Learn OpenSSL Keytool Free training
Work together PKI consulting CAS consulting Sponsored contributions
Site About Support Mister PKI Cookie policy Search
© 2026 Mister PKI Secure systems. Clear guidance.