Clerk
Use Clerk for MainSDK auth - application setup, development and production instances, main.yaml, secret keys, local testing and swapping.
Clerk is a hosted user management service and one of the drivers behind auth. Clerk holds your users, their sign-in methods and their organisations; auth gives your routes one way to read the session and require a role, whatever provider sits underneath. Pick Clerk when you want a hosted user directory with ready-made sign-in screens and organisations, and you don't want to run identity yourself. The auth spec names Clerk as its default and proposes Clerk and Better Auth as the two drivers that make auth stable in 0.3.
Interfaces it serves
Pick Clerk in main.yaml for any of these. Your calls stay the same, and you can swap later.
authBuilding for 0.3Driver clerk Clerk
auth:
driver: clerkSwap to another provider
Before you start
You need a Clerk account.
- Create an application in the Clerk Dashboard. Clerk creates a development instance for it straight away.
- Choose sign-in methods for the application. Turn on passkeys; MainSDK makes them the default method. Add the social providers you want, such as GitHub.
- Copy the API keys. Each instance has a publishable key, used in the browser, and a secret key, used only on your server.
- Create the production instance when you are ready to go live. It has its own keys and needs your own domain, which Clerk asks you to verify with DNS records.
- For organisations: turn on Clerk's organisations feature if your customers sign in as teams.
Store the keys in your secrets manager, never in code or a committed env file.
Configure
auth:
driver: clerk
methods: [passkeys, whatsapp, sso]
whatsapp: { driver: whatsapp-cloud }
sso: { protocols: [saml, oidc], scim: true }
session: { ttl: 15m, refresh: 7d, bind: dbsc }
# [to be decided] key names; suggested secrets: CLERK_SECRET_KEY, CLERK_PUBLISHABLE_KEYThe auth spec does not define the keys a driver reads its credentials from yet. When it does, they take secret: references. Use development-instance keys in development and stage, and production-instance keys in production.
Use it
import { auth, db } from "mainsdk";
export async function GET(req: Request) {
const session = await auth.require(req); // 401 with MAIN-AUTH-0001 if not signed in
return Response.json(await db.orders.for(session.user).list({ limit: 20 }));
}Turn on SSO for one of your customer organisations:
import { auth } from "mainsdk";
export async function enablePinecartSso() {
await auth.sso.enable("pinecart", {
protocol: "saml",
domains: ["pinecart.com"],
metadata: new URL("https://idp.pinecart.com/saml/metadata"),
});
}Local development and testing
- No Clerk account: the
localauth driver runs in development with no keys. - Clerk development instance: use its keys locally to try the real sign-in screens. Development instances are meant for testing and have looser limits and settings than production.
- Tests:
createTestApp()from@mainsdk/testingputsauthon its in-memory fake, andchaos.on("auth", { outage: true })simulates Clerk being unreachable;auth.require()fails closed.
import { it } from "node:test";
import assert from "node:assert/strict";
import { createTestApp } from "@mainsdk/testing";
import { GET } from "./route";
it("auth.AC1 refuses a request with no session", async () => {
createTestApp({ main: "./main.yaml" });
assert.equal((await GET(new Request("http://localhost/api/orders"))).status, 401);
});What MainSDK adds on top
- Short-lived, HttpOnly, Secure, SameSite sessions with rotating refresh tokens, bound to the device where the browser supports it.
- Passkeys by default, with conditional create after a password sign-in and a report of the share of users on passkeys.
- Fails closed when Clerk cannot be reached.
- WhatsApp codes single use, expiring and rate limited per phone and per IP; SAML and SCIM provided in your app where the driver lacks them.
- 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 Clerk instance. MainSDK never becomes the identity provider.
- Clerk and Better Auth are the proposed pair for a stable
authin 0.3 (spec ticket for both drivers and the conformance suite); that choice is still open. - Check where Clerk stores user data against your residency needs. MainSDK's regions (US, EU, India) govern the records in your own
db. auth.raw()returns the Clerk client for featuresauthdoes not wrap.mainsdk checklists every use.
Swap to or from it
auth:
driver: auth0 # was clerkFAQ
Do I have to use Clerk's sign-in screens? auth gives you passkey, WhatsApp and SSO calls you can build your own screens on. Whether the driver also mounts Clerk's prebuilt components is not specified.
Where do I put the publishable key? It is safe in the browser, but keep it in your secrets setup like the secret key so each environment gets the right instance.
Can I keep my existing Clerk users? Yes. The driver runs on your existing instance (byo-identity); nothing moves.
Next
Was this page helpful?