Apereo CAS - SAML2 Identity Provider Integration w/ InCommon


Collaborate
The blog is managed and hosted on GitHub. If you wish to update the contents of this post or if you have found an inaccuracy and wish to make corrections, we recommend that you please submit a pull request to this repository.

Apereo CAS, acting as a SAML2 identity provider, has the capability to integrate with SAML2 service providers from metadata aggregates such as InCommon. To handle these types of integrations successfully, one must note that CAS services (aka relying parties) are fundamentally recognized by service identifiers taught to CAS typically via regular expressions using the serviceId field. This allows for common groupings of applications and services by URL patterns (i.e. Everything that belongs to example.org is registered with CAS). A bilateral SAML2 SP integration is fairly simple in this regard as one might find an easy one-to-one relationship between a serviceId from CAS and the entityId from a SAML2 SP. With aggregated metadata, this behavior becomes more complicated since a CAS relying-party definition typically represents a single group of applications while aggregated metadata, given its very nature, represents many different SAML2 services from a variety of organizations and domains.

In this tutorial, we are going to review a number of use cases dealing with multilateral integrations from the SAML2 metadata aggregate offered by InCommon. We will also briefly address configuration of various attribute release policies, specifically those that may belong to the Research and Scholarship group of service providers expecting a standard pre-defined bundle of attributes.

Our starting position is based on the following:

CAS Configuration

In order to allow CAS to become a SAML2 identity provider, the overlay needs to be prepped based on the instructions provided here. Remember to add the relevant module to the overlay along with the list of required build repositories.

The SAML2 IdP configuration will need to minimally match the following settings:

cas.authn.samlIdp.entityId=https://sso.example.org/idp
cas.authn.samlIdp.scope=example.org
cas.authn.samlIdp.metadata.location=file:/etc/cas/saml

You will, of course, need to adjust your entityId and scope as needed. Upon startup, CAS will attempt to generate the appropriate metadata based on provided settings and produced artifacts will be placed at /etc/cas/saml. Of course, the running CAS process will need to have the right permissions in order to create this directory and the contents within it. Furthermore, to keep things simple, this post will assume that CAS is already configured to use LDAP authentication and is set to fetch all needed attributes such as givenName, eduPersonPrincipalName from LDAP, etc. We shall also assume that relying party registration records are handled in CAS via the JSON Service Registry.

Relying-Party Integrations

Let’s consider the following fictitious use cases:

Service Provider Entity ID Expected Attributes
Almond almond.example.org InCommon R&S bundle, department, title
Coconut coconut.example.org givenName, title
All Others * InCommon R&S bundle, REFEDS R&S bundle

The above relying parties may be registered with CAS using the following sample records. As you browse through, you should pay attention to the following:

  • There is a fair amount of duplication when it comes to the definition of the metadata location and anything else applicable to fetching, parsing and validating the metadata such as the signing signature, etc. Solutions to this issue to simplify maintenance and remove duplication may be worked out in future CAS releases.
  • The metadata is downloaded once and cached, even though it is repeatedly specified for all relying parties. Caching rules are controlled by the service provider metadata tags, and/or the CAS service definition for that service provider as an override.
  • Given a service definition file typically is entirely self-contained, a certain number of attribute release policies may need to be repeated in the event that a relying party definition needs to override or complement the default catch-all policy. Solutions to this issue to simplify maintenance and remove duplication may be worked out in future CAS releases.

Almond Service Registration

{
  "@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
  "serviceId": "almond.example.org",
  "name": "almond",
  "id": 1,
  "evaluationOrder": 1,
  "metadataLocation": "https://[metadata-aggregate-address].xml",
  "attributeReleasePolicy": {
    "@class": "org.apereo.cas.services.ChainingAttributeReleasePolicy",
    "policies": [
      "java.util.ArrayList",
      [
        { "@class": "org.apereo.cas.support.saml.services.InCommonRSAttributeReleasePolicy" },
        {
          "@class": "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy",
          "allowedAttributes" : [ "java.util.ArrayList", [ "department", "title" ] ]
        }
      ]
    ]
  }
}

Coconut Service Registration

{
  "@class" : "org.apereo.cas.support.saml.services.SamlRegisteredService",
  "serviceId" : "coconut.example.org",
  "name" : "coconut",
  "id" : 2,
  "evaluationOrder": 2,
  "metadataLocation": "https://[metadata-aggregate-address].xml",
  "attributeReleasePolicy" : {
    "@class" : "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy",
    "allowedAttributes" : [ "java.util.ArrayList", [ "givenName", "title" ] ]
  }
}

All Others

Note the serviceId field here contains a regular expression that is very friendly to all relying parties. The evaluationOrder field is set to a sufficiently large number to ensure this definition is considered very late into the process.

{
  "@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
  "serviceId": ".+",
  "name": "All",
  "id": 3,
  "evaluationOrder": 10000,
  "metadataLocation": "https://[metadata-aggregate-address].xml",
  "attributeReleasePolicy": {
    "@class": "org.apereo.cas.services.ChainingAttributeReleasePolicy",
    "policies": [
      "java.util.ArrayList",
      [
        { "@class": "org.apereo.cas.support.saml.services.InCommonRSAttributeReleasePolicy" },
        { "@class": "org.apereo.cas.support.saml.services.RefedsRSAttributeReleasePolicy" }
      ]
    ]
  }
}

Metadata Administration

There is also the ability to observe and manage the service provider metadata cache administratively, using a dedicated actuator endpoint.

HA Deployments
Note that the state of the cache belongs to the CAS server node's JVM memory; it's not distributed. In an HA environment, you'd need to bypass load balancers, etc to reach the actual CAS server node(s) before the cache can be accessed.

Let’s demonstrate this with a few examples:

  • Retrieve the current state of the service provider metadata cache for coconut:
curl -k -X GET https://sso.example.org/cas/actuator/samlIdPRegisteredServiceMetadataCache?serviceId=All'&'entityId=coconut.example.org

Likewise, the following command may do just as well:

curl -X GET https://sso.example.org/cas/actuator/samlIdPRegisteredServiceMetadataCache?serviceId=coconut
  • Invalidate the current state of the service provider metadata cache for coconut:
curl -X DELETE https://sso.example.org/cas/actuator/samlIdPRegisteredServiceMetadataCache?serviceId=coconut
  • Invalidate the current state of the service provider metadata cache:
curl -X DELETE https://sso.example.org/cas/actuator/samlIdPRegisteredServiceMetadataCache

Better details may be found here.

Finale

I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please feel free to engage and contribute as best as you can.

Misagh Moayyed

Related Posts

CAS 6.1.0 RC5 Feature Release

...in which I present an overview of CAS 6.1.0 RC5 release.

Apereo CAS - Are We Logged In Yet?

Learn how to modify and extend a CAS deployment to determine whether an SSO session is still valid and tied to a user authentication session.

Apereo CAS - REST API Integrations

Learn how to integrate with CAS using its REST API to authenticate, exchange tickets and get access to user profiles and attributes.

CAS 6.1.0 RC4 Feature Release

...in which I present an overview of CAS 6.1.0 RC4 release.

Apereo CAS - Multifactor Provider Selection

Learn how to configure CAS to integrate with and use multiple multifactor providers at the same time. This post also reveals a few super secret and yet open-source strategies one may use to select appropriate providers for authentication attempts, whether automatically or based on a menu.

Apereo CAS - Dockerized Hazelcast Deployments

Learn how to run CAS backed by a Hazelcast cluster in Docker containers and take advantage of the Hazelcast management center to monitor and observer cluster members.

Apereo CAS - Configuration Security w/ Jasypt

Learn how to secure CAS configuration settings and properties with Jasypt.

CAS 6.1.0 RC3 Feature Release

...in which I present an overview of CAS 6.1.0 RC3 release.

Apereo CAS - Webflow Decorations

Learn how you may decorate the Apereo CAS login webflow to inject data pieces and objects into the processing engine for display purposes, peace on earth and prosperity of all mankind, etc. Mainly, etc.

Apereo CAS - SAML2 Metadata Query Protocol

Learn how you may configure Apereo CAS to fetch and validate SAML2 metadata for service providers from InCommon's MDQ server using the metadata query protocol.