Concepts
One user, many orgs
The single most important difference between Authio and WorkOS: a real B2B identity model that doesn't force duplicate accounts.
WorkOS scopes a user to a single organization. If your customer joins a second org on your platform, they have to use a second email. This is, frankly, terrible UX for any modern B2B product. Authio fixes it.
The model
At the schema level, the relationship looks like this:
Project
└── Users (project-scoped; canonical identity = (project, email))
└── Organizations (B2B accounts in your customer's product)
└── Memberships (the join: one User ↔ many Organizations)A User has ID user_… and is keyed by (project_id, email). They never live inside an organization. Instead, a Membership row links them to each organization with an independent role and status:
memberships
id | mem_zXY…
project_id | proj_2eh…
user_id | user_alice
organization_id | org_acme
role | admin
status | active
joined_at | 2026-05-13T13:42:53Z
memberships
id | mem_aBC…
project_id | proj_2eh…
user_id | user_alice ← same user
organization_id | org_globex ← different org
role | member
status | activeSessions are user-scoped, not org-scoped
After authentication (passkey, magic link, OAuth, SAML, anything), Authio mints a JWT with sub = user_id and an act_org claim that names the active organization. The same user can switch act_org in-session without re-authenticating, with a single API call:
POST /v1/sessions/switch-org
{
"organization_id": "org_globex"
}
200 OK
{
"access_token": "<new JWT with same sub, new act_org>",
"active_organization": { "id": "org_globex", "name": "Globex Inc" },
"memberships": [ ... all the user's orgs ... ]
}Every membership change is captured in an audit event (session.org_switched) so customers’ security teams can see the pivot.
Privacy boundary
sk_live_ key) can list all of a user’s memberships.SDK ergonomics
Drop-in components in @authio/react render the entire flow:
import {
useUser,
useOrganizations,
useActiveOrganization,
useSwitchOrganization,
OrganizationSwitcher,
} from "@authio/react";
const { user } = useUser();
const { organizations } = useOrganizations(); // every org user belongs to
const { organization, role } = useActiveOrganization();
const switchOrg = useSwitchOrganization();
<OrganizationSwitcher createOrganizationUrl="/orgs/new" />Where this matters
- Vendors who sell to multiple teams in the same company.Stop emailing the same dev "use a different account when logging into the staging org."
- Marketplaces and platforms. A consultant working across many client tenants is a single human being — their auth should reflect that.
- Any product where users naturally span boundaries.Slack, Linear, GitHub, Figma, Notion all model this. Now your product can too without writing it from scratch.