# SAML Inbound Security Module

The SAML Inbound Security module can be used to provide user authentication and authorization to interactive endpoints in Smile CDR, such as the Web Admin Console or FHIRWeb Console.

The SAML Specification covers many use cases and patterns. Not all of these patterns are relevant to Smile CDR however. The supported parts of the SAML specification are described here.

# SAML 2.0 Authentication Request Protocol

The **SAML 2.0 Authentication Request Protocol** is used to authenticate and authorize users to an interactive application (i.e. not a system making an API call but rather a human user signing into an application of some sort). For example, SAML Authentication Request Protocol can be used to secure access to the Smile CDR Web Admin Console module, but it cannot be used to secure access to a FHIR Endpoint.

If you are already familiar with how SAML works, you may skip this section and skip to [Enabling SAML Auth](/content/docs/security/saml_inbound_security_module.html#enabling/index.html).

**Step 1: Authentication Request Initial Launch**
This flow begins with the user initiating a SAML Authentication Request. There are two ways to launch it:

- **Login page button** – When SAML is enabled on a Web Admin Console module, the console login page displays a **Sign in with SSO** link that initiates this flow. The text of this link can be customized using the Web Admin Console  [SSO Button Label](/content/docs/configuration_categories/admin_web_console_config.html#signin.sso_button_label/index.html) setting.

- **Direct URL** – If the Web Admin Console is on port 9100, the following URL can be used to request a SAML authentication flow. SMILECDR is the Identity Provider's registration id. It is configured in SAML and set in the Service Provider (Smile CDR).
[https://example.com:9100/saml2/authenticate/SMILECDR](https://example.com:9100/saml2/authenticate/SMILECDR)

**Step 2: Redirect to IDP**

The module will immediately redirect the user's browser session to the IDP server using a URL similar to the following. Note that parameter values have been truncated for readability.
[http://some.idp/websso?SAMLRequest=fZJfT8IwFMW%2FSnPfy7oNyGwYBkUj&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=UADfIst0h6eLWdFAKdP%2FMURoc2QW%2F46U7Ok%2FXROXDousJkhMPXBeiVYSryb](http://some.idp/websso?SAMLRequest=fZJfT8IwFMW%2FSnPfy7oNyGwYBkUj&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=UADfIst0h6eLWdFAKdP%2FMURoc2QW%2F46U7Ok%2FXROXDousJkhMPXBeiVYSryb)

The `SAMLRequest` parameter contains a SAML Request XML document that has been serialized, deflated, and base64 encoded. Decoding this parameter yields a document similar to the following:

```xml
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                     AssertionConsumerServiceURL="https://example.com:9100/login/saml2/sso/SMILECDR"
                     Destination="http://some.idp/websso"
                     ForceAuthn="false"
                     ID="ARQb35c288-3888-43ee-990b-2d0418f231fa"
                     IsPassive="false"
                     IssueInstant="2020-08-03T00:46:56.121Z"
                     ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                     Version="2.0">
   <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://example.com:9100/saml2/service-provider-metadata/SMILECDR</saml2:Issuer>
</saml2p:AuthnRequest>
```

Copy

**Step 3: Authentication with IDP**
At this point, the user has been redirected to the IDP server. It may ask for credentials, or it may use an existing SSO session. Assuming the IDP server wishes to grant the user access to the requested Service Provider, it will generate and sign a SAML XML document called a **Response**.
**Step 4: Redirect to Service Provider**
Next, the IDP will direct the user back to the Service Provider and will include a SAML Response document as a part of the redirect. This is typically performed using an HTML FORM with a POST action that is automatically submitted. The following is an example of a SAML Response document:

```xml
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Version="2.0" ID="12345" IssueInstant="2020-08-03T00:46:56.397Z">
  <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://example.com/idp</saml2:Issuer>
  <saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></saml2p:Status>
  <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="assertion-id-1234" IssueInstant="2020-08-03T00:46:56.397Z" Version="2.0">
    <saml2:Issuer>http://example.com/idp</saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <ds:SignedInfo>
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <ds:Reference URI="#assertion-id-1234">
          <ds:Transforms>
            <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xsd"/></ds:Transform>
          </ds:Transforms>
          <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <ds:DigestValue>4+090Sm0RWBVi82T92jqco4rQyyaDnWYdxcWfObQuAs=</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>
        LHiJn4R6GmjuImJHbO69eLUHGSZqYHDwMmDn1tUYltAHa6Y956VK5CzN/IJT6UpZ0QkzUVRpNCs9&#xD; rwKbrNwPuuG4f9n0xdl06vJ/wsT6VS77UMDCz8OUOzKv7CIKWfWdtrRKoqiO8Q8ELkByRAXL6bOS&#xD; s8/n6cWKmLYebLfV3X5glgVilzFEpa173s+EU7RjBVJ1z96Aqqcmsc1+BOfb1v2ZFIAUFX3Jl5jy&#xD;
        LLnB/pUqQV5RNLCryyB+JY4Nv/MVKBcVI1ym5hWTp8ISg6Y7fqdF7V1VKXD29GfEMIDxHYmma4Xz&#xD; VjUCoXgAa92S5X2xwxHFULqpnVwRxROyEdMAMYw6zlaGw7oeRjD+ham/38KB2GBO456eeGsj4Gh/&#xD; RjlvE4maDBHyuW0dDZRK6wuKUoAN/FD3nFDiygzZFG0XIixKoHGq/OQTdLqUNvVW/8qZ0enEmxfk&#xD;
        Uq6MJvujytd2igyZcEpj67fp4ZCNK/BUdGAom/HSIilav+1B3Y/upzx+txyzAxQzF+0etvNZ+1MP&#xD; QVkd9T+dfsJFZ6x9INuBsji31KBZ/QCPkV0CJlWrB7xTDRfnX/wXi7xe39Ra7DSj3JRllNGGfRJ5&#xD; BdjouLHsBS/xGSuGNjCJdgFFkGiH70nbxIaEEc44wmcC9s2CQftr0TWUja0i6oKAs3eseWFgvHY=
      </ds:SignatureValue>
    </ds:Signature>
    <saml2:Subject>
      <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="My Website">UserJohnSmith</saml2:NameID>
      <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml2:SubjectConfirmationData NotBefore="2020-08-03T00:46:56.397Z" NotOnOrAfter="2020-08-03T00:48:56.397Z"/></saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:AuthnStatement AuthnInstant="2020-08-03T00:46:56.399Z" SessionIndex="abcdedf1234567" SessionNotOnOrAfter="2020-08-03T00:46:56.404Z">
      <saml2:AuthnContext>
        <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
      </saml2:AuthnContext>
    </saml2:AuthnStatement>
    <saml2:AttributeStatement>
      <saml2:Attribute Name="FirstName">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">John</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="LastName">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">Smith</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="http://example.com/roles">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">AdminUser</saml2:AttributeValue>
      </saml2:Attribute>
    </saml2:AttributeStatement>
  </saml2:Assertion>
</saml2p:Response>
```

Copy

The SAML Response document contains (among other things) the following:

- A **digital signature** in the `<ds:Signature>` tag, which allows Smile CDR to verify that it was actually issued by the IDP.

- A **subject** in the `<saml2:Subject>` tag, which identifies the user on whose behalf this response was created.

- A set of **attributes** in the `<saml2:AttributeStatement>` tag, which contain arbitrary information about the logged in user. The attributes shown above are examples only, different IDPs will provide different sets of attributes. These attributes will typically be translated into Smile CDR user session attributes and permissions via a script.

# Enabling SAML Authentication

To enable SAML Authentication for a Smile CDR module such as the Web Admin Console, follow the following steps.

**Create a Registration for Smile CDR in your IDP**
In your IDP system, create a new registration (your IDP may call this something else, such as an _Application_, or an _Application Profile_) for authenticating users to your system. You will need to come up with an ID (called a _Registration ID_ by Smile CDR) that uniquely identifies the integration between Smile CDR and your IDP. By default the string `SMILECDR` will be used.

The IDP will likely need to know the SSO URL for the application being authenticated. This will be the following, where the host and port (and possibly also an additional context root) will correspond to the address for the Smile CDR endpoint module being authenticated. For example, if you have a Web Admin Console module on server **example.com** at port 9100, your base URL will be:
[https://example.com:9100/login/saml2/sso/REGISTRATION\_ID](https://example.com:9100/login/saml2/sso/REGISTRATION_ID)

**Create a Keystore**

Next, you will need to create a  [Keystore](/content/docs/product_configuration/tls_https.html#truststores-and-keystores/index.html) file. This file should contain the certificate used to verify the signed assertions. If you are using signed Authentication Requests, it should also contain the key and certificate that will be used to perform this signature.

**Create a SAML Inbound Security Module**
In the Web Admin Console, create a new module of type _SAML Inbound Security_. Enter the appropriate settings for your IDP.

**Issuer ID** – This should contain the ID for the IDP, and must match the value configured in that system. This is also sometimes called an Entity ID (and specifically refers to the Entity ID for the IDP/SAML Server itself). By convention this is generally a URL to the IDP server, but Smile CDR will not attempt to resolve it.

**Web SSO URL** – This is the URL to the IDP SSO endpoint. Smile CDR will redirect users to this URL when a login is needed.

- **Authentication Callback Script** – This is the callback script that will be used to map the SAML response and its various attributes to Smile CDR permissions in order to create a user session. See  [Authentication Scripts](/content/docs/security/saml_inbound_security_module.html#script/index.html) below for more information.

- **Entity ID Template** – This value controls the Entity ID for the application being authenticated with this security module. See [Entity ID Template](/content/docs/security/saml_inbound_security_module.html#entity-id-template/index.html) below for more information.

**Enable SAML in your Endpoint**
In the module that is being SAML-enabled:

- In your endpoint module configuration (i.e. the actual module you wish to allow a SAML-secured login to, such as the Web Admin Console), enable  [SAML Authentication Enabled](/content/docs/configuration_categories/auth_general_for_web.html#saml.enabled).

- Specify a module dependency from the endpoint module to your new SAML Inbound Security module.

- Restart the endpoint module

**Try It Out!**
There are three ways to start a login:

**IDP-initiated launch** – If your IDP supports it, launch Smile CDR directly from the IDP.

- **Login page button** – When SAML is enabled on a Web Admin Console module, the login page displays a **Sign in with SSO** link. Its text can be changed using the Web Admin Console  [SSO Button Label](/content/docs/configuration_categories/admin_web_console_config.html#signin.sso_button_label/index.html) setting.

- **Direct URL** – Open the following URL to initiate an Authentication Request from Smile CDR:
[https://example.com:9100/saml2/authenticate/REGISTRATION\_ID](https://example.com:9100/saml2/authenticate/REGISTRATION_ID)

# Entity ID Template

The Entity ID Template controls the SAML Entity ID assigned to the SAML _Relying Party_, which refers to the application being authenticated. For example, if you are using a SAML IDP to authenticate access to the Smile CDR Web Admin Console module, this setting controls the Entity ID that the SAML Server will know the Web Admin Console by.

This setting is important, because a well configured SAML Server should include an _Audience_ identifier in assertions that it issues, and the Entity ID that Smile CDR uses must match the Audience declaration in the SAML Assertion.

This setting may include the following substitution variables:

|     |     |
| --- | --- |
| {baseUrl} | Refers to the base URL for the web application being authenticated. For example, if the _Web Admin Console_ module is secured using the _SAML Inbound Security_ module, this variable will be replaced with the base URL for the Web Admin Console module. This value will be different for each module that is secured using the same SAML Inbound Security module, which is helpful since it allows an Entity ID to be unique per authenticated module. |
| {registrationId} | The SAML [Registration ID](/content/docs/configuration_categories/security_in_saml_provider.html#property-registration-id/index.html) assigned to this SAML configuration. |
| {baseScheme} | The protocol (typically `https`) used in the base URL. |
| {baseHost} | The host name used in the base URL. |
| {basePort} | The port number used (or implied by the protocol) in the base URL. |

The default value for this setting is the following:

`{baseUrl}/saml2/service-provider-metadata/{registrationId}`

For example, when using a default registration ID and authenticating a Web Admin Console module that is deployed to https://smilecdr.example.com:9100, the default value will be translated to the following URL (which should be configured exactly as such in the SAML Provider settings):

`https://smilecdr.example.com:9100/saml2/service-provider-metadata/SMILECDR`

If you prefer, you can simply hard code a value in this field with no substitution variables. By convention this value should be a URL, but it does not have to be.

# Authentication Scripts

The authentication script provides a method called `authenticate` that is called automatically when a SAML token has been received and verified. Smile CDR will automatically validate signatures, timestamps, etc. in order to ensure that the token itself is valid for use. The script should then translate the data in the token into a session object containing the appropriate user demographics, permissions, etc.

# Function: authenticate(theRequest, theOutcomeFactory)

This function will be invoked once for each token received, and should return a session or an error.

## Parameters

- **theRequest** – Contains details about the request. This parameter will be of type [AuthenticationRequest](/content/docs/javascript_execution_environment/callback_models.html#authenticationcontext/index.html). Generally this will be used as shown in the example below to access the SAML Response document and extract attributes from it using XPath JavaScript [Document Operations](/content/docs/javascript_execution_environment/xml.html).

- **theOutcomeFactory** – This parameter is of type [ScriptAuthenticationOutcomeFactory](/content/docs/javascript_execution_environment/callback_models.html#scriptauthenticationoutcomefactory/index.html). This parameter can be used to create a failure object if you wish to abort the login from your script.

## Example

The following example script expects custom attributes named "FirstName", "LastName", and "http://example.com/roles". See the example SAML Response [above](/content/docs/security/saml_inbound_security_module.html#saml-response-example/index.html) to see how these attributes might look.

```javascript
/*
 * This is an authentication script for the saml-inbound-security
 * module. It is required to contain a function called "authenticate".
 *
 * This function takes two parameters:
 *   - theRequest       : This object contains the incoming credentials.
 *   - theOutcomeFactory: This is a factory for the success/failure responses
 *                        to be returned by this function.
 */
function authenticate(theRequest, theOutcomeFactory) {

let samlResponse = theRequest.samlResponseDocument;

// Create a successful login response
   var success = theOutcomeFactory.newSuccess();
   success.username = theRequest.username;
   success.familyName = samlResponse.getXPathValue("/saml2p:Response/saml2:Assertion/saml2:AttributeStatement/saml2:Attribute[@Name='LastName']/saml2:AttributeValue/text()");
   success.givenName = samlResponse.getXPathValue("/saml2p:Response/saml2:Assertion/saml2:AttributeStatement/saml2:Attribute[@Name='FirstName']/saml2:AttributeValue/text()");

// Extract the custom role attribute
   let roles = samlResponse.getXPathValues("/saml2p:Response/saml2:Assertion/saml2:AttributeStatement/saml2:Attribute[@Name='http://example.com/roles']/saml2:AttributeValue/text()");

// We'll log a few attributes - In a real system you might reduce these to debug level
   Log.info("GivenName: " + success.givenName);
   Log.info("User has roles: " + roles);

// If the user has an admin role, we'll make them a superuser
   if (roles.includes('AdminUser')) {
      success.addAuthority('ROLE_SUPERUSER');
   }

// You can also reject the session based on specific criteria if needed
   if (roles.includes('BannedUser')) {
      var failure = theOutcomeFactory.newFailure();
      failure.message = 'User is banned';
      return failure;
   }

return success;

}
```

Copy

# Authorizing SMART on FHIR Apps using SAML

See [SAML to SMART Bridging](/content/docs/smart/smart_on_fhir_outbound_security_module_saml_bridging.html) for a description of how to use this module to provide authentication and authorization for SMART on FHIR apps.

[Scripted Inbound Security Module](/content/docs/security/script_inbound_security_module.html)

SAML Inbound Security Module

Security

[Authentication Protocols](/content/docs/security/authentication_protocols.html)
[Authorization and Consent](/content/docs/security/authorization_and_consent.html)
[Inbound Security Module](/content/docs/security/inbound_security_module.html)
[Local Inbound Security Module](/content/docs/security/local_inbound_security_module.html)
[LDAP Inbound Security Module](/content/docs/security/ldap_inbound_security_module.html)
[Scripted Inbound Security Module](/content/docs/security/script_inbound_security_module.html)
[SAML Inbound Security Module](/content/docs/security/saml_inbound_security_module.html)
[Trusted Client Mode](/content/docs/security/trusted_client_mode.html)
[Roles and Permissions](/content/docs/security/roles_and_permissions.html)
[Callback Scripts](/content/docs/security/callback_scripts.html)
[Anonymous Access](/content/docs/security/anonymous_access.html)
[Consent Service](/content/docs/security/consent_service.html)
[Consent Service: JavaScript API](/content/docs/security/consent_service_javascript.html)
[Consent Service: Java API](/content/docs/security/consent_service_java.html)
[Security Recipes](/content/docs/security/security_recipes.html)
[Two Factor Authentication](/content/docs/security/two_factor_auth.html)
[Password Hashing Algorithms](/content/docs/security/password_hashing_algorithms.html)
[JWT Signature Algorithms](/content/docs/security/jwt_signature_algorithms.html)
[Troubleshooting Security](/content/docs/security/troubleshooting_security.html)

[Trusted Client Mode](/content/docs/security/trusted_client_mode.html)
