Identity & auth
OIDC, SAML, OAuth2, passkeys, magic link, password — vendor-neutral identity surface across Auth0, Clerk, WorkOS, Okta, Cognito, custom.
Vadyl's identity plane is a vendor-neutral abstraction over the major identity providers. You declare what you want — an OIDC connection, a SAML flow, a passkey challenge, an OAuth2 federation — and bind to whichever provider you're using. Application code never sees the vendor.
Provider registry
IIdentityProviderFactoryRegistry resolves identity provider implementations from canonical type names. Built-in: Auth0, Clerk, WorkOS, Okta, Cognito, Microsoft Entra, Google Workspace, Apple, custom OIDC, custom SAML.
bindings: {
identity: {
type: "auth0",
domain: process.env.AUTH0_DOMAIN,
clientId: process.env.AUTH0_CLIENT_ID,
clientSecret: secret.ref("AUTH0_CLIENT_SECRET"),
},
},Identity entities
Vadyl persists eight identity entities under the canonical model:IdentitySubject (the canonical user / agent / service), IdentityCredential, IdentityMembership, AuthSession, AuthChallenge, AuthRevocation, IdentityConnectorBinding, RefreshTokenFamily.
Sessions and refresh tokens
Sessions are first-class entities — revocable, queryable, durable. Refresh-token families implement secure rotation: each refresh produces a new family member and invalidates the previous one. Token-replay attacks are detected and the entire family is revoked.
MFA challenges
Step-up auth is a typed challenge: TOTP, WebAuthn, SMS code, email code, push notification. The capability resolver (IIdentityChallengeCapabilityResolver) is consulted by both Discovery and ChallengeStart so the available challenge types match what the user has actually enrolled.
// Step up to a higher auth strength before sensitive operation
await ctx.identity.challenge.start({
subjectId: ctx.actor.userId,
requireStrength: "mfa-totp",
});JIT provisioning
First-time SSO sign-ins create a canonical IdentitySubjectkeyed by the provider's subject identifier. Subsequent sign-ins resolve to the same subject. Multiple credentials (Google + Auth0 + password) can attach to the same subject through explicit account linking.
Federation flows
OAuth2 / OIDC flows are first-class:
// Start an OIDC flow
const challenge = await ctx.identity.federation.start({
provider: "google",
redirectUri: "https://app.example.com/auth/callback",
});
// Complete it on the callback handler
const session = await ctx.identity.federation.complete({
provider: "google",
code: req.query.code,
state: req.query.state,
});Auth strength
Every authentication carries a typed AuthStrength:weak, basic, mfa-sms, mfa-totp, mfa-webauthn, passkey. Access models can require a minimum strength per facet via ctx.authStrengthAtLeast(level).
Switch providers
Migrate from Auth0 to Clerk: change the binding, run the migration script that maps existing subjects, deploy. Application code doesn't change. Existing sessions remain valid until they expire (or are explicitly revoked).