# Guide to Okta SAML App Integration for RiskOS™ SSO

This guide walks through setting up an Okta SAML app integration for RiskOS™ Single Sign-On (SSO) using the new account architecture. You configure the Okta application, map the required SAML attributes, assign users, and retrieve the metadata URL that Socure uses to register your identity provider.

> ⚠️  
> **Before You Start**:  
> Request your Socure Support for your public account ID. The public account ID would be in the following format: acc-XXXXXXXXXX e.g. acc-gU5p9W5wFj

## URLs and Attributes

### Attributes
Map the following SAML attributes in your Okta application:

| SAML attribute                                                         | Format      | Application attribute                       | Description                                                                                                                |
|-----------------------------------------------------------------------|-------------|--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| `accountContext`                                                      | Unspecified | `identityProvider`                         | "saml-<publicAccountId>-<envId>"<br>e.g. "saml-acc-gU5p9W5wFj-1"<br>NOTE: Need to be enclosed by double quotes.         |
| `urn:oid:2.5.4.42`                                                  | Unspecified | `user.firstName` or `user.profile.firstName` | First name                                                                                                               |
| `urn:oid:2.5.4.4`                                                   | Unspecified | `user.lastName` or `user.profile.lastName`   | Last name                                                                                                                |
| `urn:oid:2.5.4.20`                                                  | Unspecified | `user.phoneNumber` or `user.profile.mobilePhone` | Phone number                                                                                                            |
| `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`            | Unspecified | `user.email` or `user.profile.email`          | Email address                                                                                                           |
| `https://dashboard.socure.com/attributes/role`                      | URI Reference | `String.join(",", appUser.RoleName)`    | User roles                                                                                                              |

### SAML Endpoints

| Field                | Purpose                                                                                         | Example value                                                                                                          |
|----------------------|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
| ACS URL              | Endpoint where the IdP posts the SAML response.                                                | `https://user-access-manager-prod.auth.us-east-1.amazoncognito.com/saml2/idpresponse`                                 |
| Audience Restriction  | Identifies the Cognito User Pool acting as the SP (must match the SAML audience).              | `urn:amazon:cognito:sp:us-east-1_fXpfelaxM`                                                                          |
| Default Relay State  | Tells Cognito which IdP to use and where to redirect after authentication.                       | `identity_provider=saml-<publicAccountId>-<envId>&client_id=hh218b94fhq1f15k0qgtp9quc&redirect_uri=https://api-dashboardv2.socure.com/saml/SSO&response_type=code&scope=openid`   |

#### Default Relay State — Parameter Breakdown

| Parameter          | Description                                                                                                                      |
|---------------------|----------------------------------------------------------------------------------------------------------------------------------|
| `identity_provider` | SAML identity provider name (`saml-<publicAccountId>-<envId>`)<br>E.g. `saml-acc-gU5p9W5wFj-1`<br>1 is for RiskOS Production<br>3 is for RiskOS Sandbox |
| `client_id`        | Cognito app client ID. Needs to be the following specific value:<br>`hh218b94fhq1f15k0qgtp9quc`                                   |
| `redirect_uri`     | Dashboard SSO callback endpoint. Needs to be the following specific value:<br>`https://api-dashboardv2.socure.com/saml/SSO`     |
| `response_type`    | OAuth response type. Needs to be the following specific value: `code`                                                              |
| `scope`            | Requested OAuth scope. Needs to be the following specific value: `openid`                                                          |

> 📘  
> **Environment ID**:  
> Use the suffix that matches your environment in the `identity_provider` value:
> - `1` — Production
> - `3` — Sandbox

## Multi-IdP: Multiple Identity Providers per Account
A single account can have multiple SAML Identity Providers (e.g., separate Okta apps for different teams, regions, or IdP vendors).
Each IdP is distinguished by an **alias** — 1–6 character lowercase alphanumeric suffix appended to the provider name.

### Provider Naming

| **Scenario**               | **Provider Name Format**                                     | **Example**                  |
|-----------------------------|-------------------------------------------------------------|-------------------------------|
| Single IdP (default)      | `saml-<publicAccountId>-<envId>`                            | `saml-acc-JOOrE07GA2-1`      |
| Multi-IdP (with alias)    | `saml-<publicAccountId>-<envId>-<alias>`                   | `saml-acc-JOOrE07GA2-1-okta1`|

**Alias rules:**
- 1–6 characters
- Lowercase alphanumeric only (`a-z`, `0-9`)
- Must be unique per account + envId combination
- Examples: `okta1`, `emea`, `ping`, `clnt1`

### Setup
1. **First IdP** — create without alias (backward compatible):  
   JSON  
   ```json
   {
     "publicAccountId": "acc-JOOrE07GA2",
     "metadataUrl": "<https://idp-1.example.com/sso/saml/metadata>",
     "envId": 1
   }
   ```  
   → Provider name: `saml-acc-JOOrE07GA2-1`

2. **Additional IdPs** — create with alias:  
   JSON  
   ```json
   {
     "publicAccountId": "acc-JOOrE07GA2",
     "metadataUrl": "<https://idp-2.example.com/sso/saml/metadata>",
     "envId": 1,
     "alias": "clnt1"
   }
   ```  
   → Provider name: `saml-acc-JOOrE07GA2-1-clnt1`

### Default Relay State for Multi-IdP
Each IdP needs its own relay state with the correct `identity_provider` value:

| **IdP**                  | **identity_provider**              |
|---------------------------|------------------------------------|
| Primary (no alias)      | `saml-acc-JOOrE07GA2-1`            |
| Secondary (alias: `clnt1`) | `saml-acc-JOOrE07GA2-1-clnt1`    |

### Role Behavior with Multiple IdPs
| **Scenario**                                                     | **Behavior**                                                   |
|------------------------------------------------------------------|---------------------------------------------------------------|
| User logs in via IdP-1 with `role-1`                            | `role-1` is assigned                                          |
| Same user logs in via IdP-2 with `role-2`                        | `role-1` is removed, `role-2` is assigned (replace strategy) |
| IdP sends no roles / invalid roles                                 | Existing roles are retained (no change)                       |
| User is Account Owner and IdP omits Account Owner role          | Login is **blocked** (Account Owner demotion protection)      |

## Create an Okta App Integration
### Step 1 — Create the app integration
In the Okta Admin Console, go to **Applications > Applications**, click **Create App Integration**, select **SAML 2.0**, and click **Next**.

### Configure the SAML Integration
### Step 1 — General Settings  
Confirm the **App name** under **General Settings**, then continue to the SAML configuration.

### Step 2 — Configure SAML Settings  
Enter the values Socure provides for your environment:
- **Single sign-on URL** — the ACS URL. Keep **Use this for Recipient URL and Destination URL** selected.
- **Audience URI (SP Entity ID)** — the SP entity ID.
- **Default RelayState** — the relay state string for your account and environment.
- **Name ID format** — Select **EmailAddress**.

### Step 3 — Finish  
Complete the feedback step and click **Finish**.

## Add Attribute Statements  
On the application's **Sign On** settings, add the attribute statements listed in the Attributes section. Map each SAML attribute name to the corresponding Okta user profile attribute.

> 📘  
> **Note**:  
> `email`, `firstName` and `lastName` are required for just-in-time (JIT) user provisioning. Map the role attribute only if you assign specific roles through SAML.

### Map the Role Attribute (Optional)  
To manage RiskOS™ roles through SAML, create a custom **RoleName** attribute on the application profile before you add the role attribute statement:
1. Go to **Directory > Profile Editor** and select your application.

2. Click **Add Attribute**, then configure the attribute:
- **Data type** — String array
- **Display name** — `https://dashboard.socure.com/attributes/role`
- **Variable name** — `RoleName`
- **Enum** — Selected
- **Attribute members** — Add one member for each role you assign. The **value** must match a valid RiskOS™ role name; the display name is your choice.

3. Save the attribute. The new **RoleName** attribute appears in the application's Attributes list.

4. **Add Expressions**

> 📘  
> **Default role**:  
> If the SAML assertion does not include a `RoleName` value, RiskOS™ assigns auto-created users the **Fraud Analyst** role by default during Just-In-Time (JIT) creation i.e. upon first ever sign-in. An administrator can change the role from the **Users** page in the RiskOS™ Dashboard.

**Sample Decoded SAML Assertion (as received by Socure)**

```xml
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response Destination="https://user-access-manager-dev.auth.us-east-1.amazoncognito.com/saml2/idpresponse" ID="id-60329139073102282801583932823" IssueInstant="2026-07-01T11:27:37.545Z" Version="2.0"
	xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
	xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
		xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.okta.com/exk14qkxh9z8VaWWV698
	</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/2001/04/xmldsig-more#rsa-sha256"/>
			<ds:Reference URI="#id-60329139073102282801583932823">
				<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 PrefixList="xs"
							xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
					</ds:Transform>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>3udT9hC/arsz7afkfwPVsAnEqS5KcaLdFGJ4TH7PpfM=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>REDACTED_SIGNATURE_VALUE==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIIDxxxxxxxx...REDACTED_CERTIFICATE...xxxxxxxx==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<saml2p:Status
		xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
		<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
	</saml2p:Status>
	<saml2:Assertion ID="id98007094508477714852680778" IssueInstant="2026-07-01T11:27:37.545Z" Version="2.0"
		xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
		xmlns:xs="http://www.w3.org/2001/XMLSchema">
		<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
			xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.okta.com/exk14qkxh9z8VaWWV698
		</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/2001/04/xmldsig-more#rsa-sha256"/>
				<ds:Reference URI="#id98007094508477714852680778">
					<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 PrefixList="xs"
							xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
						</ds:Transform>
					</ds:Transforms>
					<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
					<ds:DigestValue>kIqZpZBYdSibCBYHq1vbUi6QO4GgY79Q0+nxqZLYGjM=</ds:DigestValue>
				</ds:Reference>
			</ds:SignedInfo>
			<ds:SignatureValue>REDACTED_SIGNATURE_VALUE==</ds:SignatureValue>
			<ds:KeyInfo>
				<ds:X509Data>
					<ds:X509Certificate>MIIDxxxxxxxx...REDACTED_CERTIFICATE...xxxxxxxx==</ds:X509Certificate>
				</ds:X509Data>
			</ds:KeyInfo>
		</ds:Signature>
		<saml2:Subject
		xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@example.com</saml2:NameID>
			<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml2:SubjectConfirmationData NotOnOrAfter="2026-07-01T11:32:37.545Z" Recipient="https://user-access-manager-dev.auth.us-east-1.amazoncognito.com/saml2/idpresponse"/>
			</saml2:SubjectConfirmation>
		</saml2:Subject>
		<saml2:Conditions NotBefore="2026-07-01T11:22:37.545Z" NotOnOrAfter="2026-07-01T11:32:37.545Z"
		xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:AudienceRestriction>
				<saml2:Audience>urn:amazon:cognito:sp:us-east-1_sSSrar2Dx</saml2:Audience>
			</saml2:AudienceRestriction>
		</saml2:Conditions>
		<saml2:AuthnStatement AuthnInstant="2026-07-01T11:23:59.841Z" SessionIndex="id1782905257374.553763817"
		xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:AuthnContext>
				<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
			</saml2:AuthnContext>
		</saml2:AuthnStatement>
		<saml2:AttributeStatement
		xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
			<saml2:Attribute Name="https://dashboard.socure.com/attributes/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
				<saml2:AttributeValue
				xmlns:xs="http://www.w3.org/2001/XMLSchema"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Analyst
				</saml2:AttributeValue>
			</saml2:Attribute>
			<saml2:Attribute Name="accountContext" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue
				xmlns:xs="http://www.w3.org/2001/XMLSchema"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">saml-acc-JOOrE07GA2-3
				</saml2:AttributeValue>
			</saml2:Attribute>
			<saml2:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue
				xmlns:xs="http://www.w3.org/2001/XMLSchema"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">user@example.com
				</saml2:AttributeValue>
			</saml2:Attribute>
			<saml2:Attribute Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue
				xmlns:xs="http://www.w3.org/2001/XMLSchema"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Jane
				</saml2:AttributeValue>
			</saml2:Attribute>
			<saml2:Attribute Name="urn:oid:2.5.4.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
				<saml2:AttributeValue
				xmlns:xs="http://www.w3.org/2001/XMLSchema"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Doe
				</saml2:AttributeValue>
			</saml2:Attribute>
		</saml2:AttributeStatement>
	</saml2:Assertion>
</saml2p:Response>
```

## Assign the Application to a User
### Step 1 — Add a User
In **Directory > People**, click **Add person**.

### Step 2 — Enter the User Details
Enter the user's first name, last name, username, and primary email, then save.

### Step 3 — Assign the Application to the User
Open the application's **Assignments** tab, click **Assign**, and assign the user. Set the **RoleName** values for the user as needed, then save.

### Step 4 — Confirm the Assignment
Confirm that the user appears in the application's **Assignments** list.

## Retrieve the Metadata URL
On the application's **Sign On** tab, copy the **Metadata URL** from the **Metadata details** section. Share this URL with Socure to complete the identity provider setup.

## SAML Configuration Checklist
### Request your Public Account ID from Socure Support or your Account Manager
This is a pre-requisite step before you start your SAML configuration.

### Set up SAML App for RiskOS Sandbox
Set up Okta SAML app (ACS URL, Entity ID) for RiskOS Sandbox
- Map `email` attribute (`urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` → `user.profile.email`) — required for JIT
- Map `accountContext` attribute with correct account context (as specified for `identityProvider` in Default Relay State) — required for JIT
- Map `firstName` (`urn:oid:2.5.4.42` → `user.profile.firstName`) — required for JIT
- Map `lastName` (`urn:oid:2.5.4.4` → `user.profile.lastName`) — required for JIT
- (Optional) Map role attribute if you want to control roles assigned to user dynamically from your IdP side.
- Assign users/groups to the SAML app
- Share the metadata URL with Socure to complete the SAML configuration on Socure's side

### Set up SAML App for RiskOS Production
Set up Okta SAML app (ACS URL, Entity ID) for RiskOS Production
- Map `email` attribute (`urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress` → `user.profile.email`) — required for JIT
- Map `accountContext` attribute with correct account context (as specified for `identityProvider` in Default Relay State) — required for JIT
- Map `firstName` (`urn:oid:2.5.4.42` → `user.profile.firstName`) — required for JIT
- Map `lastName` (`urn:oid:2.5.4.4` → `user.profile.lastName`) — required for JIT
- (Optional) Map role attribute if you want to control roles assigned to user dynamically from your IdP side.
- Assign users/groups to the SAML app
- Share the metadata URL with Socure to complete the SAML configuration on Socure's side

### Additional IdP (if needed)
Create a separate Okta SAML app for the new IdP
- Configure ACS URL, Entity ID, and attributes (same as primary)
- Set the Default Relay State with the aliased `identity_provider` name
- Register the IdP in UAM with the `alias` field
- Test login to verify the correct provider name and roles flow through
- Share the metadata URL with Socure to complete the SAML configuration on Socure's side

### Socure SAML Configuration
After you complete the Okta configuration, share the **metadata URL** and your **public account ID** with Socure. Socure registers the identity provider and enables SAML for your account.

### Verification
- Test login with a new user — verify JIT creates user with correct name, roles, and use cases
- Test login with an existing user — verify roles and profile sync correctly

Updated 2 days ago
