WorkOS Integration
Use WorkOS for B2B authentication when AuthKit, enterprise SSO, and organization-aware sessions should sit behind Farm-owned routes.
This adapter covers AuthKit sign-in and sealed sessions. Directory Sync and other WorkOS APIs remain separate application integrations.
Add WorkOS
farm add integration workos --ui
Configure
import { workos } from "@farmjs/integrations/workos";export const appIntegrations = { auth: workos({ clientId: process.env.WORKOS_CLIENT_ID, apiKey: process.env.WORKOS_API_KEY, cookiePassword: process.env.WORKOS_COOKIE_PASSWORD, callbackPath: "/callback", protectedRoutes: ["/dashboard(.*)"], }),} as const;export type AppIntegrations = typeof appIntegrations;
Farm builds the absolute redirect URI from the incoming request origin and callbackPath. Register that exact URL in WorkOS, for example https://app.example.com/callback.
Environment variables
| Variable | Required | Purpose |
|---|---|---|
WORKOS_CLIENT_ID |
Yes | AuthKit client ID. |
WORKOS_API_KEY |
Yes | Server-side WorkOS API key. |
WORKOS_COOKIE_PASSWORD |
Production | Encrypts and seals the AuthKit session cookie. |
FARM_WORKOS_COOKIE_PASSWORD |
Alternative | Backward-compatible cookie password name. |
Development has a local fallback cookie password. Production startup fails without an explicit password.
Routes and methods
| Method | Default route | Purpose |
|---|---|---|
GET |
/login |
Starts AuthKit sign-in. |
GET |
/signup |
Starts AuthKit sign-up. |
GET |
/callback |
Exchanges the code and stores the sealed session. |
POST |
/logout |
Clears the cookie and redirects through WorkOS logout. |
GET |
/auth/session |
Returns the authenticated user, session ID, and organization ID. |
Override these routes with loginPath, signUpPath, callbackPath, logoutPath, and sessionPath.
Start an AuthKit flow
Document navigation redirects directly:
<a href="/login?returnTo=/dashboard">Sign in</a><a href="/signup?returnTo=/dashboard">Create account</a>
The typed client returns the provider URL:
const result = await apiClient.auth.login.get({ query: { returnTo: "/dashboard", },});if (result.data) { window.location.assign(result.data.redirectTo);}
Read the sealed session
const result = await api.auth.session.get();if (result.error && "status" in result.error && result.error.status === 401) { // No authenticated WorkOS session.}const organizationId = result.data?.organizationId;const user = result.data?.user;
An authenticated response contains:
{ authenticated: true; sessionId?: string; organizationId?: string; user: { id: string; email: string; firstName?: string | null; lastName?: string | null; profilePictureUrl?: string | null; };}
The organization ID is useful for looking up your app's tenant record. Authorization roles and permissions still need to be resolved by your application.
Logout
const result = await apiClient.auth.logout.post();if (result.data) { window.location.assign(result.data.redirectTo);}
Farm clears the local cookie first. If a sealed session exists, WorkOS supplies the final logout URL; otherwise the user returns to the app origin.
Protect app routes
workos({ protectedRoutes: ["/dashboard(.*)", "/settings(.*)"],});
Signed-out requests receive a 307 redirect to /login with the original root-relative path in returnTo.
Options
| Option | Default | Use |
|---|---|---|
clientId |
WORKOS_CLIENT_ID |
AuthKit client ID. |
apiKey |
WORKOS_API_KEY |
Server API key. |
cookiePassword |
WorkOS cookie env | Sealed-session password. |
cookieName |
wos-session |
Session cookie name. |
loginPath |
/login |
Sign-in route. |
signUpPath |
/signup |
Sign-up route. |
callbackPath |
/callback |
AuthKit callback route. |
logoutPath |
/logout |
Logout route. |
sessionPath |
/auth/session |
Session JSON route. |
protectedRoutes |
None | One matcher or a list of matchers. |
Production checklist
- Register the production callback URL in WorkOS.
- Use a strong
WORKOS_COOKIE_PASSWORD. - Confirm the public request origin is preserved by your proxy.
- Test personal and organization-backed sessions.
- Map
organizationIdto an application tenant before authorizing tenant data.