---
title: "WorkOS"
description: "Use WorkOS for enterprise-ready MainSDK auth - environment setup, redirect URIs, main.yaml, API keys, local testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/workos"
updated: "2026-10-28"
---

# WorkOS

> Use WorkOS for enterprise-ready MainSDK auth - environment setup, redirect URIs, main.yaml, API keys, local testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/workos · Updated: 2026-10-28

WorkOS is a hosted identity service built for apps that sell to companies, with single sign-on and directory sync for your customers' organisations. Behind [`auth`](https://mainsdk.dev/docs/interfaces/auth), it holds your users while your routes keep one way to read the session and require a role. Pick WorkOS when enterprise customers are your main audience and you want their SSO connections managed by a provider.

## Interfaces it serves

### Sign-in and sessions (`auth`)

- Status: Building for 0.3 · ships as a stable API
- Driver: `workos` (WorkOS)
- Docs: https://mainsdk.dev/docs/interfaces/auth.md

```yaml
auth:
  driver: workos
```

Swap to another provider: `github`, `clerk`, `auth0`, `better-auth`, `supabase`, `local`.

## Before you start

You need a WorkOS account.

1. **Use separate environments.** WorkOS gives you a staging and a production environment, each with its own keys.
2. **Copy the API key and client ID** for each environment.
3. **Add your redirect URIs**: the route that receives WorkOS's redirect after sign-in. The path MainSDK mounts is not defined yet [TBD].

## Configure

```yaml title="main.yaml"
auth:
  driver: workos
  methods: [passkeys, sso]
  sso: { protocols: [saml, oidc], scim: true }
  # [TBD] key names; suggested secrets: WORKOS_API_KEY, WORKOS_CLIENT_ID
```

The `auth` spec does not define the driver's credential keys yet; they take `secret:` references when it does.

## Use it

```ts title="app/sign-in/sso/route.ts"
import { auth } from "mainsdk";

export async function POST(req: Request) {
  const { email } = await req.json();
  return auth.sso.signIn(req, { email });   // routes by verified email domain
}
```

## Local development and testing

Use the `local` auth driver in development and WorkOS's staging environment to try real SSO. In tests, `createTestApp()` from `@mainsdk/testing` runs `auth` on its in-memory fake, and `chaos.on("auth", { outage: true })` checks that `auth.require()` fails closed.

## What MainSDK adds on top

- Short-lived, device-bound sessions with rotating refresh tokens.
- Passkeys by default, phishing-resistant.
- Fails closed when WorkOS cannot be reached.
- SAML assertions checked for signature, audience and replay (`MAIN-AUTH-0008`); OIDC `state` and `nonce` checked (`MAIN-AUTH-0007`).

See [Sign-in and sessions](https://mainsdk.dev/docs/interfaces/auth).

## Limits and notes

- The WorkOS driver and its capability profile have a ticket in the `auth` spec next to Auth0.
- Users stay in your WorkOS environment (`byo-identity`). Check where WorkOS stores data against your residency needs.
- `auth.raw()` returns the WorkOS client; `mainsdk check` lists every use.

## Swap to or from it

```yaml title="main.yaml"
auth:
  driver: auth0   # was workos
```

> **Warning:** Users and their SSO connections live in WorkOS. Moving them is a migration that MainSDK runs as a guided job with a rollback, and each customer's IdP may need its settings updated.

## FAQ

**Is this SSO for the MainSDK console?** No. This driver signs your app's users in. Console SSO is a separate MainSDK Cloud feature.

**Do I need WorkOS to offer SSO?** No. MainSDK provides SAML and SCIM in your app on top of any driver that lacks them.

## Next

- [Sign-in and sessions](https://mainsdk.dev/docs/interfaces/auth)
- [Auth0](https://mainsdk.dev/docs/integrations/auth0) and [Clerk](https://mainsdk.dev/docs/integrations/clerk)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
