- Published on
WorkOS for Enterprise Auth — SSO, SCIM, and Audit Logs in a Day
- Authors

- Name
- Sanjeev Sharma
- @webcoderspeed1
Introduction
Enterprise customers demand SAML SSO, SCIM user provisioning, and audit logs. Building these from scratch takes 3-6 months. WorkOS bundles all three into a unified API that you integrate in days, not quarters.
This post covers WorkOS''s core features, how to onboard your first enterprise customer with SSO, and the business case for when enterprise auth becomes necessary.
- What Enterprise Customers Demand
- WorkOS SSO with 30+ IdP Connectors
- SCIM User Provisioning/Deprovisioning
- Admin Portal for Self-Service SSO Setup
- Audit Log Events for Compliance
- Directory Sync
- Typescipt SDK Integration
- Adding WorkOS to Existing Auth System
- Pricing Model and Break-Even Point
- Checklist
- Conclusion
What Enterprise Customers Demand
SAML SSO: Users log in via their corporate identity provider (Okta, Azure AD, Google Workspace) instead of creating another password.
SCIM Provisioning: When an employee joins the company, they''re automatically added to your application. When they leave, they''re deprovisioned.
Audit Logs: Security teams need proof of who accessed what, when, and from where. For compliance (SOC 2, HIPAA), audit logs are mandatory.
Admin Portal: Customers want self-service setup. They configure SSO in your UI without contacting support.
Directory Sync: Keep employee lists in sync without manual CSV uploads.
WorkOS provides all of this via API and hosted UI components.
WorkOS SSO with 30+ IdP Connectors
WorkOS supports every major identity provider: Okta, Azure AD, Google Workspace, Ping Identity, and 25+ more.
import { WorkOS } from '@workos-inc/node';
const workos = new WorkOS(process.env.WORKOS_API_KEY);
// Initiate SAML login
const authorizationURL = workos.sso.getAuthorizationURL({
domain: 'customer-domain.com',
redirectURI: 'https://app.example.com/sso/callback',
clientID: 'client_id',
});
// User is redirected to their IdP, logs in, returns with code
// Exchange code for session
const { user, sessionToken } = await workos.sso.authenticateWithCode({
code: 'auth_code',
clientID: 'client_id',
});
// User is now authenticated
return res.json({ user, sessionToken });
Setup is minutes. WorkOS handles all IdP-specific SAML nuances.
SCIM User Provisioning/Deprovisioning
When a customer enables SCIM in their identity provider, new employees appear in your database automatically.
// Set up SCIM endpoint
app.post('/api/scim/v2/users', async (req, res) => {
// WorkOS sends user data via SCIM
const { userName, name, emails } = req.body;
await db.users.create({
data: {
email: emails[0].value,
firstName: name.givenName,
lastName: name.familyName,
organisationId: req.organisationId, // From WorkOS directory
},
});
return res.json({
id: 'scim_user_id',
userName,
name,
emails,
active: true,
});
});
// Deprovisioning
app.delete('/api/scim/v2/users/:id', async (req, res) => {
await db.users.update({
where: { scimId: req.params.id },
data: { deletedAt: new Date() },
});
return res.status(204).send();
});
Employees appear in your app within seconds of being added to Okta or Azure AD.
Admin Portal for Self-Service SSO Setup
Instead of emailing configuration details to customers, embed WorkOS''s setup flow in your app.
// In your admin dashboard
import { Organizations } from '@workos-inc/react';
export function SSOSetup({ organizationId }: { organizationId: string }) {
return (
<Organizations
organizationId={organizationId}
onSuccess={() => console.log('SSO configured')}
/>
);
}
// Or use the API
const createdOrganization = await workos.organizations.createOrganization({
name: 'Acme Corp',
domains: ['acme.com'],
});
const ssoConnection = await workos.ssoConnections.create({
organizationId: createdOrganization.id,
type: 'SAML',
});
// Customer logs into your UI and configures their Okta app
// No support ticket needed
Self-service reduces support overhead and accelerates enterprise sales.
Audit Log Events for Compliance
Every authentication event, user addition, and permission change is logged.
// Query audit logs
const auditLogs = await workos.auditLogs.list({
organizationId: 'customer_org_id',
limit: 100,
});
console.log(auditLogs.data.map((log) => ({
timestamp: log.createdAt,
action: log.action, // 'user.login', 'user.created', etc.
actor: log.actor.name,
target: log.targets[0].name,
ipAddress: log.ipAddress,
})));
// Response in your audit tab
// [
// {
// timestamp: '2026-03-18T10:30:00Z',
// action: 'user.login',
// actor: 'john@acme.com',
// ipAddress: '203.0.113.45',
// }
// ]
Export logs to your compliance dashboard or SIEM for investigation.
Directory Sync
Okta and Azure AD sync employee lists to WorkOS. Access via API.
const users = await workos.directoryUsers.list({
directory: 'directory_id',
limit: 50,
});
for (const user of users.data) {
await db.users.upsert({
where: { directoryUserId: user.id },
update: {
email: user.emails[0].value,
firstName: user.firstName,
lastName: user.lastName,
},
create: {
directoryUserId: user.id,
email: user.emails[0].value,
firstName: user.firstName,
lastName: user.lastName,
organisationId: req.organisationId,
},
});
}
Sync on webhook or scheduled job. Keeps your user list in sync with corporate HR systems.
Typescipt SDK Integration
WorkOS's TypeScript SDK is type-safe and async/await friendly.
import { WorkOS } from '@workos-inc/node';
import type { Organization, User } from '@workos-inc/node/types';
const workos = new WorkOS(process.env.WORKOS_API_KEY);
// Fully typed
const organization: Organization = await workos.organizations.retrieveOrganization(
'org_id'
);
const ssoConnections = await workos.ssoConnections.list({
organizationId: organization.id,
});
for (const conn of ssoConnections.data) {
console.log(conn.state); // 'pending' | 'linked' | 'verified'
}
No type confusion. SDK handles API versioning.
Adding WorkOS to Existing Auth System
If you have existing auth (Clerk, Auth.js), layer WorkOS on top for enterprise.
// Existing auth returns user
const { user, session } = await existingAuth.getSession();
// Check if org has SSO enabled
const org = await workos.organizations.retrieveOrganization(
user.organisationId
);
const ssoEnabled = org.domains?.length > 0;
if (ssoEnabled && user.email.endsWith(org.domains[0])) {
// Require SSO
return redirect(`/sso-login?org=${org.id}`);
}
// Otherwise, allow password login
Enterprise customers use SSO. SMBs use password auth. Support both.
Pricing Model and Break-Even Point
WorkOS pricing:
- Free tier: 5 organisations, limited features
- Per-organisation pricing:
$200-500/mo per enterprise org - Custom volume pricing: negotiated at scale
Building SAML + SCIM yourself costs:
- Engineer: 3-6 months salary (
$30k-60k) - Infrastructure: ~
$2k/mo - Maintenance: 0.5 engineer ongoing
Break-even: 2-4 enterprise deals at $500/mo each. For most SaaS, WorkOS is cheaper than building in-house. Only self-host if >500 enterprise customers.
Checklist
- Sign up for WorkOS
- Configure SAML SSO in your test environment
- Implement SSO callback handler
- Set up SCIM endpoint for user provisioning
- Test with Okta and Azure AD
- Enable audit logging in WorkOS Dashboard
- Design enterprise onboarding flow in your UI
- Create audit log viewer for customers
- Document SSO setup for sales
- Load test SSO endpoint
Conclusion
WorkOS eliminates the "build enterprise auth" project. In a day, you have SAML SSO, SCIM provisioning, and audit logging. Your enterprise sales team can close deals without waiting for engineering to build single sign-on. For B2B SaaS, WorkOS is a tactical win and a strategic asset.