Skip to content

SAML-based Single Sign-On

This section will describe how to enable and use SAML single sign-on.

API Access for SAML

In dr-provision versions 4.8.0 and later, the DRP server provides the following endpoints for SAML Single Sign-On.

Endpoint Purpose
/login Starts the SP-initiated SAML flow and returns a DRP token
/logout Clears the local SAML session cookie
/saml/list Lists the configured Identity Providers
/saml/metadata Serves the DRP Service Provider metadata
/saml/acs Assertion Consumer Service; receives the IDP's SAML response

Login

By pointing a browser at https://drp-ip:api-port/login, the server will redirect the user to the identity provider for authentication. Once this is complete, the login page will return a token and info structure by default.

Additionally, the login endpoint uses two query parameters to provide additional customizations.

  • SAML-IDP= - The IDP is the name of one of the configured Identity Providers.
  • redirect= - The redirect option takes a base64 encoded URL that should be redirected to upon success. A DRP token is appended to the URL as a query parameter.

List

By pointing a browser at https://drp-ip:api-port/saml/list, a list of SAML Identity Providers is returned. This is a smaller list from the Identity Provider objects. The object contains:

  • Name - the name of the IDP to use in the SAML-IDP query parameter
  • DisplayName - A display name to use for presenting to the user.
  • LogoPath - A path or URL to a logo image. If the PATH is a full URL, this will be an image. If the PATH is relative, the file is served from DRP files directory.

These fields map directly to the Identity Provider fields.

The response is a JSON array sorted by Name, served with the content type application/samllist+json.

Only Identity Providers whose metadata was successfully loaded appear in this list. An IDP whose metadata could not be fetched or parsed is omitted (see Troubleshooting Tips).

Logout

https://drp-ip:api-port/logout deletes the local SAML session cookie and returns 200.

Logout is local to DRP only

/logout does not perform SAML Single Logout. The DRP Service Provider metadata advertises a SingleLogoutService endpoint, but the server does not implement it. Configuring Single Logout at the Identity Provider will not sign the user out of DRP, and /logout will not sign the user out of the Identity Provider. Any DRP token already issued remains valid until it expires or until that user's next SAML login regenerates their secret (see User Provisioning).

Service Provider Behavior and Limits

The DRP Service Provider is configured by the server and is not tunable through the Identity Provider object. These constraints affect how you configure the IDP side.

Behavior Value Implication for IDP configuration
Signed authentication requests Disabled Do not require a signed AuthnRequest at the IDP
Forced re-authentication Disabled DRP never sets ForceAuthn
Encrypted assertions Supported Optional; DRP publishes an encryption key in its metadata
IDP-initiated SSO Not allowed Users must start at /login; IDP dashboard tiles and app links return 403
SAML Single Logout Not implemented See the warning above
DRP token lifetime 1 hour Not configurable; independent of the IDP session lifetime

DRP only accepts service-provider-initiated logins. Testing an application by clicking its tile in an Identity Provider's dashboard is an IDP-initiated login, and the assertion is rejected with 403 at /saml/acs. Always begin at https://drp-ip:api-port/login?SAML-IDP=<IDP> or use the IDP button on the DRP UX login page.

The SAML-IDP value must name a loaded Identity Provider. If it does not match one, DRP redirects to an arbitrarily chosen Identity Provider instead of reporting an error, so verify the name against /saml/list when a login goes somewhere unexpected.

UX Access by SAML

The UX login page presents the standard authentication page. If Identity Providers have been configured and functional, the UX login page will have additional buttons for each of IDP. The UX will redirect the user to the SAML page for authentication. Upon completion, the UX is redirected to the UX system with a DRP token for normal operations.

Identity Provider Configuration

To enable SAML-based Single Sign-On, the system must have ONE or more Identity Provider configured. This configuration requires configuring the IDP with the DRP server's metadata and vice versa.

The SAML Single Sign-On uses the API server's certificate and key for identity. If this certificate/key pair is changed, the metadata at the IDP must be updated.

Register DRP with IDP

The DRP server must be registered with the IDP. Registration requires two distinct values, and DRP derives them from separate precedence chains. Setting only one of them is the most common cause of SAML login failures.

The identity (entityID) of the DRP server is the first configured value in order:

Order Source Environment variable
1 Server Host Name RS_SERVER_HOSTNAME
2 HA Id RS_HA_ID
3 DRP Id RS_DRP_ID

The host name used to build the endpoint URLs (the ACS URL and the metadata URL) is the first configured value in order:

Order Source Environment variable
1 Server Host Name RS_SERVER_HOSTNAME
2 HA Virtual Address none
3 Server listen address none
4 localhost none

Set RS_SERVER_HOSTNAME

RS_SERVER_HOSTNAME is the only value that appears at the top of both chains, so setting it makes the entityID and the endpoint URLs agree. Without it, the entityID falls back to an HA or DRP Id while the URLs fall back to an IP address, and the two will not match what you register at the IDP. See Customizing the server at launch time.

The virtual and listen addresses affect only the endpoint URLs. They are never used as the entityID.

IPv6 listen addresses

Colons in the host name are replaced with - when the endpoint URLs are built. If DRP falls back to an IPv6 listen address, the resulting URLs will not be usable. Set RS_SERVER_HOSTNAME in IPv6 deployments.

With the identity established, registration can be done one of two ways.

For some IDPs, they can be given a URL to get the metadata automatically. The metadata URL is https://drp-ip:api-port/saml/metadata. Entering this URL into the IDP will cause the IDP to query the DRP Server for the required certificate and identity information.

The other is to save the metadata into a file. This file will be XML data that can be upload to your identity provider.

Bash
curl -k https://drp-ip:api-port/saml/metadata -o metadata.xml

This metadata.xml file can be upload to your identity provider. The file can be reused for all Identity Providers.

Register IDP with DRP

This requires creating an Identity Provider in the DRP system. This can be either done through the UX or the CLI.

The required fields for the IDP are:

  • Name - this is the short name of the IDP.
  • DisplayName - this is the displayed name for us in the UX
  • LogoPath - this is an optional URL or relative file path into the DRP server. It presents an image for display.
  • MetaDataUrl - This the URL to the IDP's metadata.
  • MetaDataBlob - This is the XML file from the IDP stored as a string on the object.

All Identity Provider metadata is reloaded at server startup and again whenever any Identity Provider is created, updated, or removed, including by a content pack load. MetaDataBlob is parsed in place; MetaDataUrl is fetched from the DRP server at that time.

MetaDataUrl takes precedence. If both fields are set, MetaDataBlob is ignored. Set exactly one.

Unreachable metadata fails silently

If a MetaDataUrl cannot be fetched, or metadata cannot be parsed, that Identity Provider is skipped and the failure is recorded only in the server log. The Identity Provider object itself shows no error, and the IDP simply does not appear in /saml/list or on the UX login page. Check the server log for Failed to get metadata or Failed to parse metadata blob when a configured IDP does not appear. Because the DRP server performs this fetch, the metadata URL must be reachable from the DRP server, not just from your browser.

Once both steps are done, SAML can be used for authentication.

Additional Customization

Each Identity Provider in DRP will also define the access control path for the authenticated users.

There are two attributes that are delivered by the SAML Assertions. The first attribute is used to define the username. This is the UserAttribute field. This maps the SAML IDP identity into the Name of a User. This is usually an email for ease of use, but is not required. If the attribute carries more than one value, only the first is used.

Which attribute identifier to use

UserAttribute and GroupAttribute are matched against each assertion attribute's FriendlyName when the IDP supplies one, and against its Name otherwise.

The second attribute is used to define groups that should apply to the user. This is the GroupAttribute field.

Groups must be a multi-valued attribute

The IDP must emit the group attribute as a multi-valued SAML attribute, with one group name per attribute value. DRP reads the attribute's values directly and does not split them on any delimiter.

The Identity Provider has three additional fields that control what access the user should have.

  • DenyIfNoGroups - If no groups are present or none match, access is denied that user.
  • DefaultRole - This is the default role that should be given to the User if no groups match. The DenyIfNoGroups overrides this.
  • GroupToRoles - This is a map of group names to lists of roles. It is a key value pair, where the key is the group name and the value is a list of roles to apply.

A user receives the union of the Roles mapped from all of their matching groups.

User Provisioning

DRP creates and maintains a User object for each SAML identity automatically. On every successful SAML login, DRP builds a User object from the assertion and writes it, creating the User if it does not already exist.

The written object contains only the name taken from UserAttribute, the Roles resolved from GroupToRoles (or DefaultRole), and the Meta keys listed below. It replaces the stored User rather than merging into it.

SAML login overwrites the whole User object

Because the object is replaced, every login discards any other state on that User. Do not reuse a name that already belongs to a local password user as a SAML UserAttribute value.

The Meta keys written on each login are useful for auditing and troubleshooting:

Meta key Contents
auth-method Always saml for SAML logins
saml-auth Name of the Identity Provider that authenticated the user
auth-groups Comma-joined list of groups received in the assertion
auth-last Unix timestamp of the most recent SAML login

auth-groups records the groups as they arrived, which makes it the quickest way to confirm whether the IDP is sending the group names you expect.

Every Role named in GroupToRoles and DefaultRole must already exist in DRP. Writing the User fails if any resolved Role is undefined, and the login fails with it.

Identity Provider Examples

AWS

An example yaml file for AWS:

YAML
---
DefaultRole: "superuser"
DenyIfNoGroups: false
DisplayName: AWS IAM
GroupAttribute: "groups"
GroupToRoles:
  role1:
    - operator
  role2:
    - superuser
MetaDataUrl: https://portal.sso.us-west-2.amazonaws.com/saml/metadata/Nzg0NDI0NjE0NTk2X2lucy03MjJmMGU0NjQ5OTRiNzNk
Name: aws-west-2
UserAttribute: "username"

Google

For Google, you will need to use go to your Google Workspace Admin page. Navigate to App -> Web and mobile apps.

You will need to "Add app -> Add custom SAML app". You will need to specify an app name, this can be anything along with a description.

At this point, you can download metadata. The contents of this file will need to be added to your IDP object as a MetadataBlob.

With that set, the next pieces to fill in are the ACS URL and the Entity ID. This can be found by selecting Download Metadata in the DRP UX. This file contains the EntityID. This is the value can be found here or the order is defined above. The ACS URL is specified near the end of the line. It looks like this:

HTML
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                          Location="https://webhook.rackn.io:8092/saml/acs" index="1"></AssertionConsumerService>

The URL is usually <https://><server name or ip>:<api port>/saml/acs. If the ServerHostname is specified, it will be used. Otherwise, it will be the IP address of the DRP endpoint.

Specify the Name ID format as email. This must be specified, but isn't really used. The registered attributes in the next section as used for group matching.

Add Mapping attributes for the username. Click Add Mapping, select primary email and name the attribute email. Add Mapping attributes for group memberships. Select the groups you want to map to the groups attribute in the bottom section.

Click Finish.

In DRP, create an IDP object for Google. It would look like this:

YAML
DefaultRole: ''
DenyIfNoGroups: true
DisplayName: RackN Google Auth
GroupAttribute: groups
GroupToRoles:
  Engineering:
    - superuser
LogoPath: https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/240px-Google_%22G%22_Logo.svg.png
MetaDataBlob: blob from google
Name: GoogleAuth
UserAttribute: email

Note that UserAttribute matches the attribute containing the email of the user. Note that GroupAttribute matches the attributing containing groups list.

There are some issues with this integration. You will have to clear current google token/auth cookies to get new enabled cookies from Google. Additionally, if you have multiple google accounts, you may have to log out of the accounts that you don't want to use to login. Using an incognito window can help this.

Okta

First collect the DRP entityID and ACS URL, because Okta needs both and they must match exactly. Download the Service Provider metadata and read the values from it:

Bash
curl -k https://drp-ip:api-port/saml/metadata -o metadata.xml

The entityID is the attribute on the root EntityDescriptor element. The ACS URL is the Location attribute of the AssertionConsumerService element, normally https://<server name or ip>:<api port>/saml/acs.

In the Okta Admin Console, create an app integration with the following settings:

Okta field Value
Single sign-on URL The ACS URL from the DRP metadata
Audience URI (SP Entity ID) The entityID from the DRP metadata
Name ID format EmailAddress
Application username Email

Name ID must be set, but DRP does not use it for identity. The attributes configured below are what determine the username and groups.

Under Attribute Statements, add the attribute DRP will read as the username:

Name Name format Value
email Unspecified user.email

Under Group Attribute Statements, add the attribute DRP will read as group memberships. Use a filter that matches the groups you intend to map:

Name Name format Filter
groups Unspecified Matches regex with .*

A Group Attribute Statement emits one attribute value per group, which is the multi-valued form DRP requires. Narrow the regex if you do not want every Okta group sent in the assertion.

Leave request signing off. DRP does not sign authentication requests, so do not enable a signature requirement on the Okta side. Encrypted assertions are supported and may be enabled if your policy requires them.

Finish the wizard, then assign the app to the users and groups that should have DRP access. On the app's Sign On tab, use the SAML setup instructions or the metadata link to obtain the Okta IDP metadata URL.

In DRP, create the Identity Provider object:

YAML
---
DefaultRole: ''
DenyIfNoGroups: true
DisplayName: Okta
GroupAttribute: groups
GroupToRoles:
  drp-admins:
    - superuser
  drp-operators:
    - my-operator-role
LogoPath: ''
MetaDataUrl: https://<your-org>.okta.com/app/<app-label>/<app-id>/sso/saml/metadata
Name: okta
UserAttribute: email

DRP ships only two built-in Roles, superuser and discovery. my-operator-role above stands in for a Role you have already created (see Role). Mapping a group to a Role that does not exist causes the login to fail.

Take the MetaDataUrl value from the app's Sign On tab rather than assembling it by hand; the path includes both the app label and the app ID.

UserAttribute and GroupAttribute must match the attribute names configured in the Okta app, not the Okta source fields. Okta does not send a FriendlyName, so the configured name is what DRP matches on. The keys under GroupToRoles are Okta group names as they appear in the assertion, and every Role they map to must already exist in DRP.

Do not test by clicking the app tile in the Okta dashboard or End-User Portal. That is an IDP-initiated login, which DRP rejects. Test from the DRP UX login page, or by browsing directly to https://drp-ip:api-port/login?SAML-IDP=okta. See Service Provider Behavior and Limits.

Troubleshooting Tips

Troubleshooting issues with the SAML configuration requires some special tools. The RackN support team finds SAML Tracer very useful. It is a plugin for Firefox and Chrome that will allow an operator to debug the payloads coming and going from the Identity Provider and the Service Provider (dr-provision).

The most common problem the RackN support team encounters with customers trying to use SAML is the entityID in the Service Provider metadata not matching what is entered into the Identity Provider. This must match or the browser will end up in a loop unable to log in. The best way to set the entityID of the dr-provision Service Provider is to set the RS_SERVER_HOSTNAME environment variable in the systemd config files.

Example:

Bash
cat /etc/systemd/system/dr-provision.service.d/user.conf

[Service]
Restart=always
User=root
Group=root
Environment=RS_BASE_ROOT=/var/lib/dr-provision
Environment=RS_SERVER_HOSTNAME=MY_HOST_NAME
This would cause the entityID on the endpoint to report "MY_HOST_NAME".

Always confirm the value DRP is actually publishing rather than assuming it, since the entityID and the endpoint URLs are derived from different fallback chains:

Bash
curl -k https://drp-ip:api-port/saml/metadata