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

# Okta SAML SSO

> Connect Okta to OpenWork Cloud or a self-hosted OpenWork deployment with SAML

Use this guide to let organization members sign in to OpenWork through an
Okta application integration. It works for OpenWork Cloud and for a Helm
deployment with a public HTTPS web origin.

After SAML sign-in works, use [Okta SCIM provisioning](/docs/cloud/scim-okta) to
synchronize members and groups.

## Before you start

You need:

* An OpenWork owner, or a member who can manage security configuration.
* An Okta administrator who can create and assign application integrations.
* Control of DNS for the email domain you will associate with the connection.
* The final HTTPS OpenWork web origin, for example
  `https://openwork.example.com`.

OpenWork keeps a new SSO configuration disabled until you verify the domain,
complete a real authentication test, and explicitly enable SSO. Keep password
access available as a recovery path during setup.

<Note>
  For a Helm deployment with separate web and API hosts, use the URLs OpenWork
  shows in **Settings → SSO**. Do not replace their host with the separate API
  origin. SAML uses the deployment's configured auth origin, which is normally
  the public web origin when `/api/auth` is proxied through the web host.
</Note>

## 1. Get the organization ID

In OpenWork, select the organization and open **Settings → General**. Copy the
organization ID. OpenWork creates the SAML provider ID as:

```text theme={null}
openwork-sso-<organization-id>
```

The corresponding assertion consumer service URL is:

```text theme={null}
https://<openwork-web-origin>/api/auth/sso/saml2/sp/acs/openwork-sso-<organization-id>
```

You can confirm the exact generated URL after saving the OpenWork connection.

## 2. Create the Okta SAML application

In the Okta Admin Console:

1. Open **Applications → Applications**.
2. Select **Create App Integration**.
3. Choose **SAML 2.0**, then select **Next**.
4. Set **App name** to `OpenWork` or another recognizable workspace name.
5. Select **Next**.

## 3. Configure SAML in Okta

Under **General**, enter:

| Okta field                                     | Value                                                               |
| ---------------------------------------------- | ------------------------------------------------------------------- |
| Single sign-on URL                             | The OpenWork ACS URL from step 1                                    |
| Use this for Recipient URL and Destination URL | Enabled                                                             |
| Audience URI (SP Entity ID)                    | The OpenWork web origin, for example `https://openwork.example.com` |
| Default RelayState                             | Leave blank                                                         |
| Name ID format                                 | `EmailAddress`                                                      |
| Application username                           | `Okta username`                                                     |

Open **Show Advanced Settings** and confirm:

* **Response**: `Signed`
* **Assertion Signature**: `Signed`
* **Signature Algorithm**: `RSA-SHA256`
* **Digest Algorithm**: `SHA256`
* **Assertion Encryption**: `Unencrypted`

OpenWork requires a signed assertion. Keep the Okta username and NameID equal
to the stable work email that SCIM will later send as `userName`.

Select **Next**, mark the integration as an internal application when
appropriate, then select **Finish**.

## 4. Copy Okta values into OpenWork

In the Okta application's **Sign On** tab, select
**View SAML setup instructions**. Copy:

* **Identity Provider Single Sign-On URL**
* **Identity Provider Issuer**
* **X.509 Certificate**, including the `BEGIN CERTIFICATE` and
  `END CERTIFICATE` lines

In OpenWork, open **Settings → SSO**, select **SAML**, and enter:

| OpenWork field   | Okta value                                             |
| ---------------- | ------------------------------------------------------ |
| IdP Issuer URL   | **Identity Provider Issuer**                           |
| Domain           | The members' email domain, for example `example.com`   |
| SAML Entry Point | **Identity Provider Single Sign-On URL**               |
| Audience URL     | Leave blank to use the configured OpenWork auth origin |
| IdP Certificate  | **X.509 Certificate**                                  |

Save the connection. OpenWork then shows setup values including **Sign-in URL**,
**Redirect URL**, **ACS URL**, and **Metadata URL**. Compare the generated
**ACS URL** with Okta's **Single sign-on URL** character for character. Also
copy the generated OpenWork **Sign-in URL** into Okta if you want the Okta tile
to launch the same organization-scoped flow.

The saved configuration is still disabled at this point.

## 5. Verify the email domain

Select **Request token** under **Domain verification**. Create a DNS TXT
record for the email domain:

| DNS field | Value                              |
| --------- | ---------------------------------- |
| Type      | `TXT`                              |
| Name      | `_better-auth-token-<provider-id>` |
| Value     | The token OpenWork displays        |

For example, provider `openwork-sso-org_123` for `example.com` produces:

```text theme={null}
_better-auth-token-openwork-sso-org_123.example.com
```

In a DNS console that automatically appends the zone, enter only
`_better-auth-token-<provider-id>` in the name field. The token is valid for
seven days. After the TXT record resolves publicly, select **Verify domain**
in OpenWork and confirm the connection shows **Domain verified: Yes**.

## 6. Assign a test user in Okta

In the Okta application:

1. Open **Assignments**.
2. Select **Assign → Assign to People**.
3. Assign one OpenWork owner or another controlled test user.
4. Confirm the application username is that user's stable work email.

Do not assign broad groups until the test user can complete the full flow.

## 7. Test and enable SSO in OpenWork

After the Okta assignment and domain verification are complete:

1. In OpenWork **Settings → SSO**, select **Enable Config** or **Enable SSO**.
2. In the **Test SSO before enabling it** dialog, select **SSO Login**.
3. Complete Okta authentication in the separate window.
4. Return to OpenWork and confirm **Authentication test successful**.
5. Select **Enable SSO**.

During the test, confirm that:

1. OpenWork redirects to the expected Okta tenant.
2. Okta authenticates the assigned user.
3. Okta posts the assertion to the generated OpenWork ACS URL.
4. OpenWork returns the user to the intended organization.
5. The member identity in OpenWork uses the same email that Okta sent as
   NameID.

SSO is not offered to organization members until you explicitly enable it after
the successful test. If you edit the SSO configuration after a successful test,
test it again before enabling. Test links expire after five minutes.

Only after this succeeds should you configure SCIM.

## Just-in-time provisioning and password signup

After Okta SAML SSO is enabled for a verified domain, OpenWork's standard
sign-in flow routes users with that email domain to the organization SSO flow.
When a user completes SAML sign-in successfully, OpenWork can create their
organization membership just in time with the default `Member` role.

JIT provisioning happens only after successful SAML authentication. Creating an
email/password account with the same email domain does not add the user to the
organization or create a SCIM-managed identity. If that user later completes
SSO, OpenWork can link the matching account and provision the organization
membership through SSO.

OpenWork does not convert SAML attributes such as `role`, `groups`, or `admin`
into elevated organization roles. Assign `Admin`, `Owner`, or custom roles in
OpenWork after review, or through an invitation that grants the intended role.

## Troubleshooting

| Symptom                                                                                      | Likely cause                                                                                                 | Fix                                                                                                               |
| -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| `Provider domain has not been verified`                                                      | The TXT record is missing, attached to the zone apex, or has not propagated                                  | Put the token at `_better-auth-token-<provider-id>.<domain>`, wait for public DNS, then select **Verify domain**  |
| `invalid_saml_configuration`                                                                 | The OpenWork build did not persist the generated ACS callback URL in the SAML provider                       | Upgrade to a build containing the SAML callback configuration fix, then edit and save the connection again        |
| `invalid_audience`                                                                           | Okta's Audience URI does not match OpenWork's configured auth origin                                         | Use the OpenWork web/auth origin shown by the deployment; do not substitute a separate API host                   |
| `invalid_destination` or `invalid_recipient`                                                 | Okta is posting to a different URL than OpenWork expects                                                     | Copy the generated OpenWork ACS URL into Okta and keep **Use this for Recipient URL and Destination URL** enabled |
| `Invalid SAML response`                                                                      | The assertion is unsigned, uses a deprecated algorithm, or the active Okta certificate differs from OpenWork | Sign the assertion with RSA-SHA256 and paste Okta's current active X.509 certificate into OpenWork                |
| Okta refuses access                                                                          | The person is not assigned to the application                                                                | Assign the test user under **Assignments**                                                                        |
| OpenWork shows **Verify the SSO domain before testing this configuration**                   | The DNS TXT proof has not passed yet                                                                         | Create the TXT record shown by OpenWork, wait for DNS propagation, then select **Verify domain**                  |
| The test dialog shows **The SSO authentication window was closed before the test completed** | The popup was closed or redirected away before OpenWork received the test result                             | Start a new test and keep the authentication window open until it returns or closes itself                        |
| OpenWork will not enable SSO after editing settings                                          | The current configuration has not been tested successfully                                                   | Run **SSO Login** again, then select **Enable SSO** after the successful test                                     |
