> ## Documentation Index
> Fetch the complete documentation index at: https://support.lilt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Single Sign On (SSO) For Self-Managed

For **self-managed customers** only, LILT supports Single Sign-On (SSO), allowing users to sign in to LILT using an identity provider other than LILT. Organizations can utilize SSO to simplify account management and reduce password fatigue.

Currently, for installations without WSO2, a user account must pre-exist in the LILT system before SSO can be used to authenticate the user.  If WSO2 is installed with the package then users will be auto-provisioned with the `lilt_api` and `lilt_role` attributes mentioned in the WSO2 configuration section.

## Google SSO

LILT customers can sign in via their Google account.

After being invited to join LILT by someone in your organization, you can create an account using Google Sign-On.

Users with existing LILT accounts that use traditional username/password sign in can access their accounts and all their data using Google Sign-On with an email address that matches their existing account. Users may use both sign-in methods interchangeably.

## OpenID Connect

LILT Platform users can sign in through their organization's SSO once configured via OpenID Connect (OIDC).

[OpenID Connect](https://openid.net/developers/how-connect-works/) is an interoperable authentication protocol based on the OAuth 2.0 framework of specifications (IETF RFC 6749 and 6750). It simplifies the way to verify the identity of users based on the authentication performed by an Authorization Server and to obtain user profile information in an interoperable and REST-like manner. OIDC can be leveraged through many identity providers such as Amazon, Microsoft, Okta, etc.

### Configuration

* LILT must be registered as a client with your OpenID Connect (OIDC) provider before installation. Client key, secret, and configuration parameters need to be configured during installation. Those parameters will be set by your systems administrator under the front:config:SSO property in the helm values file.
* A LILT installation can support only one OIDC configuration at a time.
* OpenID support has currently been tested with the following two signing algorithms: SHA256 and HS256.
* The integration supports encryption with the OpenID provider via HTTPS but does not additionally encrypt the OpenID payload.

### Custom Claims

The following custom claims can be configured in your OIDC provider to enable auto-provisioning and domain assignment:

* **`lilt_api`** (required for JIT provisioning) — Your organization's API key, used to identify which LILT organization the user belongs to. Set this as a static claim value — it is the same for all users in the organization.
* **`lilt_role`** (recommended) — The user's role within LILT. Accepts three formats:

  | Format                 | Example               | Notes                              |
  | :--------------------- | :-------------------- | :--------------------------------- |
  | Numeric role ID        | `"4"`                 | Most reliable — never changes      |
  | Internal role name     | `"Agency Translator"` | Case-sensitive, must match exactly |
  | Localized display name | `"External Linguist"` | Case-insensitive                   |

  If omitted or unrecognized, the user receives the organization's default role.
* **`lilt_domains`** (optional) — Assigns the user to specific domains on first login. Supports multiple formats:

  | Format          | Example                   |
  | :-------------- | :------------------------ |
  | Single value    | `"Marketing"`             |
  | Comma-separated | `"Marketing,Sales,Legal"` |
  | JSON array      | `["Marketing", "Sales"]`  |
  | Domain ID       | `"123"`                   |
  | Mixed           | `"Marketing,456,Sales"`   |

  Domain names are case-sensitive. Numeric values are resolved as domain IDs. Domain assignments are only applied on first login — subsequent logins do not update assignments.

### Usage

* After configuration, OIDC authentication can be used to authenticate existing LILT accounts and their data.
* To create new user accounts, users must first be invited by email using the "New member" screen in the LILT Organizations tab. After being invited, new users can sign in using the SSO button on the sign-in page.
* NOTE: Automated user provisioning and de-provisioning is only supported when using WSO2.

## WSO2

### Configuring WSO2 Identity Server with LILT

This section describes how to configure WSO2 Identity Server for single sign-on (SSO) authentication with LILT.

#### Prerequisites

* WSO2 Identity Server installed and running by running `<install dir>/install_scripts/install-wso2.sh`
* Access to WSO2 Identity Server Console with Super Admin privileges -- username and password are `admin` by default.
* LILT application deployed

#### Step 1: Configure User Attributes

##### 1.1 Access User Attributes

1. Log into the WSO2 Identity Server Console as Super Admin
2. Navigate to **User Attributes & Stores** → **Attributes**
3. Click on **Attributes** to view and manage user attributes

##### 1.2 Add Custom LILT Attributes

You need to add two critical attributes for LILT integration:

**Add lilt\_role Attribute:**

1. Click **New Attribute** button
2. Configure the attribute:
   * **Attribute Name**: `lilt_role`
   * **Attribute URI**: `http://wso2.org/claims/lilt_role`
   * **Protocol Mappings**:
     * OpenID Connect: `lilt_role`
     * SCIM 2.0: `urn:scim:schemas:extension:custom:User:lilt_role`
   * **Attribute Display Name**: `LILT Role`
3. Click **Finish** to save
4. Scroll down on the page and make sure to select `Display` under the `Administrator Console` column for the `Attribute Configurations` section

**Add lilt\_api Attribute:**

1. Click **New Attribute** button again
2. Configure the attribute:
   * **Attribute Name**: `lilt_api`
   * **Attribute URI**: `http://wso2.org/claims/lilt_api`
   * **Protocol Mappings**:
     * OpenID Connect: `lilt_api`
     * SCIM 2.0: `urn:scim:schemas:extension:custom:User:lilt_api`
   * **Attribute Display Name**: `LILT API`
3. Click **Finish** to save
4. Scroll down on the page and make sure to select `Display` under the `Administrator Console` column for the `Attribute Configurations` section

**Add lilt\_domains Attribute (Optional):**

1. Click **New Attribute** button again
2. Configure the attribute:
   * **Attribute Name**: `lilt_domains`
   * **Attribute URI**: `http://wso2.org/claims/lilt_domains`
   * **Protocol Mappings**:
     * OpenID Connect: `lilt_domains`
     * SCIM 2.0: `urn:scim:schemas:extension:custom:User:lilt_domains`
   * **Attribute Display Name**: `LILT Domains`
3. Click **Finish** to save
4. Scroll down on the page and make sure to select `Display` under the `Administrator Console` column for the `Attribute Configurations` section

#### Step 2: Configure OpenID Connect Scopes

##### 2.1 Access OIDC Scopes Configuration

1. Navigate to **User Attributes & Stores** → **Attributes** → **OpenID Connect** -> **Scopes**

##### 2.2 Add to Roles Scope

1. Click **Roles** to configure the scope
2. Click **New Attribute**
3. Choose the `lilt_role` attribute
4. Click **Save**
5. Click **Save Changes**

##### 2.3 Add to Profile Scope

1. Return to the scopes page from 2.1
2. Click **Profile** to configure the scope
3. Click **New Attribute**
4. Choose the `lilt_api` attribute
5. Click **Save**
6. If using `lilt_domains`: Click **New Attribute** again, choose the `lilt_domains` attribute, and click **Save**
7. Click **Save Changes**

#### Step 3: Create and Configure the LILT Application

##### 3.1 Create New Application

1. Navigate to **Applications**
2. Click **New Application**
3. Select **Standard-Based Application**
4. Choose **OAuth2.0/OpenID Connect**
5. Configure basic settings:
   * **Name**: `LILT` (or your preferred application name)
   * **Description**: LILT Application for SSO
6. Click **Register**

##### 3.2 Configure Protocol Settings

1. In the application configuration, go to the **Protocol** tab
2. Configure the following OAuth/OIDC settings:

**Allowed Grant Types:**

* ✓ Code
* ✓ Client Credentials
* ✓ Organization Switch

**URLs Configuration:**

Authorized Redirect URLs:

```
https://<your-domain>/signin2
https://<your-domain>/auth/embedded-oidc/logout
https://<your-domain>/auth/embedded-oidc/callback
```

**Important Note:** Replace `<your-domain>` with your actual LILT instance domain.

Allowed Origins:

```
https://<your-domain>
```

**Access Token:**

* Select: `JWT` as the **Token type**

##### 3.3 Configure User Attributes

1. Go to the **User Attributes** tab
2. Select the following attributes to be included in the ID token:
   * ✓ Email
   * ✓ Groups
   * ✓ Profile (Expand to make sure `lilt_api` is included)
   * ✓ Roles (Expand to make sure `lilt_role` is included)
3. Select `Assign alternate subject identifier`
   * Select `Email` in the dropdown

##### 3.4 Configure API Authorization

1. Go to the **API Authorization** tab
2. Click **Authorize an API Resource**
3. Configure the API authorization:
   * **API Resource**: Select the API resource you need to authorize
   * **Authorized Scopes**: Select appropriate scopes for your implementation
   * **Authorization Policy**: Role Based Access Control (RBAC)
4. Click **Finish**

**Note:** Repeat this process for each API resource that needs to be authorized for your LILT implementation.

#### Step 4: Configure Login Flow

1. Go to the **Login Flow** tab in your application
2. Configure the authentication flow based on your requirements:

**Basic Login Flow (Username & Password):**

* **Step 1**: Sign in with Username & Password

**Multi-Factor Authentication Options (Optional):**

You can add various MFA methods as a second step:

* Email OTP
* Push Notification
* SMS OTP
* TOTP
* Passkey
* Magic Link

#### Step 5: Configure SSO Settings (Optional)

If you want to integrate with external identity providers:

1. Navigate to **Connections** → **New Connection**
2. Select your identity provider type
3. Configure the connection settings based on your IdP requirements
4. Map the external attributes to WSO2 attributes

**Note:** You can auto-navigate to SSO by removing the Username & Password login screen and only selecting the SSO option in the Login Flow section

#### Step 6: User Management

##### Creating New Users

When creating users in WSO2 for LILT access:

1. Navigate to **User Management** → **Users**
2. Click **Add User**
3. Fill in required fields:
   * Username
   * Email
   * First Name
   * Last Name
   * Password
4. **Important**: Add the custom attributes:
   * **lilt\_role**: Assign appropriate LILT role. Accepted formats (tried in order):
     1. **Numeric role ID** (e.g., `4`) — matches by role ID
     2. **Internal role name** (e.g., `Administrator`, `Manager`) — exact match, case-sensitive
     3. **Localized display name** (e.g., `External Linguist`, `Korrektor`, `外部担当者`) — case-insensitive match via alias map
   * If `lilt_role` is omitted or does not match any role, the user will be assigned the organization's default role (typically "Customer")
   * **lilt\_api**: API key -- this is only required if the user does not already exist in LILT
   * **lilt\_domains** (optional): Comma-separated domain names or IDs (e.g., `"Marketing,Sales"`). Domain names are case-sensitive. Numeric values are resolved as domain IDs.
5. Save the user

**Note:** If the **lilt\_role** and **lilt\_api** fields do not appear when adding a user revisit step 1.2. These attributes are used for auto-provisioning. If **lilt\_domains** does not appear, ensure you completed the optional attribute setup in step 1.2.

**Note:** The `lilt_domains` claim is only applied when a user is first provisioned (JIT). Subsequent SSO logins do not update domain assignments. To change domain assignments for existing users, update them directly in LILT.

##### Modifying Existing Users

For users already in the system:

1. Navigate to the user profile
2. Edit user attributes
3. Add the `lilt_role` and `lilt_api` attributes if required
4. Save changes

#### Tying it to the application

All of the information needed can be found in the **Quick Start** and **Info** tabs in the WSO2 application that was just created.  The environment variables required are shown below:

<Note>
  After configuring the environment variables below, you must also enable the `enableWSO2Login` feature flag for each organization using the Admin CLI:

  ```bash theme={null}
  npm run dist-admin-cli -- set-org-setting --orgIds <ORG_ID> --settingName=enableWSO2Login --value=true
  ```

  **Note: If users were already created before enabling this flag, their account type in the database will be set to `local` and they will not be able to sign in via SSO.**

  **To fix this, you must edit the database row for each affected user and change their account type to `embedded-oidc`.**

  This flag enables the authentication type selector in the user invite UI and allows WSO2/Embedded OIDC to be set as the authentication method for new users.
</Note>

```yaml theme={null}
front:
  onpremValues:
    env:
      # Embedded OIDC Provider
      EMBEDDED_OIDC_PROVIDER_ENABLED: true
      EMBEDDED_OIDC_PROVIDER_CLIENT_ID: "<WSO2 app client id>"
      EMBEDDED_OIDC_PROVIDER_CLIENT_SECRET: "<WSO2 app client secret>"
      EMBEDDED_OIDC_PROVIDER_ID_TOKEN_SIGNED_RESPONSE_ALG: "RS256"
      EMBEDDED_OIDC_PROVIDER_ISSUER_ENDPOINT: "https://<your-wso2-domain>/oauth2/token"
      EMBEDDED_OIDC_PROVIDER_ISSUER_AUTH_ENDPOINT: "https://<your-wso2-domain>/oauth2/authorize"
      EMBEDDED_OIDC_PROVIDER_ISSUER_TOKEN_ENDPOINT: "https://<your-wso2-domain>/oauth2/token"
      EMBEDDED_OIDC_PROVIDER_ISSUER_USERINFO_ENDPOINT: "https://<your-wso2-domain>/oauth2/userinfo"
      EMBEDDED_OIDC_PROVIDER_ISSUER_JWKS_URI: "https://<your-wso2-domain>/oauth2/jwks"
      EMBEDDED_OIDC_PROVIDER_ISSUER_END_SESSION_ENDPOINT: "https://<your-wso2-domain>/oidc/logout"
      EMBEDDED_OIDC_PROVIDER_INTEGRATION_APIS_WSO2_IS_ENABLED: false
      EMBEDDED_OIDC_PROVIDER_INTEGRATION_APIS_WSO2_IS_ASGARDEO: false
      EMBEDDED_OIDC_PROVIDER_INTEGRATION_APIS_WSO2_BASE_URL: ""
      EMBEDDED_OIDC_PROVIDER_INTEGRATION_APIS_WSO2_TENANT: ""
      EMBEDDED_OIDC_PROVIDER_INTEGRATION_APIS_WSO2_LILT_ROOT_ORG: ""
```

#### Organization Alias Mapping (Optional)

If your organization uses multiple names or identifiers that should resolve to the same LILT organization, you can configure organization aliases via a Kubernetes ConfigMap.

Organization identifiers are normalized before lookup: converted to lowercase, trimmed, and spaces are replaced with hyphens (e.g., "My Org" becomes "my-org").

**Configuration:**

Create or update the ConfigMap mounted at `/home/lilt/server/config/sso-org-aliases.json` with a JSON object mapping aliases to canonical organization identifiers:

```json theme={null}
{
  "alternate-name": "canonical-org-name",
  "old-company-name": "canonical-org-name"
}
```

Both alias keys and canonical values must be valid identifiers: alphanumeric characters, dots (`.`), hyphens (`-`), and underscores (`_`) only, up to 255 characters.

#### Testing the Configuration

After completing the configuration:

1. Navigate to `https://<your-domain>/signin`
2. You should be redirected to the WSO2 login page
3. Enter credentials for a user with proper `lilt_role` and `lilt_api` attributes
4. Upon successful authentication, you should be redirected back to LILT with proper access

#### Troubleshooting WSO2 Integration

If users cannot access LILT after authentication:

* Verify the lilt\_role and lilt\_api attributes are properly configured
* Check that redirect URLs match exactly
* Ensure all required scopes are configured
* Verify API authorizations are in place
* Check application logs for specific error messages

## Direct Integration (SINGLE OIDC)

The version 1.20.0 (September 2023) release of LILT Enterprise supports two new kinds of customization of the Single Sign On feature:  "custom certs" and "non-standard overrides".  The intent is to expand the environments where SSO can be used.

These customizations are discussed in more detail in the following section, where we will reference the configuration shown immediately below.  This particular configuration illustrates using custom certificate info, as well as overrides to standard OIDC behaviour, so that login using Active Directory Federation Services (ADFS) on Windows 2016 can be achieved.

```yaml theme={null}
front:
  onpremValues:
    env:
      # SSO configurations
      #
      # OIDC
      SINGLE_OIDC_PROVIDER_ENABLED: true
      SINGLE_OIDC_PROVIDER_CLIENT_ID: "lilt"
      SINGLE_OIDC_PROVIDER_CLIENT_SECRET: "SAMPLE"
      SINGLE_OIDC_PROVIDER_ID_TOKEN_SIGNED_RESPONSE_ALG: "RS256"
      SINGLE_OIDC_PROVIDER_ISSUER_NAME: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs"
      SINGLE_OIDC_PROVIDER_ISSUER_AUTH_ENDPOINT: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/oauth2/authorize/"
      SINGLE_OIDC_PROVIDER_ISSUER_TOKEN_ENDPOINT: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/oauth2/token/"
      SINGLE_OIDC_PROVIDER_ISSUER_USERINFO_ENDPOINT: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/userinfo"
      SINGLE_OIDC_PROVIDER_ISSUER_JWKS_URI: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/discovery/keys"
      #
      # OIDC - overrides for working with ADFS
      SINGLE_OIDC_PROVIDER_OVERRIDES_RESOURCE_QUERY_PARAM: "urn:microsoft:userinfo"
      SINGLE_OIDC_PROVIDER_OVERRIDES_IDTOKEN_CLAIM_NAME_FOR_LILT_EMAIL_ADDRESS: "upn"
    config:
      # singleOidcProviderTlsOptions provides a means to customize HTTP requests made from the front container
      # to the OIDC Provider, when using the SingleOidcProvider SSO feature.  Using these options means you
      # should NOT use any other OIDC-based login strategy besides that of the SingleOidcProvider SSO feature, or at
      # least be aware other strategies implemented via the openid-client library will also be affected by these options.
      singleOidcProviderTlsOptions:
        # existingSecret should be set to true if you are going to manage the secret yourself; otherwise set existingSecret
        # to false and the template will manage the secret.  If managing the secret yourself, you can provide key-value pairs
        # in the secret for any of the following keys:
        #    ca, cert, key, passphrase, crl, pfx
        # However, you MUST also provide a non-empty string value in the map below for the keys that you want to be used.
        # It does not matter what non-empty string you provide below in that case -- e.g.,
        #    ca: "use-the-existing-secret-value"
        # added below would cause your existing secret's ca value to be used.
        existingSecret: false
        secretName: "single-oidc-provider-tls-options"
        # ca, cert, key, passphrase, crl, and pfx are used to customize HTTP calls from the oidc-client library to the OIDC Provider
        # Only those with non-empty values will be used; all others will be ignored.
        # If existingSecret is false, the values you specify below should be base64 encoded.
        # Their meaning can be found at:  https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions
        ca: |-
          SAMPLE
        cert: |-
          SAMPLE
        key: ""
        passphrase: ""
        crl: ""
        pfx: ""
```

#### Azure Active Directory, Graph

If using Azure Active Directory with Graph API, the following need to be configured on the provider:

Configure Authentication:

1. Click Authentication (left sidebar)
2. Click Add a platform
3. Select Web
4. Configure:
   Redirect URIs:
   `https://<host_name>/auth/openid/callback`
   Front-channel logout URL: (leave blank)
   Implicit grant and hybrid flows:
   ❌ Access tokens (used for implicit flows) - UNCHECK
   ❌ ID tokens (used for implicit and hybrid flows) - UNCHECK
   Click Configure
   Scroll down to Advanced settings:
   Allow public client flows: No
   Enable the following mobile and desktop flows: (leave as is)
   Click Save at the top

Configure API Permissions:

1. Click API permissions (left sidebar)
2. You should see Microsoft Graph with some permissions already
3. Click Add a permission
4. Select Microsoft Graph
5. Select Delegated permissions
6. Search and check these permissions:
   ✅ email (under OpenId permissions)
   ✅ openid (under OpenId permissions)
   ✅ profile (under OpenId permissions)
7. Click Add permissions
8. Grant Admin Consent:
   Click Grant admin consent for \[Your Organization]
   Click Yes to confirm
   Wait for green checkmarks to appear
   Final state should look like:

```bash theme={null}
Microsoft Graph (3)
├── email          - Delegated - ✅ Granted for [Org]
├── openid         - Delegated - ✅ Granted for [Org]
└── profile        - Delegated - ✅ Granted for [Org]
```

Update `values.yaml`:

```yaml theme={null}
front:
  onpremValues:
    env:
      # SSO configurations
      # OIDC
      SINGLE_OIDC_PROVIDER_ENABLED: true
      SINGLE_OIDC_PROVIDER_CLIENT_ID: "<client_id>"  # "", if using existing secret
      SINGLE_OIDC_PROVIDER_CLIENT_SECRET: "<client_secret>" # "", if using existing secret
      SINGLE_OIDC_PROVIDER_ID_TOKEN_SIGNED_RESPONSE_ALG: "RS256"
      SINGLE_OIDC_PROVIDER_ISSUER_NAME: "https://login.microsoftonline.com/<directory_tenant_id>/v2.0"
      SINGLE_OIDC_PROVIDER_ISSUER_AUTH_ENDPOINT: "https://login.microsoftonline.com/<directory_tenant_id>/oauth2/v2.0/authorize"
      SINGLE_OIDC_PROVIDER_ISSUER_TOKEN_ENDPOINT: "https://login.microsoftonline.com/<directory_tenant_id>/oauth2/v2.0/token"
      SINGLE_OIDC_PROVIDER_ISSUER_USERINFO_ENDPOINT: "https://graph.microsoft.com/oidc/userinfo"
      SINGLE_OIDC_PROVIDER_ISSUER_JWKS_URI: "https://login.microsoftonline.com/<directory_tenant_id>/discovery/v2.0/keys"
```

## SSO configuration format changes, starting at version 1.19.0 (SINGLE OIDC)

Changes were made to how the SSO configuration values are specified, starting with version 1.19.0.  Note that the "regular" SSO-related configuration values are now specified as environment variables, nested under front.onpremValues.env has shown in this excerpt:

```yaml theme={null}
front:
  onpremValues:
    env:
      # SSO configurations
      #
      # OIDC
      SINGLE_OIDC_PROVIDER_ENABLED: true
      SINGLE_OIDC_PROVIDER_CLIENT_ID: "lilt"
      SINGLE_OIDC_PROVIDER_CLIENT_SECRET: "SAMPLE"
      SINGLE_OIDC_PROVIDER_ID_TOKEN_SIGNED_RESPONSE_ALG: "RS256"
      SINGLE_OIDC_PROVIDER_ISSUER_NAME: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs"
      SINGLE_OIDC_PROVIDER_ISSUER_AUTH_ENDPOINT: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/oauth2/authorize/"
      SINGLE_OIDC_PROVIDER_ISSUER_TOKEN_ENDPOINT: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/oauth2/token/"
      SINGLE_OIDC_PROVIDER_ISSUER_USERINFO_ENDPOINT: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/userinfo"
      SINGLE_OIDC_PROVIDER_ISSUER_JWKS_URI: "https://active-directory-bare-windows-vm-shared-vpc.ssodev.lilt.dev/adfs/discovery/keys"
```

## Client ID and Secret

Can use an existing secret for client ID and SECRET. Ensure that a generic kubernetes secret already exists in the cluster.

```yaml theme={null}
front:
  onpremValues:
    env:
      # SSO configurations
      #
      # OIDC
      SINGLE_OIDC_PROVIDER_ENABLED: true
      SINGLE_OIDC_PROVIDER_CLIENT_ID: ""
      SINGLE_OIDC_PROVIDER_CLIENT_SECRET: ""
    config:
      oidc:
        useExistingSecret:
          enabled: true
          existingSecretRef: <secret_name>
          ## This defines where to find the keys for OIDC credentials in the existingSecretRef
          # Keys in the secret for OIDC client ID and client secret
          clientIdKey: <id_key_name_in_secret>
          clientSecretKey: <secret_key_name_in_secret>
        ## If oidc.useExistingSecret.enabled is false or not set, values fall back to
        ## env.SINGLE_OIDC_PROVIDER_CLIENT_ID and env.SINGLE_OIDC_PROVIDER_CLIENT_SECRET
```

## SSO TLS customization

Communication from the LILT app to your OIDC IdentityProvider occurs over a connection secured by TLS. For this communication to be successful, certificate information is exchanged and verified. In many environments, this verification can succeed using well-known CertificateAuthority information that is part of the default network stack in nodejs (the platform used to implement the SSO feature). In some environments, it will be necessary to provide additional TLS-related configuration. Support for doing so was added to LILT Enterprise starting at version 1.20.0.

### singleOidcProviderTlsOptions

Specifically, it is now possible, via the `front.onpremValues.config.singleOidcProviderTlsOptions` object, to provide the following configuration values affecting the TLS communication for calls made from the LILT appserver to your OIDC IdentityProvider:

* ca
* cert
* key
* passphrase
* crl
* pfx

The meaning of the above six parameters can be found in the nodejs documentation at:

[TLS (SSL) | Node.js v24.6.0 Documentation](https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions)

In testing where Active Directory Federation Services (ADFS), running on Windows Server, was used as the IdentityProvider, it was necessary to specify `ca` and `cert` values, but not the others.

Further instructions for using these configuration values can be found in the comments in the YAML shown at the start of this SSO section.

## Using ADFS 2016 in lieu of standard OIDC Identity Provider

Microsoft's ADFS 2016 does not conform to the OIDC standard when acting as an identity provider. Starting with version 1.20.0, the LILT application can work around this non-conformance, if you leverage two new environment variables, as discussed below.

### SINGLE\_OIDC\_PROVIDER\_OVERRIDES\_RESOURCE\_QUERY\_PARAM

ADFS 2016 needs an additional "resource" query parameter to be used when calling the OIDC authenticaiton endpoint. Set the `SINGLE_OIDC_PROVIDER_OVERRIDES_RESOURCE_QUERY_PARAM` as shown in the YAML at the start of this SSO documentation (above).

### SINGLE\_OIDC\_PROVIDER\_OVERRIDES\_IDTOKEN\_CLAIM\_NAME\_FOR\_LILT\_EMAIL\_ADDRESS

ADFS 2016 does not include the expected `email` property in the response from the Userinfo OIDC endpoint. As a workaround, you can adjust the settings in ADFS 2016 to provide the user's email address as the value of a claim in the ID\_TOKEN. Use the `SINGLE_OIDC_PROVIDER_OVERRIDES_IDTOKEN_CLAIM_NAME_FOR_LILT_EMAIL_ADDRESS` setting as shown in the YAML at the start of this SSO documentation (above) to tell your LILT installation which claim in the ID\_TOKEN will contain the email address.

The following articles might be helpful when attempting to configure ADFS to provide an email address via an ID\_TOKEN claim:

[Blog Michael Boeynaems](https://www.michaelboeynaems.com/keycloak-ADFS-OIDC.html)

[OIDC configuration with AD FS | Qlik Sense for administrators Help](https://help.qlik.com/en-US/sense-admin/May2023/Subsystems/DeployAdministerQSE/Content/Sense_DeployAdminister/QSEoW/Administer_QSEoW/Managing_QSEoW/OIDC-configuration-ADFS.htm)

Note that in the example shown above (and excerpted again below), the `upn` property in the IdToken is being leveraged, but it may or may not correspond to an email address used by your users. It likely is in the same format as an email address, and uniquely identifies a user in your IdentityProvider, and so may be suitable for using in this way if it is not possible to provide an email address via a property in the IdToken.

```yaml theme={null}
front:
  onpremValues
	  env:
	    SINGLE_OIDC_PROVIDER_OVERRIDES_RESOURCE_QUERY_PARAM: "urn:microsoft:userinfo"
	    SINGLE_OIDC_PROVIDER_OVERRIDES_IDTOKEN_CLAIM_NAME_FOR_LILT_EMAIL_ADDRESS: "upn"
```

## SSO Troubleshooting

### Communication paths

The OpenIDConnect (OIDC) standard used in the implementation of SSO in LILT Enterprise depends on two communication paths being open and configured properly:

* the path from user's browser to the OIDC IdentityProvider
* the path from the LILT app-server (front pod in the Kubernetes cluster) to the OIDC IdentityProvider

**Testing communication path from user's browser to the OIDC IdentityProvider:**

It will be apparent whether that first path is open and functioning when the user is redirected to the sign-in page hosted by your OIDC IdentityProvider. If that sign-in page loads, then that path is functioning. (To be clear, this is not the initial "Sign in to LILT" page hosted by the LILT app; rather, it is the page that loads after clicking the "Sign in with SSO" button on the "Sign in to LILT" page.)

It is also informative to load in your browser the "…well-known…" configuration page served up by your OIDC IdentityProvider. The URL will depend on how you have configured your IdentityProvider, but will be something like "https\://YOUR\_IDP\_DOMAIN\_NAME/adfs/.well-known/openid-configuration".

**Testing communication path from the LILT app-server to the OIDC IdentityProvider:**

Determining whether that second path is open and configured appropriately is more challenging. The following steps can be used to help diagnose when there is a problem.

```bash theme={null}
# ssh into the master vm for the Kubernetes cluster
# (exactly how to do that is site specific)
# store the front pod name in a variable, for ease of use
fpod=$(kubectl get pods | grep front | awk '{print $1}')
# "kubectl exec" into the "front" container of the "front" pod
kubectl exec --stdin --tty $fpod -- /bin/sh
#
# At this point, you should have a shell prompt in that front container
#
# Use `curl` to verify domain name of your IdentityProvider can be resolved
curl YOUR_IDP_DOMAIN_NAME
## Failure to resolve will look something like this:
##
## curl: (6) Could not resolve host: YOUR_IDP_DOMAIN_NAME; Unknown error
##
# Use `curl --insecure` to verify the ".well-known" configuration page served by
# your IdentityProvider can loaded, ignoring certificate issues.
# (Note that the "adfs" in the URL below may not match what your IdentityProvider
# uses.  But there should be a URL with ".well-known" that is valid.
curl --insecure https://YOUR_IDP_DOMAIN_NAME/adfs/.well-known/openid-configuration
# If successful, the curl command above should return a result something
# similar to:
## {"issuer":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs","authorization_endpoint":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/oauth2\\/authorize\\/","token_endpoint":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/oauth2\\/token\\/","jwks_uri":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/discovery\\/keys","token_endpoint_auth_methods_supported":["client_secret_post","client_secret_basic","private_key_jwt","windows_client_authentication"],"response_types_supported":["code","id_token","code id_token","id_token token","code token","code id_token token"],"response_modes_supported":["query","fragment","form_post"],"grant_types_supported":["authorization_code","refresh_token","client_credentials","urn:ietf:params:oauth:grant-type:jwt-bearer","implicit","password","srv_challenge","urn:ietf:params:oauth:grant-type:device_code","device_code"],"subject_types_supported":["pairwise"],"scopes_supported":["winhello_cert","user_impersonation","vpn_cert","logon_cert","profile","openid","allatclaims","email","aza"],"id_token_signing_alg_values_supported":["RS256"],"token_endpoint_auth_signing_alg_values_supported":["RS256"],"access_token_issuer":"http:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/services\\/trust","claims_supported":["aud","iss","iat","exp","auth_time","nonce","at_hash","c_hash","sub","upn","unique_name","pwd_url","pwd_exp","mfa_auth_time","sid"],"microsoft_multi_refresh_token":true,"userinfo_endpoint":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/userinfo","capabilities":["kdf_ver2"],"end_session_endpoint":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/oauth2\\/logout","as_access_token_token_binding_supported":true,"as_refresh_token_token_binding_supported":true,"resource_access_token_token_binding_supported":true,"op_id_token_token_binding_supported":true,"rp_id_token_token_binding_supported":true,"frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"device_authorization_endpoint":"https:\\/\\/YOUR_ID_DOMAIN_NAME\\/adfs\\/oauth2\\/devicecode"}
# Use `curl` to verify certificates used by the TLS setup are ok
curl https://YOUR_IDP_DOMAIN_NAME/adfs/.well-known/openid-configuration
# If successful, you should see the same result as the `curl --insecure` command.
# If instead you see something like the output below, you may need to configure
# one or more of the parameters of
#
#     `front.onpremValues.config.singleOidcProviderTlsOptions`
#
# as described in sections above.
#
## curl: (60) SSL certificate problem: unable to get local issuer certificate
## More details here: <https://curl.se/docs/sslcerts.html>
##
## curl failed to verify the legitimacy of the server and therefore could not
## establish a secure connection to it. To learn more about this situation and
## how to fix it, please visit the web page mentioned above.
## command terminated with exit code 60
```

### Deleting session information

When troubleshooting the SSO configuration, it may be helpful to delete session information stored in the browser for both the LILT app and your OIDC IdentityProvider.

To delete session information for the LILT app, load the `/signin` page of the LILT app, and use your browser's tools to delete the cookies and storage associated with the LILT app domain name.

To delete session information associated with your OIDC IdentityProvider, load the "…well-known…" configuration page (e.g., "https\://YOUR\_IDP\_DOMAIN\_NAME/adfs/.well-known/openid-configuration") in the browser, and use your browser's tools to delete the cookies and storage associated with your IdentityProvider.

Note that if you do not delete the session info associated with your OIDC IdentityProvider, when you click on "Sign in with SSO" it may skip taking you to the IdentityProvider's login screen to type in password information; instead, it will re-use the previous successful login session, if any.

### Configuration to TEMPORARILY enable debug logging for SSO

The following configuration will cause details about the HTTP/TLS communication with the OIDC identity provider to be included in the front pod logs. PLEASE BE CAREFUL USING THESE OPTIONS. This extra logging should not be enabled for production use.

```yaml theme={null}
front:
  onpremvalues:
    env:
      DEBUG: "openid-client,lilt:singleOidcProvider"
      NODE_DEBUG: "http,tls"
```

The options can be adjusted to include only a subset of the debug logging available. For instance, you can just specify the `DEBUG` setting shown, but leave out the one for `NODE_DEBUG`.
