Authentication · modules/iam

Production-ready adapter

BetterAuth,
behind a port.

Auth is the part a blank repo ships insecure. UseDeploy wires BetterAuth into the IAM bounded context behind a typed IAuthProvider port — with the OWASP-recommended argon2id hasher, first-class second factors, and cookie sessions from day one.

One adapter, every method

createBetterAuth wires the Prisma session adapter, the argon2id hasher backed by Bun’s native password API, and the plugins for magic links, two-factor and passkeys. Google OAuth switches on only when its client id/secret are present.

better-auth.adapter.ts
 1  return betterAuth({
 2    database: prismaAdapter(prisma, { provider: 'postgresql' }),
 3    emailAndPassword: { enabled: true, password: argon2Hasher },
 4    socialProviders: cfg.google ? { google: cfg.google } : undefined,
 5    plugins: [
 6      magicLink({ sendMagicLink }),
 7      twoFactor({ /* TOTP */ }),
 8      passkey({ /* WebAuthn */ }),
 9    ],
10  });

What you get on day one

argon2id password hashing

Bun ships argon2id in core — no npm dependency. It is the OWASP-recommended default for new applications.

Magic links

Passwordless sign-in via a delivery hook that forwards to the configured email provider (or logs the link in dev).

TOTP two-factor

The two-factor plugin enrolls authenticator apps and gates sign-in with a twoFactorRedirect step.

Passkeys (WebAuthn)

The passkey plugin registers platform authenticators against your RP id / origin.

Google OAuth

Social sign-in switches on when GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET are set — the avatar field is mapped to the Prisma schema so social create never fails.

Cookie sessions

Sessions are cookie-based end to end. The client sends credentials with withCredentials — no bearer tokens in localStorage.

Configuration reference

Environment variables

  • BETTER_AUTH_SECRETrequired

    min 32 chars

  • BETTER_AUTH_URLrequired

    the server’s own URL

  • CORS_ORIGINSrequired

    trusted browser origins

  • GOOGLE_CLIENT_IDoptional

    enables Google OAuth

  • GOOGLE_CLIENT_SECREToptional

Where it lives

  • apps/server/src/modules/iam/infrastructure/auth/better-auth.adapter.ts
  • apps/server/src/modules/iam/application/ports/auth-provider.ts

Don’t let your agent write auth from scratch.

Start with 2FA, passkeys, magic links and OAuth already wired behind a typed port — the part a blank repo ships broken.