Apereo CAS - SAML2 Metadata with MongoDb


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.

MongoDB is a free and open-source cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with schemata and is supported in CAS in many different ways. In this walkthrough, we are going to take a pass at getting CAS connected to MongoDB to store SAML2 identity provider and service provider metadata documents.

Our starting position is based on the following:

MongoDB

To run MongoDB for development and testing, we can use the provided Docker image:

docker run -d -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=root \
  -e MONGO_INITDB_ROOT_PASSWORD=secret --name="mongodb-server" mongo:4.0-xenial
docker ps

This runs a MongoDB database server which is useful for development but SHOULD NOT be used in production.

To access the MongoDB instance using a UI, run:

docker run --link mongodb-server -d -p 8081:8081 \
  -e 'ME_CONFIG_MONGODB_ADMINUSERNAME=root' \
  -e 'ME_CONFIG_MONGODB_ADMINPASSWORD=secret' \
  -e 'ME_CONFIG_MONGODB_SERVER=mongodb-server' mongo-express

The ME_CONFIG_MONGODB_SERVER is the address of the docker container that runs the MongoDB server. By default, Docker containers use the container as the DNS host name. So we can just specify the mongodb-server the name of the container that runs our MongoDB instance.

Shell into the container:

CID=docker ps -aqf name=mongodb-server
docker exec -it $CID /bin/bash

When inside the container:

mongo --host mongodb://root:secret@localhost:27017
use database cas;

# Create a database user for authentication
db.createUser({user:"casuser", pwd:"Mellon", roles: ["readWrite", "dbAdmin"]})

Point your browser to http://localhost:8081 and let’s create a collection called cas-saml-sp-metadata with the following document:

image

Note the value field which contains a base64-encoded version of the metadata for a SAML2 service provider which makes it easier to get the metadata added to the MongoDB document. I am also skipping over the metadata signature that would have been used to validate its integrity and that could have just as easily been added to the document using a signature field.

That should do for now. Let’s get CAS running.

CAS

SAML2 Service Provider Metadata

So in order to enable a CAS integration with MongoDB directly, you want to start with the CAS Overlay, clone the project and follow the notes here to get CAS acting as SAML2 identity provider. In its simplest form, it comes to down to 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/config/saml

…and this module in the CAS build:

compile "org.apereo.cas:cas-server-support-saml-idp:${project.'cas.version'}"

To keep things simple, we could use the JSON service registry to manage our SAML2 service provider definitions. Here is what our service definition might look like for SAML2 service provider in a SAML-1.json file:

{
  "@class" : "org.apereo.cas.support.saml.services.SamlRegisteredService",
  "serviceId" : "<your-sp-entity-id>",
  "name" : "SAML",
  "id" : 1,
  "description" : "This SP has its metadata in MongoDB somewhere.",
  "metadataLocation" : "mongodb://"
}

The metadata location in the registration record above simply needs to be specified as mongodb:// to signal to CAS that SAML metadata for our service provider must be fetched from MongoDB data sources defined in CAS configuration. As the next step, let’s teach CAS) about our MongoDB setup. Just like before, you’d need this module in your CAS build:

compile "org.apereo.cas:cas-server-support-saml-idp-metadata-mongo:${project.'cas.version'}"

…and CAS needs to know how to connect to MongoDB to fetch stuff:

cas.authn.samlIdp.metadata.mongo.host=localhost
cas.authn.samlIdp.metadata.mongo.port=27017
cas.authn.samlIdp.metadata.mongo.userId=casuser
cas.authn.samlIdp.metadata.mongo.password=Mellon
cas.authn.samlIdp.metadata.mongo.collection=cas-saml-sp-metadata
cas.authn.samlIdp.metadata.mongo.databaseName=cas

That’s it. Build and run CAS. At this point, you should be able to log into service provider successfully whose metadata is fetched and processed by CAS from MongoDB.

SAML2 Identity Provider Metadata

If you examine your CAS startup logs, you might notice the following statement:

[...FileSystemSamlIdPMetadataLocator] - <Metadata directory location is at [/etc/cas/config/saml]>

…which matches our setting above:

cas.authn.samlIdp.metadata.location=file:/etc/cas/config/saml

Metadata artifacts that belong to CAS as a SAML2 identity provider may also be managed and stored via MongoDb. This includes things such as the metadata XML document, signing and encryption keys, etc. While CAS has the ability to generate brand new metadata in MongoDB, let’s instead figure out how our existing metadata might be relocated to MongoDB.

Let’s create a MongoDB collection called saml-idp-metadata in our cas database to hold IdP artifacts with the following document in it:

{
    "signingCertificate": "...",
    "signingKey": "...",
    "encryptionCertificate": "...",
    "encryptionKey": "...",
    "metadata": "..."
}

Here is the drill:

  • The metadata, signing and encryption certificates may be base64-encoded.
  • The signing and encryption keys MUST be signed and encrypted using CAS crypto settings and keys.

The signing secret key and the encryption secret key are both JWKs of size 512 and 256. We can use the command-line shell to create the two keys:

cas> generate-key key-size 512
$signingKey
cas> generate-key key-size 256
$encryptionKey

Once you have the keys, you can try to secure the metadata keys:

cas> cipher-text file /etc/cas/config/saml/idp-signing.key signing-key $signingKey encryption-key $encryptionKey
...
cas> cipher-text file /etc/cas/config/saml/idp-encryption.key signing-key $signingKey encryption-key $encryptionKey
...

The signing and encryption SAML2 metadata keys plus the base64-encoded versions of the signing and encryption certificates and the metadata XML can next be put into the MongoDB document.

image

CAS settings will then take on the following form:

# cas.authn.samlIdp.metadata.location=file:/etc/cas/config/saml
cas.authn.samlIdp.metadata.mongo.idpMetadataCollection=saml-idp-metadata
cas.authn.samlIdp.metadata.mongo.crypto.encryption.key=$encryptionKey
cas.authn.samlIdp.metadata.mongo.crypto.signing.key=$signingKey

Build and run CAS. At this point, you should be able to log into the service provider successfully with CAS using its own SAML2 metadata from MongoDB to produce a SAML2 response, etc.

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 RC3 Feature Release

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

Apereo CAS 6.1.x - Credential Caching & Proxy AuthN

Learn how you may configure Apereo CAS to capture and cache the credential's password and the proxy-granting ticket in proxy authentication scenarios, pass them along to applications as regular attributes/claims. We will also be reviewing a handful of attribute release strategies that specifically affect authentication attributes, conveying metadata about the authentication event itself.

Apereo CAS 6.1.x - Attribute Repositories w/ Person Directory

An overview of CAS attribute repositories and strategies on how to fetch attributes from a variety of sources in addition to the authentication source, merge and combine attributes from said sources to ultimately release them to applications with a fair bit of caching.

Apereo CAS 6.1.x - Building CAS Feature Modules

An overview of how various CAS features modules today can be changed and tested from the perspective of a CAS contributor working on the codebase itself to handle a feature request, bug fix, etc.

CAS 6.1.0 RC2 Feature Release

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

Apereo CAS - Riffing on Attribute Release Policies

Learn how to release the kraken of attributes to CAS clients, relying parties and service providers using a variety of attribute release policies and authentication protocols, sampled and collected here to fun and profit.

Apereo CAS - Delegated Authentication to SAML2 Identity Providers

Learn how your Apereo CAS deployment may be configured to delegate authentication to an external SAML2 identity provider.

Apereo CAS - Custom Login Fields w/ Dynamic Bindings

Learn how to extend the Spring Webflow model to add custom fields to the CAS login form and the authentication process and take advantage of the additional user-provided data in customized authentication handlers.

Apereo CAS as an OAuth2 Authorization Server

Learn how to configure CAS as an OAuth2 Authorization Server and configure Spring Boot client app to work with it

Apereo CAS - SAML2 Identity Provider Integration w/ Gitlab (also staring HAProxy and LDAP)

Learn how Apereo CAS may act as a SAML2 identity provider for Gitlab and run everything locally on a workstation with Docker and Java.