Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2f64885
improvement(sso): fix provider lookup, migrate UI to emcn, add enterp…
waleedlatif1 Apr 20, 2026
6183a98
fix(sso): add org membership guard on providers route, fix idpMetadat…
waleedlatif1 Apr 20, 2026
b4e3a98
fix(sso): add org membership guard on register route, fix SP entityID…
waleedlatif1 Apr 20, 2026
613756d
fix(sso): fix SAML script callbackUrl and SP entityID to use app base…
waleedlatif1 Apr 20, 2026
1b3693d
fix(sso): correct SAML callback URL path in script header comment
waleedlatif1 Apr 20, 2026
ef82fcd
fix(sso): restrict SSO provider read/write to org owners and admins
waleedlatif1 Apr 20, 2026
1739a4e
docs(sso): restructure page, fix provider guide accuracy, add externa…
waleedlatif1 Apr 20, 2026
2f2d8bb
fix(sso): correct SAML callback path and generate idpMetadata from ce…
waleedlatif1 Apr 20, 2026
e94f803
fix(sso): always require NEXT_PUBLIC_APP_URL for SAML SP metadata ent…
waleedlatif1 Apr 20, 2026
28e5fea
fix(sso): scope provider query to org only when organizationId is pro…
waleedlatif1 Apr 20, 2026
6831389
fix(sso): escape XML special chars in script idpMetadata generation
waleedlatif1 Apr 20, 2026
b0e38f6
fix(sso): final audit corrections — saml mapping, xml escaping, self-…
waleedlatif1 Apr 20, 2026
93b52e3
fix(sso): redact oidc client secret in providers response, add self-h…
waleedlatif1 Apr 20, 2026
b70ea44
fix(sso): scope redacted-secret lookup to caller's org or userId
waleedlatif1 Apr 20, 2026
cd0fc46
fix(sso): null out oidcConfig on parse failure to prevent unredacted …
waleedlatif1 Apr 20, 2026
aeafa27
fix(sso): use issuer as entityID in auto-generated idp metadata xml
waleedlatif1 Apr 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions apps/docs/content/docs/en/enterprise/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,9 @@ Define permission groups to control what features and integrations team members

## Single Sign-On (SSO)

Enterprise authentication with SAML 2.0 and OIDC support for centralized identity management.
Enterprise authentication with SAML 2.0 and OIDC support. Works with Okta, Azure AD (Entra ID), Google Workspace, ADFS, and any standard OIDC or SAML 2.0 provider.

### Supported Providers

- Okta
- Azure AD / Entra ID
- Google Workspace
- OneLogin
- Any SAML 2.0 or OIDC provider

### Setup

1. Navigate to **Settings** → **SSO** in your workspace
2. Choose your identity provider
3. Configure the connection using your IdP's metadata
4. Enable SSO for your organization

<Callout type="info">
Once SSO is enabled, team members authenticate through your identity provider instead of email/password.
</Callout>
See the [SSO setup guide](/docs/enterprise/sso) for step-by-step instructions and provider-specific configuration.

---

Expand Down
5 changes: 5 additions & 0 deletions apps/docs/content/docs/en/enterprise/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Enterprise",
"pages": ["index", "sso"],
"defaultOpen": false
}
345 changes: 345 additions & 0 deletions apps/docs/content/docs/en/enterprise/sso.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,345 @@
---
title: Single Sign-On (SSO)
description: Configure SAML 2.0 or OIDC-based single sign-on for your organization
---

import { Callout } from 'fumadocs-ui/components/callout'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
import { FAQ } from '@/components/ui/faq'

Single Sign-On lets your team sign in to Sim through your company's identity provider instead of managing separate passwords. Sim supports both OIDC and SAML 2.0.

---

## Requirements

**Sim Cloud:** Enterprise plan. You must be a workspace owner or admin.

**Self-hosted:** Set `SSO_ENABLED=true` and `NEXT_PUBLIC_SSO_ENABLED=true` in your environment. No plan requirement.

---

## Setup

### 1. Open SSO settings

Go to **Settings → Enterprise → Single Sign-On** in your workspace.

### 2. Choose a protocol

| Protocol | Use when |
|----------|----------|
| **OIDC** | Your IdP supports OpenID Connect — Okta, Microsoft Entra ID, Auth0, Google Workspace |
| **SAML 2.0** | Your IdP is SAML-only — ADFS, Shibboleth, or older enterprise IdPs |

### 3. Fill in the form

**Fields required for both protocols:**

| Field | What to enter |
|-------|--------------|
| **Provider ID** | A short slug identifying this connection, e.g. `okta` or `azure-ad`. Letters, numbers, and dashes only. |
| **Issuer URL** | The identity provider's issuer URL. Must be HTTPS. |
| **Domain** | Your organization's email domain, e.g. `company.com`. Users with this domain will be routed through SSO at sign-in. |

**OIDC additional fields:**

| Field | What to enter |
|-------|--------------|
| **Client ID** | The application client ID from your IdP. |
| **Client Secret** | The client secret from your IdP. |
| **Scopes** | Comma-separated OIDC scopes. Default: `openid,profile,email`. |

<Callout type="info">
For OIDC, Sim automatically fetches endpoints (`authorization_endpoint`, `token_endpoint`, `userinfo_endpoint`, `jwks_uri`) from your issuer's `/.well-known/openid-configuration` discovery document. You only need to provide the issuer URL.
</Callout>

**SAML additional fields:**

| Field | What to enter |
|-------|--------------|
| **Entry Point URL** | The IdP's SSO service URL where Sim sends authentication requests. |
| **Identity Provider Certificate** | The Base-64 encoded X.509 certificate from your IdP for verifying assertions. |

### 4. Copy the Callback URL

The **Callback URL** shown in the form is the endpoint your identity provider must redirect users back to after authentication. Copy it and register it in your IdP before saving.

**OIDC providers** (Okta, Microsoft Entra ID, Google Workspace, Auth0):
```
https://simstudio.ai/api/auth/sso/callback/{provider-id}
```

**SAML providers** (ADFS, Shibboleth):
```
https://simstudio.ai/api/auth/sso/saml2/callback/{provider-id}
```

For self-hosted, replace `simstudio.ai` with your instance hostname.

### 5. Save and test

Click **Save**. To test, sign out and use the **Sign in with SSO** button on the login page. Enter an email address at your configured domain — Sim will redirect you to your identity provider.

---

## Provider Guides

<Tabs items={['Okta', 'Microsoft Entra ID', 'Google Workspace', 'ADFS']}>

<Tab value="Okta">

### Okta (OIDC)

**In Okta** ([official docs](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm)):

1. Go to **Applications → Create App Integration**
2. Select **OIDC - OpenID Connect**, then **Web Application**
3. Set the **Sign-in redirect URI** to your Sim callback URL:
```
https://simstudio.ai/api/auth/sso/callback/okta
```
4. Under **Assignments**, grant access to the relevant users or groups
5. Copy the **Client ID** and **Client Secret** from the app's **General** tab
6. Your Okta domain is the hostname of your admin console, e.g. `dev-1234567.okta.com`

**In Sim:**

| Field | Value |
|-------|-------|
| Provider Type | OIDC |
| Provider ID | `okta` |
| Issuer URL | `https://dev-1234567.okta.com/oauth2/default` |
| Domain | `company.com` |
| Client ID | From Okta app |
| Client Secret | From Okta app |

<Callout type="info">
The issuer URL uses Okta's default authorization server (`/oauth2/default`), which is pre-configured on every Okta org. If you created a custom authorization server, replace `default` with your server name.
</Callout>

</Tab>

<Tab value="Microsoft Entra ID">

### Microsoft Entra ID (OIDC)

**In Azure** ([official docs](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app)):

1. Go to **Microsoft Entra ID → App registrations → New registration**
2. Under **Redirect URI**, select **Web** and enter your Sim callback URL:
```
https://simstudio.ai/api/auth/sso/callback/azure-ad
```
3. After registration, go to **Certificates & secrets → New client secret** and copy the value immediately — it won't be shown again
4. Go to **Overview** and copy the **Application (client) ID** and **Directory (tenant) ID**

**In Sim:**

| Field | Value |
|-------|-------|
| Provider Type | OIDC |
| Provider ID | `azure-ad` |
| Issuer URL | `https://login.microsoftonline.com/{tenant-id}/v2.0` |
| Domain | `company.com` |
| Client ID | Application (client) ID |
| Client Secret | Secret value |

<Callout type="info">
Replace `{tenant-id}` with your Directory (tenant) ID from the app's Overview page. Sim auto-discovers token and JWKS endpoints from the issuer.
</Callout>

</Tab>

<Tab value="Google Workspace">

### Google Workspace (OIDC)

**In Google Cloud Console** ([official docs](https://developers.google.com/identity/openid-connect/openid-connect)):

1. Go to **APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client ID**
2. Set the application type to **Web application**
3. Add your Sim callback URL to **Authorized redirect URIs**:
```
https://simstudio.ai/api/auth/sso/callback/google-workspace
```
4. Copy the **Client ID** and **Client Secret**

**In Sim:**

| Field | Value |
|-------|-------|
| Provider Type | OIDC |
| Provider ID | `google-workspace` |
| Issuer URL | `https://accounts.google.com` |
| Domain | `company.com` |
| Client ID | From Google Cloud Console |
| Client Secret | From Google Cloud Console |

<Callout type="info">
To restrict sign-in to your Google Workspace domain, configure the OAuth consent screen and ensure your app is set to **Internal** (Workspace users only) under **User type**. Setting the app to Internal limits access to users within your Google Workspace organization.
</Callout>

</Tab>

<Tab value="ADFS">

### ADFS (SAML 2.0)

**In ADFS** ([official docs](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)):

1. Open **AD FS Management → Relying Party Trusts → Add Relying Party Trust**
2. Choose **Claims aware**, then **Enter data about the relying party manually**
3. Set the **Relying party identifier** (Entity ID) to your Sim base URL:
```
https://simstudio.ai
```
For self-hosted, use your instance's base URL (e.g. `https://sim.company.com`)
4. Add an endpoint: **SAML Assertion Consumer Service** (HTTP POST) with the URL:
```
https://simstudio.ai/api/auth/sso/saml2/callback/adfs
```
For self-hosted: `https://sim.company.com/api/auth/sso/saml2/callback/adfs`
5. Export the **Token-signing certificate** from **Certificates**: right-click → **View Certificate → Details → Copy to File**, choose **Base-64 encoded X.509 (.CER)**. The `.cer` file is PEM-encoded — rename it to `.pem` before pasting its contents into Sim.
6. Note the **ADFS Federation Service endpoint URL** (e.g. `https://adfs.company.com/adfs/ls`)

**In Sim:**

| Field | Value |
|-------|-------|
| Provider Type | SAML |
| Provider ID | `adfs` |
| Issuer URL | `https://simstudio.ai` |
| Domain | `company.com` |
| Entry Point URL | `https://adfs.company.com/adfs/ls` |
| Certificate | Contents of the `.pem` file |

<Callout type="info">
For ADFS, the **Issuer URL** field is the SP entity ID — the identifier ADFS uses to identify Sim as a relying party. It must match the **Relying party identifier** you registered in ADFS.
</Callout>

</Tab>

</Tabs>

---

## How sign-in works after setup

Once SSO is configured, users with your domain (`company.com`) can sign in through your identity provider:

1. User goes to `simstudio.ai` and clicks **Sign in with SSO**
2. They enter their work email (e.g. `alice@company.com`)
3. Sim redirects them to your identity provider
4. After authenticating, they are returned to Sim and added to your organization automatically
5. They land in the workspace

Users who sign in via SSO for the first time are automatically provisioned and added to your organization — no manual invite required.

<Callout type="info">
Password-based login remains available. Forcing all organization members to use SSO exclusively is not yet supported.
</Callout>

<Callout type="info">
**Self-hosted:** Automatic organization provisioning requires `ORGANIZATIONS_ENABLED=true` in addition to `SSO_ENABLED=true`. Without it, SSO authentication still works — users get a valid session — but they are not automatically added to an organization.
</Callout>

---

<FAQ items={[
{
question: "Which SSO providers are supported?",
answer: "Any identity provider that supports OIDC or SAML 2.0. This includes Okta, Microsoft Entra ID (Azure AD), Google Workspace, Auth0, OneLogin, JumpCloud, Ping Identity, ADFS, Shibboleth, and more."
},
{
question: "What is the Domain field used for?",
answer: "The domain (e.g. company.com) is how Sim routes users to the right identity provider. When a user enters their email on the SSO sign-in page, Sim matches their email domain to a registered SSO provider and redirects them there."
},
{
question: "Do I need to provide OIDC endpoints manually?",
answer: "No. For OIDC providers, Sim automatically fetches the authorization, token, and JWKS endpoints from the discovery document at {issuer}/.well-known/openid-configuration. You only need to provide the issuer URL."
},
{
question: "What happens when a user signs in with SSO for the first time?",
answer: "Sim creates an account for them automatically and adds them to your organization. No manual invite is needed. They are assigned the member role by default."
},
{
question: "Can I still use email/password login after enabling SSO?",
answer: "Yes. Enabling SSO does not disable password-based login. Users can still sign in with their email and password if they have one. Forced SSO (requiring all users on the domain to use SSO) is not yet supported."
},
{
question: "Who can configure SSO on Sim Cloud?",
answer: "Organization owners and admins can configure SSO. You must be on the Enterprise plan."
},
{
question: "What is the Callback URL?",
answer: "The Callback URL (also called Redirect URI or ACS URL) is the endpoint in Sim that receives the authentication response from your identity provider. For OIDC providers it follows the format: https://simstudio.ai/api/auth/sso/callback/{provider-id}. For SAML providers it is: https://simstudio.ai/api/auth/sso/saml2/callback/{provider-id}. You must register this URL in your identity provider before SSO will work."
},
{
question: "How do I update or replace an existing SSO configuration?",
answer: "Open Settings → Enterprise → Single Sign-On and click Edit. Update the fields and save. The existing provider configuration is replaced."
}
]} />

---

## Self-hosted setup

Self-hosted deployments use environment variables instead of the billing/plan check.

### Environment variables

```bash
# Required
SSO_ENABLED=true
NEXT_PUBLIC_SSO_ENABLED=true

# Required if you want users auto-added to your organization on first SSO sign-in
ORGANIZATIONS_ENABLED=true
NEXT_PUBLIC_ORGANIZATIONS_ENABLED=true
```

You can register providers through the **Settings UI** (same as cloud) or by running the registration script directly against your database.

### Script-based registration

Use this when you need to register an SSO provider without going through the UI — for example, during initial deployment or CI/CD automation.

```bash
# OIDC example (Okta)
SSO_ENABLED=true \
NEXT_PUBLIC_APP_URL=https://your-instance.com \
SSO_PROVIDER_TYPE=oidc \
SSO_PROVIDER_ID=okta \
SSO_ISSUER=https://dev-1234567.okta.com/oauth2/default \
SSO_DOMAIN=company.com \
SSO_USER_EMAIL=admin@company.com \
SSO_OIDC_CLIENT_ID=your-client-id \
SSO_OIDC_CLIENT_SECRET=your-client-secret \
bun run packages/db/scripts/register-sso-provider.ts
```

```bash
# SAML example (ADFS)
SSO_ENABLED=true \
NEXT_PUBLIC_APP_URL=https://your-instance.com \
SSO_PROVIDER_TYPE=saml \
SSO_PROVIDER_ID=adfs \
SSO_ISSUER=https://your-instance.com \
SSO_DOMAIN=company.com \
SSO_USER_EMAIL=admin@company.com \
SSO_SAML_ENTRY_POINT=https://adfs.company.com/adfs/ls \
SSO_SAML_CERT="-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----" \
bun run packages/db/scripts/register-sso-provider.ts
```

The script outputs the callback URL to configure in your IdP once it completes.

To remove a provider:

```bash
SSO_USER_EMAIL=admin@company.com \
bun run packages/db/scripts/deregister-sso-provider.ts
```
2 changes: 1 addition & 1 deletion apps/docs/content/docs/en/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"execution",
"permissions",
"self-hosting",
"./enterprise/index",
"enterprise",
"./keyboard-shortcuts/index"
],
"defaultOpen": false
Expand Down
Binary file added apps/docs/public/static/enterprise/sso-form.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading