SAML SSO

SAML SSO

SAML SSO

The SAML SSO AuthMod incorporates single sign-on functionality into the login process:

  • Enables single sign-on (SSO) functionality via SAML allowing users to skip the standard FIN username/password login page if they are already logged in to their SSO environment.

  • User record tags can be dynamically mapped or updated during SAML login with a user prototype.

  • FIN uses the HTTP Redirect Binding for logging in to the Identity Provider (IdP).

Currently, the SAML configuration must be performed manually because there is no UI available yet.

Logging in with Local Accounts

After setting up SAML, navigating to the FIN Uri will automatically attempt SAML login via single sign-on so the standard FIN login page will not be displayed. During initial setup or in the rare instance where the FIN host is having communication issues with the SAML server, it may be necessary to login with a local FIN user account. To login with local FIN accounts, such as the su account created during setup, access {FIN URL:port}/user/login directly, which will display the standard FIN user login page (bypassing single sign-on).

Using SamlSso Authentication

After configuring SamlSso, users will no longer see the standard login page when they navigate to the FIN Server Url (unless the Uri described in Local Account Login is accessed directly). The SamlSso AuthMod will verify SAML assertions sent by the IdP to authenticate the user and read configured attributes from the assertion to authorize the user.

FIN provides flexibility in how user records are managed when using SAML. User roles and access filters can be managed entirely in the FIN User app or users can be synthesized during login by mapping the user to a configured prototype in FIN and using the synthesized user to create a local user record. Therefore, users do not need to be setup prior to login, but FIN can be configured to require that a local user record exists. Review the details of the Login Update Mode setting for more information.

Setup

The following steps are required to configure SAML SSO authentication:

  1. Enable the samlSso SysMod

  2. Identify required user attributes (see SAML Attributes)

  3. Enter the required SAML Settings (see SAML SSO Settings)

  4. Configure one or more user prototypes for SAML (see User Group Mapping)

  5. Configure IdP (see SAML IdP Configuration)

  6. If using the authOnly Login Update Mode, the userAuth tag must be set to AuthMod - samlSso

IMPORTANT: If there are already local user records created in the FIN user database that will now use SAML, the userAuth tag must be manually changed to AuthMod - samlSso.

SAML Attributes

Two attributes must be included in an Assertion sent by the IdP:

  1. The attribute (samlResponseUsernameAttribute) that identifies the username of the user.

  2. The attribute (userProtoAttr) that identifies what prototype to map the user to in FIN. If a default prototype is configured, this attribute is not required.

Record the names of these attributes as they must be configured in FIN.

IMPORTANT: When configuring the attributes, make sure the value of Name is used, not FriendlyName.

In the example below from a SAML attribute statement, this attribute has a FriendlyName of uid and a Name of urn:oid:0.9.2342.19200300.100.1.1. In FIN, the value that must be configured for the samlResponseUsernameAttribute is urn:oid:0.9.2342.19200300.100.1.1 assuming this is the attribute that will be used to identify the username.

<saml2:Attribute FriendlyName="uid" Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" > <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" >samlusername</saml2:AttributeValue> </saml2:Attribute>

SAML Settings

The easiest way to configure SAML, is by using the SAML IdP Metadata. FIN can import the IdP Metadata from a Uri.

In Folio > Launch run this query:

samlImportIdPMetadataUri({uri:`<metadata url goes here>`})

FIN will read the XML document and automatically configure the host, port, tls, idpLoginPath, and idpEntityId settings. FIN will also automatically import the IdP Signing Certificate(s) to verify digitally signed assertions sent by the IdP. FIN requires all messages sent from the IdP to be digitally signed.

After the import, the samlResponseUsernameAttribute and userProtoAttr must be manually configured with the names identified in the SAML Attributes section. The userProtoPriority setting must also be manually configured. See the group example for guidance on how to configure the userProtoPriority setting.

  1. autoUpdateIdPMetadataUri - Read Only setting configured via Import IdP Metadata Action. This setting is used to identify the Uri that will be used to check for and automatically update IdP Signing Certs. The IdP Metadata must be digitally signed to support the auto update workflow. If the IdP Metadata is not digitally signed or the IdP Metadata was imported via Text, no Uri will be displayed and auto updates will not occur.

  2. host - Enter the hostname or IP address of the SAML server.

  • Example: saml.acme.com

  1. port - Enter the port of the SAML server

  2. tls - Use TLS to connect to the SAML server

  3. idpLoginPath - Path to the login HTTP REDIRECT binding on the IdP.

  4. idpEntityId - Entity ID of the IdP, which will be verified by FIN in each message.

  5. loginUpdateMode - See Login Update Mode for details.

  6. samlResponseUsernameAttribute - Required The attribute in the SAML assertion to use for the synthesized user's username.

  7. userProtoAttr - When using updateOnLogin loginUpdateMode, this setting is Required unless userProtoDefault is configured. This setting defines the attribute in the user's SAML assertion that is used to determine the user's prototype. See User Group Mapping for details.

  8. userProtoPriority - When using updateOnLogin loginUpdateMode, this setting is Required unless userProtoDefault is configured. If a user maps to multiple user prototypes, this list specifies the priority of which one should be chosen. See User Group Mapping for details.

  9. userProtoDefault - Optional setting. If a user cannot be mapped to a prototype via the userProtoAttr, then use the prototype with this name as the default.

  10. applyTagsFunc - Optional setting. Axon callback function used to set/change tags on a user before a session is created. The function should take two parameters (user, attrs) where user is the current User tags (with prototype already applied) and attrs is the SAML assertion attributes Dict for that user. Return the updated User Dict. See Example applyTagsFunc.

  11. supportText - Optional setting. Fandoc formatted text that will display on samlSso/authFailed page that can be used to help users troubleshoot login issues.

Login Update Mode

The SAML mod can be configured to interact with users in the user database in several, flexible ways. Choose the option that meets the project requirements:

  • authOnly: ( default ) SAML will only be used for authenticating the user. The user must exist in the user database in order to log in.

  • updateOnLogin: Creates or updates the user database rec every time the user logs in by applying the configured prototype and invoking the 'applyTagsFunc' (if configured). The user rec is only updated if the prototype assignment changes, or tags are modified by the the 'applyTagsFunc'.

User Groups Mapping (user prototypes)

When a user successfully authenticates using SamlSso, the user is not prompted for a username or password so the SAML assertion is used to lookup a FIN User in the local user database. If a local user record cannot be found and Login Update Mode is configured to updateOnLogin then to construct a valid user, an authenticated user must be mapped to a User Group.

  1. Create the user groups required for the host.

  2. Configure the samlSsoUserProtoAttrVal (string tag) for each group that will be used for SamlSso.

  3. The value of this tag is used to help the SamlExt determine which user prototypes a SamlSso user maps to. The SamlExt will check the values of the 'userProtoAttr' (as configured in the Saml SSO settings)

  4. After a user is authenticated using SamlSso, the SamlExt looks up the user's attribute in the SAML assertion.

  5. When reading the user's attributes SAML assertion, if one of them matches this tag's value, then this prototype is a potential match for the user attempting to log in.

  6. Configure one or more user groups as a comma separated list (enter shortName (userProtoName) of each group record) for the userProtoPriority setting.

  7. Optionally configure a default user prototype (enter shortName (userProtoName) of group record) so users can still login when they cannot be mapped to an existing prototype. As a best practice, this prototype should have an operator role and limited access.

Group Example

SAML SSO Settings:

userProtoAttr: "FINUserPrototype" userProtoPriority:"engineering, si, default"

Groups

id: @engineering userProto userProtoName: "engineering" dis:"Engineering" userRole:"admin" samlSsoUserProtoAttrVal: "Engineering" id: @si userProto userProtoName: "si" dis:"System Integrator" userRole:"op" samlSsoUserProtoAttrVal: "SI" appAccess: "energy"

SAML assertion for user bob (represented as a Dict for clarity).

username: "bob" email: "bob@company.com" FINUserPrototype: "SI" ... other attributes ...
  1. User bob authenticates via SamlSso.

  2. The SamlExt will determine the username from the SAML assertion is bob.

  3. The SamlExt now checks prototype priorities specified by the userProtoPriority setting in order to try and find the best prototype match for bob:

  4. The first prototype in this list is engineering. The samlSsoUserProtoAttrVal for this prototype is Engineering. This value is not in the FINUserPrototype list specified in Bob's SAML assertion.

  5. The next prototype in the list is si. The samlSsoUserProtoAttrVal for this prototype is SI. This value is in the FINUserPrototype list for Bob.

  6. The si prototype is used to create a synthetic user for Bob's session and Bob is successfully logged in. (Bob will be an operator with access only to the energy app).

NOTE: It is an error for a user to exist in the local user database with a username that matches the username of a user logging in via SamlSso. If this condition is detected, the user will not be allowed to log in. An error to this effect will be logged to the console.

Optional User Attributes

The following optional SAML attributes will be set while synthesizing the user if they exist:

  1. Display Name (dis) - Assertion Attribute: displayName

  2. Email Address (email) - Assertion Attribute: email

NOTE: The dis tag is set to the username if a displayName attribute does not exist.

Example applyTagsFunc

A simple example use case for the applyTagsFunc is to add the email address to the synthesized user. In this example, the user's email address is provided in the Assertion with the attribute name finEmailAddress.

NOTE: Every key in the attrs Dict is a List of values (a single value will be a List with one item). Additionally, each attribute returned from the identity provider is converted to a valid tag name using toTagName() so accessing the name of the attribute may differ from what is shown in the encoded SAML authentication response message. During initial configuration, echo(attrs) can be helpful to verify attribute names.

(user, attrs) => do emailList: attrs["finEmailAddress"] if (emailList != null and emailList.size == 1) user = user.set("email", emailList.first) return user end

SAML IdP Configuration

In Folio > Launch, query for samlShowSkySparkMetadata() and then toggle to the Zinc view to display the FIN SAML Metadata. Some IdPs will support configuring the FIN Service Provider by copying and pasting the XML portion into the IdP SP configuration page. By default, the siteUri setting is used in the two locations specified below as {siteUri}.

The entityId does not include the port. The FIN siteUri is configured in the Host > Settings page under HTTP section. When configuring the IdP it is important to use the address that users will connect to FIN with as the IdP will likely reject a request for an unknown Entity ID. Additionally, FIN will check that the Audience lists the FIN Entity ID in the response.

<?xml version='1.0' encoding='UTF-8'?> <md:EntityDescriptor xmlns:md='urn:oasis:names:tc:SAML:2.0:metadata' entityID='{siteUri without port}'> <md:SPSSODescriptor WantAssertionsSigned='true' protocolSupportEnumeration='urn:oasis:names:tc:SAML:2.0:protocol'> <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat> <md:AssertionConsumerService Binding='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' Location='{siteUri}/samlSso/assertionConsumerService' index='0' isDefault='true'/> </md:SPSSODescriptor> </md:EntityDescriptor>

For convenience when displaying the FIN SP Metadata, the SkySpark Entity ID and Assertion Consumer binding are called out below the XML. When copying the FIN Metadata to an IdP, do not include the lines shown below:

SkySpark Entity ID: {siteUri without port} SkySpark Assertion Consumer HTTP-POST Binding: {siteUri}/samlSso/assertionConsumerService

FIN Entity Id

By default, the siteUri of the FIN server is used for the FIN Entity Id, excluding the port. This can be overridden by adding a tag to the samlSso entry in var/host/folio.trio called FINEntityId and specify a Str value.

Restart FIN after making the change.

FIN Assertion Consumer Service Uri

By default, the siteUri of the FIN server is used to build the Assertion Consumer Service Uri using this format: {siteUri}/samlSso/assertionConsumerService

Most of the time, it is recommended to use the siteUri, but when working across numerous dev and test environments it can simplify testing to use something other than the siteUri. To do that, add a tag to the samlSso entry in var/host/folio.trio called FINBaseUri and specify a Uri value. Remember to include the port if necessary. When adding this tag, the default Entity Id will also change. See FIN Entity Id section to change the FIN Entity Id.

Restart FIN after making the change.

Encrypted Assertions

Support for encrypted assertions is not enabled by default. Additional support pods are required.

Example: Configuring Okta SAML SSO with FIN

This guide provides a step‑by‑step process for configuring SAML‑based Single Sign-On (SSO) between FIN and Okta.

Prerequisites

  • Users and groups are already created in Okta.

1. Configure HTTP/HTTPS Settings in FIN

Depending on your deployment requirements, FIN can operate with HTTPS either enabled or disabled.
The commands below allow you to toggle HTTPS at the directory level. This setting is independent of the UI option found under Host → Settings → HTTP → HTTPS Enabled. Run the appropriate query based on the configuration you need.

  1. Open Folio → Launch

  2. Run the following command to enable HTTPS.
    hostCommit({id:@h:http, mod:hostReadById(@h:http)->mod, httpsEnabled:true})

  3. Run the following command to disable HTTPS.
    hostCommit({id:@h:http, mod:hostReadById(@h:http)->mod, httpsEnabled:false})

2. Enable the SAML SSO Module in FIN

  1. Open Folio → Launch

  2. Run this command to enable SAML: sysModAdd(["samlSso"])

To disable: sysModRemove(["samlSso"])

To check status: sysMods().find(x => x->name.contains("samlSso"))->libStatus

3. Gather FIN Metadata for Okta

  1. In Folio → Launch, run: samlShowSkySparkMetadata()

  2. Switch to the Zinc view.

  3. Record the following values:

    • SkySpark Entity ID

    • SkySpark Assertion Consumer Service (HTTP‑POST) URL

These will be used when creating the Okta app.

4. Create the Okta SAML Application

  1. Sign into the Okta Admin Dashboard

  2. Go to Applications → Applications

  3. Click Create App Integration

  4. Choose SAML 2.0

  5. Name the application (add logo if desired)

SAML Settings

  • Single sign-on URL
    Paste the SkySpark ACS URL
    Example:
    https://{host}/samlSso/assertionConsumerService

  • Audience URI (SP Entity ID)
    Paste the SkySpark Entity ID
    Example:
    https://{host}

  • Default RelayState: leave blank

  • Name ID format: Transient

  • Application username: Okta username

  • Update application username: Create and update

Click Next → mark as internal app.

5. Assign Users and Groups in Okta

  1. In the created Okta app, open the Assignments tab.

  2. Assign individual users and Okta groups.

6. Configure Attribute Statements

  1. In the Okta app, go to Sign On → Edit → Switch to legacy view

  2. Add the following Attribute Statements:

Username Attribute

Field

Value

Field

Value

Name

username

Name format

Basic

Value

user.email

Groups Attribute

Field

Value

Field

Value

Name

groups

Name format

Basic

Filter

Matches regex .* (or use contains)

7. Collect Okta Metadata URL

While still in Sign On, copy the Metadata URL.
You will import this into FIN.

8. Create User Groups in FIN

  1. Create your FIN user groups.

  2. For each group, click the “i” (info) icon and add:

samlSsoUserProtoAttrVal: "<name of Okta group>"

This value must match exactly what Okta sends.

9. Import Okta Metadata into FIN

  1. Open Folio → Launch

  2. Run the following command using your Metadata URL:

samlImportIdPMetadataUri({uri:`https://trial-5917406.okta.com/app/exk10jrvdwd2K7EGA698/sso/saml/metadata`})

This automatically populates fields such as:

autoUpdateIdPMetadataUri:`` host:"trial-5917406.okta.com" idpEntityId:"http://www.okta.com/exk10jrvdwd2K7EGA698" idpLoginPath:"/app/trial-5917406_fin_1/exk10jrvdwd2K7EGA698/sso/saml" port:443 tls:true

Certificates are imported automatically.

10. Configure Remaining SAML Settings in FIN

In Folio → Launch, run the following query, updating the property values inside the double quotes as needed. Leave any unused properties as empty strings.

Refer to the related sections above for details on each property, including whether it is required or optional.
Query:

hostCommit({id:@h:samlSso,mod:hostReadById(@h:samlSso)->mod, applyTagsFunc:"", loginUpdateMode:"updateOnLogin", samlResponseUsernameAttribute:"username", supportText:"", userProtoAttr:"groups", userProtoDefault:"", userProtoPriority:"admin" })

Once this command is executed, the updated values will be written to the id:@samlSso section within the var/host/folio.trio file.

11. Restart FIN

After applying all the settings, restart the FIN service.

12. Test Okta SSO

Navigate to your FIN instance. If there is no active Okta session in the browser, the Okta login page should appear. Successful login should redirect back into FIN.

Video

Example video walkthrough for configuring SAML‑based Single Sign-On (SSO) between FIN and Okta.

SAMLSetup.mp4