MainSDK
Search⌘K
Integrations

Auth0

Use Auth0 for MainSDK auth - tenant and application setup, callback URLs, main.yaml, client secrets, local testing and swapping.

1 interface1 driverWritten guide
Updated 2026-10-28

Auth0 is a hosted identity platform and one of the drivers behind auth. Your users, connections and MFA settings live in an Auth0 tenant; auth gives your routes one way to read the session, require a role and turn on SSO for your customers. Pick Auth0 when your company already runs it, or when you need its range of enterprise and social connections and want to keep users in one tenant across several apps.

Interfaces it serves

Pick Auth0 in main.yaml for any of these. Your calls stay the same, and you can swap later.

Before you start

You need an Auth0 account and a tenant.

  1. Create a tenant for each environment you keep apart, such as development and production. You pick the tenant's region when you create it; choose the one that matches where your user data must live.
  2. Create an application of the regular web application type for your app.
  3. Set the allowed callback URLs to the route that receives Auth0's redirect after sign-in, and the allowed logout URLs to where users land after signing out. The paths MainSDK mounts are not defined yet.
  4. Copy the domain, client ID and client secret from the application's settings.
  5. Turn on connections. Enable the social and enterprise connections you want, and passkeys where your tenant supports them.

Store the client secret in your secrets manager, never in code or a committed env file.

Configure

main.yaml
auth:
  driver: auth0
  methods: [passkeys, sso]
  sso: { protocols: [saml, oidc], scim: true }
  session: { ttl: 15m, refresh: 7d, bind: dbsc }
  # [to be decided] key names; suggested secrets: AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET

The auth spec does not define the keys a driver reads its credentials from yet. When it does, they take secret: references. Point each environment's secrets at its own tenant.

Use it

app/api/admin/users/route.ts
import { auth } from "mainsdk";

export async function DELETE(req: Request) {
  // 401 or 403 with a fix unless an admin signed in recently with a phishing-resistant method
  const session = await auth.require(req, { role: "admin", aal: "aal2", fresh: "5m" });
  return Response.json({ by: session.user });
}

Route a customer's people to their own identity provider by email domain:

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 });   // redirects to the organisation's IdP
}

Local development and testing

  • No Auth0 tenant: the local auth driver runs in development with no keys.
  • A development tenant: register http://localhost on your dev port in the application's allowed callback URLs to try the real flow.
  • Tests: createTestApp() from @mainsdk/testing runs auth on its in-memory fake, and chaos.on("auth", { outage: true }) simulates Auth0 being unreachable; auth.require() fails closed.
app/api/admin/users/route.test.ts
import { it } from "node:test";
import assert from "node:assert/strict";
import { createTestApp } from "@mainsdk/testing";
import { DELETE } from "./route";

it("refuses a request with no session", async () => {
  createTestApp({ main: "./main.yaml" });
  const res = await DELETE(new Request("http://localhost/api/admin/users", { method: "DELETE" }));
  assert.equal(res.status, 401);
});

What MainSDK adds on top

  • Short-lived, HttpOnly, Secure, SameSite sessions with rotating refresh tokens; the implicit OAuth flow is never offered.
  • Passkeys by default, phishing-resistant.
  • Fails closed when Auth0 cannot be reached.
  • OIDC with PKCE and state: a mismatched state or nonce is refused with MAIN-AUTH-0007. Unsigned or replayed SAML assertions are refused with MAIN-AUTH-0008.
  • Every recovery audited, never weaker than sign-in.

See Sign-in and sessions for the full contract.

Limits and notes

  • Users, sessions and MFA stay in your Auth0 tenant (byo-identity).
  • The Auth0 driver and its capability profile have a ticket in the auth spec next to WorkOS; Clerk and Better Auth are the proposed first pair.
  • Auth0's tenant regions do not map one to one onto MainSDK's US, EU and India regions. Check that a region fits your residency needs before you create the tenant.
  • auth.raw() returns the Auth0 client for features auth does not wrap, such as tenant management. mainsdk check lists every use.

Swap to or from it

main.yaml
auth:
  driver: workos   # was auth0

FAQ

Can I keep my existing Auth0 tenant? Yes. The driver runs on it as it is; users stay where they are.

My Auth0 plan has no SCIM. Do I lose it? No. Where a driver lacks SAML or SCIM, MainSDK provides it in your app on top of the driver.

Is Auth0 FGA the same as this driver? No. Auth0 FGA is a managed OpenFGA service for permissions, which belongs to access through the OpenFGA driver.

Next

Open questions

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet