Authio docs

Concepts

Where does your roles source-of-truth live?

Four ways to wire roles into Authio — Authio-managed, IdP-managed, customer-managed via Actions, or a hybrid. Choose by where the authoritative role-assignment lives.

Most teams don’t adopt an identity provider on day-1. They adopt one when they have an existing application, an existing user table, and very often an existing roles table. Authio supports four integration patterns at GA so you can wire your real-world role catalogue in without rewriting your data model.

Not sure which one fits? Jump to the Picking the right pattern section.

Pattern 1 · Authio is the source of truth (default)

When to choose. Customers without an existing roles table, or customers whose existing roles table is small (≤ a few hundred rows) and movable. Most net-new builds.

Data flow.

  1. Customer creates roles + permissions in /roles and /permissions (dashboard) or via the Management API (POST /v1/session/roles, POST /v1/session/permissions).
  2. Customer assigns roles to memberships in the dashboard or via POST /v1/session/organizations/:id/members/:userId/roles.
  3. On sign-in, the access-token JWT carries “roles”: “editor” and “permissions”: [“docs:read”, “docs:write”].
  4. Customer’s app reads the claims directly from the JWT via the @authio/* SDKs.

Operational guarantees. Authio owns the role lifecycle. Role changes trigger organization_membership.updated audit events. The reserved-claim guard prevents downstream Actions from forging roles.

Authio surfaces. P0-D Roles+Permissions catalog (CRUD UI + API), the per-membership role dropdown in /orgs/[id]?tab=members, the Management API routes.

Maps to WorkOS. Identical to WorkOS’s default Roles & Permissions surface.

Pattern 2 · IdP is the source of truth

When to choose. Customers whose Workday / Okta / Entra ID / Google Workspace / Rippling / JumpCloud directory is already the authoritative source for who-is-in-what-team. Most enterprise customers.

Data flow (SCIM).

  1. Customer’s IT admin maps IdP groups to Authio roles in the Admin Portal widget (or via the dashboard for one-off setups).
  2. SCIM PUT /v2/Users/:id with a changed groups attribute triggers a directory-provisioning sync.
  3. The sync recomputes the user’s membership.role(s) per the mapping rules. Explicit mappings win over default mappings; default mappings do not override manual assignment.
  4. On next sign-in, the JWT carries the recomputed roles.

Data flow (SSO group claims).

  1. Customer’s IT admin maps SSO IdP group claims to Authio roles in the Admin Portal widget at SSO connection setup time.
  2. On every sign-in, the SAML/OIDC response carries the user’s group claims; Authio’s SSO callback handler applies the mapping and writes to memberships.role (or membership_roles).
  3. JWT carries the result.

Operational guarantees. Directory-provisioned roles override SSO-claim-provisioned roles; both override manual assignments. Re-running directory sync re-applies the IdP-sourced roles. Audit events fire on every role change with the source recorded (source: scim|sso|manual).

Authio surfaces. P0-A widget v1 (round 1) ships the SCIM mapping UI; P1-G adds the SSO-group-claim mapping UI for SAML/OIDC connections.

Maps to WorkOS. Identical to WorkOS’s IdP-role-assignment flows; we match their priority order (directory > SSO > manual).

Pattern 3 · Customer is the source of truth (via Actions hydration)

Shipped. The Actions runtime, the customer-hosted HTTPS webhook contract, the HMAC envelope, and the pre_token_mint override seam are live. End-to-end walkthrough with the customer’s Node + Postgres handler is on the Pattern 3 · Actions roles override page; concept overview is on the Actions overview.

When to choose. Customers with a large pre-existing roles table (thousands of rows), customers whose roles change frequently in their own DB (so daily SCIM sync is too slow), customers with custom role-derivation logic (e.g. roles computed from a combination of group membership + feature-flag + billing tier), customers who do not want to move the system-of-record out of their own database.

Data flow.

  1. Customer hosts an HTTPS endpoint that receives a payload like {user_id, organization_id, membership_id, email, identity_provider} from Authio on every sign-in.
  2. Customer’s endpoint queries their internal roles table (or their internal API or LDAP or any other roles backend), builds a “roles”: [“editor”] + “permissions”: [“docs:read”] response, and returns it inside a signed verdict {verdict: "Allow", roles: [...], permissions: [...]}.
  3. Authio applies the reserved-claim guard, then mints the JWT with the customer-supplied roles + permissions.

Operational guarantees. Sign-in is gated on the customer’s endpoint being reachable in ≤ 2 s (the Q1 lock timeout). On timeout, the project’s fail_mode decides whether to mint the JWT with the membership’s stored roles (fail-open) or to deny the sign-in (fail-closed). Roles cannot be assigned in the Authio dashboard in this mode — the dashboard becomes read-only for those memberships, with a banner pointing at the configured Action URL.

Authio surfaces. P0-B Actions runtime + a first-class “Hydrate roles from your customer DB” template in the dashboard’s action library. The template’s typed payload doc explicitly maps the {user_id, organization_id, membership_id, email} inputs to the expected {roles: [...], permissions: [...]} output.

Maps to WorkOS. No direct equivalent. WorkOS Actions can mutate the JWT via custom claims (so a customer could technically inject roles via their actions endpoint), but the WorkOS authorization model treats the WorkOS-side roles and permissions as the system of record — there is no published “return roles from your endpoint to override the membership’s roles” contract. Auth0 ships this same pattern via Actions (post-login action can mutate event.authorization.roles); we match Auth0’s capability while keeping the WorkOS-compatible JWT shape.

Pattern 4 · Hybrid (Authio defaults + customer overrides)

When to choose. Customers who want Authio to hold the safe defaults (e.g. every new member gets the viewer role) but their app’s domain logic computes elevated roles dynamically (e.g. “anyone who has approved an invoice in the last 30 days gets the approver role”). Or customers in the middle of migrating from Pattern 3 to Pattern 1.

Data flow.

  1. Authio dashboard manages a default_role and an available_roles allowlist per organization.
  2. Customer’s app calls POST /v1/session/organizations/:id/members/:userId/roles (server-to-server with a workspace API key) on whatever schedule / trigger their domain logic dictates — once a day, on every business-event, on demand.
  3. Authio stores the customer’s writes alongside the Authio defaults. JWT minting prefers the most-recent customer write, falling back to the Authio default if no customer write exists.

Operational guarantees. Customer-written role assignments carry source: “customer_api” in the audit log; Authio defaults carry source: “authio_default”. The same priority order from Pattern 2 applies (directory > SSO > customer_api > authio_default).

Authio surfaces. The existing Management API + the new /v1/session/organizations/:id/members/:userId/roles POST/DELETE endpoints from P0-D. No new dashboard UI needed at GA — exposed via API + docs only.

Maps to WorkOS. Closest match is WorkOS’s “temporary override” semantics in the IdP-priority section. Our pattern is more flexible because it doesn’t require an IdP to be wired in the first place.

Picking the right pattern

Customer profileRecommended patternImplementation effort
Net-new B2B SaaS, no existing roles table1 · Authio-as-sourceZero — use the dashboard
Mid-market with Okta/Entra/Workday + SCIM2 · IdP-as-source≤1 hour — IT admin maps groups in the Admin Portal widget
Established product with a roles table they won’t move3 · Customer-as-source via Actions≤1 day — host the HTTPS endpoint with HMAC verification + a SQL query
Migrating from a different IDP (Auth0 / Clerk)Start with 1, fall back to 3 during the transitiondepends on the move
Compliance-heavy customer with derived / computed roles3 · Customer-as-source via Actions≤1 day; same as above
Customer wants Authio defaults + dynamic overrides4 · Hybrid≤1 day — write to the memberships API on the customer’s schedule