Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Technology handbook

BetterAuth

Framework-agnostic authentication with sessions, plugins, organizations and two-factor support.

Topics
33
Sections
5

Hooks

authClient.useSession

Read the session reactively in a component, with isPending and error alongside the data.

  • It returns data, isPending and error together, so all three states are handled at once.
  • The component re-renders when the session changes rather than reading a stale snapshot.
  • Rendering before isPending clears is what makes a signed-in user flash as signed out.

useSession versus getSession

The hook re-renders on change; the promise is for everywhere a hook may not run.

  • The hook subscribes; the promise resolves once and never updates the caller.
  • Server code and event handlers cannot call a hook, which is what the promise is for.
  • Calling the promise on every render refetches the session instead of reusing it.

Server hooks: before

Run logic before a matched endpoint with createAuthMiddleware, and reject or rewrite the request.

  • createAuthMiddleware runs ahead of the matched endpoint and can reject the request outright.
  • Rewriting the context here changes what the endpoint receives, not just what it logs.
  • Throwing inside it is how a sign-up is blocked before any row is written.

Server hooks: after

Act once an endpoint has succeeded - send a welcome email, record an analytics event.

  • It runs only once the endpoint has succeeded, so side effects never fire on a failure.
  • Welcome mail and analytics belong here rather than inside the endpoint itself.
  • Work done here still delays the response unless it is handed to a queue.

Hook matchers

Match the paths a hook applies to, so it does not run on every auth request.

  • A matcher limits a hook to the paths it is about instead of every auth request.
  • Without one, a sign-in hook also runs on session reads and token refreshes.
  • Matching on path keeps the cost of a hook proportional to how often it is needed.

getSessionFromCtx

Read the caller's session inside a hook without a second round trip.

  • It reads the session already resolved for this request rather than fetching it again.
  • Using it inside a hook avoids a second database round trip per call.
  • It returns null for unauthenticated endpoints, which the hook must handle.

Database hooks

Intercept create and update on user, session and account records, before or after they are written.

  • They intercept create and update on user, session and account rows.
  • A before hook can refuse or rewrite the write; an after hook only observes it.
  • They fire for every path that touches the record, including provider callbacks.

Plugin hooks

Ship a plugin that contributes its own before and after handlers alongside its endpoints.

  • A plugin ships its own before and after handlers beside its endpoints.
  • Handler order follows plugin registration order, which makes it deterministic.
  • One plugin's hook can see the effect of another's, so ordering is a real dependency.

Organization client hooks

Read the active organization and membership lists through the plugin's own hooks.

  • The active organization and membership list are read through the plugin's own hooks.
  • They re-render on a switch, so the interface never shows the previous tenant's data.
  • They resolve only once the plugin is enabled on both server and client.

Core setup

Server instance

Configure the auth server with a database adapter and a base URL.

  • The server owns its tables through an adapter and a declared base URL.
  • The base URL is what callback and redirect targets are built from.
  • Enabled options here decide the schema, so the instance and migrations move together.

Database schema

Generate and apply the tables the enabled features require.

  • The generator emits the tables the currently enabled features require.
  • Applying the migration before enabling the feature is what keeps sign-in working.
  • A schema behind the configuration fails at request time, not at deploy.

Route handler

Mount the handler so client calls reach the server API.

  • Mounting the handler is what makes the client's typed calls reach the server API.
  • The mount path must match the client's base path or every call 404s.
  • One handler serves every enabled plugin's endpoints, not one route per feature.

Client instance

Create a typed client that matches the server's enabled plugins.

  • The client is typed from the server's enabled plugins, so missing methods are a compile error.
  • Its base URL must point at the mounted handler, not the application root.
  • Adding a plugin server-side without the client leaves the methods untyped.

Environment configuration

Set the secret and provider credentials per environment.

  • The secret signs sessions, so changing it signs everyone out at once.
  • Provider credentials are per environment because each has its own callback URL.
  • Configuration read at module load will not pick up a value set later at runtime.

Framework adapters

Integrate with Next.js, SvelteKit, Hono or a plain Node server.

  • An adapter translates the framework's request and response into what the handler expects.
  • Cookie writing differs per framework, which is most of what the adapter carries.
  • Running on the edge restricts the adapter to APIs that runtime actually provides.

Authentication methods

Email and password

Enable credential sign-up with verification and reset flows.

  • Verification and reset flows come with the method rather than being written by hand.
  • Password rules are configured once and enforced on sign-up and reset alike.
  • Enabling it adds credential columns the migration must apply first.

Social providers

Add OAuth providers and map returned profiles onto users.

  • The provider's returned profile is mapped onto the user row on first sign-in.
  • Each provider needs its redirect URI registered before the callback will return.
  • A second provider on the same email links or duplicates depending on configuration.

Passkeys

Register and authenticate with WebAuthn credentials.

  • WebAuthn binds the credential to the origin, so it cannot be replayed elsewhere.
  • The private key never leaves the authenticator, which removes the password to steal.
  • Registration and authentication are separate ceremonies with separate endpoints.

Two-factor authentication

Add TOTP or OTP as a second step with recovery codes.

  • TOTP adds a second step whose codes are time-bound rather than reusable.
  • Recovery codes are the fallback, and they must be single-use and stored hashed.
  • Enabling it adds tables, so the migration has to land before the feature does.

Anonymous and guest sessions

Let a visitor act before signing up and upgrade the account later.

  • A visitor can act before signing up, and the work is kept against a real session.
  • Upgrading links the existing session to the new account instead of starting over.
  • A guest session still counts as a session, so authorization must check more than presence.

Sessions & accounts

Session management

Read, refresh and revoke sessions server-side.

  • Sessions are rows, so revoking one takes effect on the very next request.
  • Listing a user's sessions is what makes a sign-out-everywhere control possible.
  • Refreshing extends the record rather than issuing an unrelated new one.

Account linking

Attach multiple providers to one user deliberately.

  • Linking keeps one user row when the same person arrives through a second provider.
  • Trusting an unverified provider email is how one account gets taken over by another.
  • Unlinking must refuse to remove the only remaining sign-in method.

Email verification

Block privileged actions until an address is confirmed.

  • Privileged actions stay blocked until the address is confirmed.
  • The token is single use, so a resend must invalidate the previous one.
  • Verification state belongs on the user row, not inferred from the provider.

Password reset

Issue single-use reset tokens that expire and cannot be replayed.

  • The reset token is single use and expires whether or not it is redeemed.
  • Resetting must end existing sessions, or a thief keeps the one they already have.
  • Responding identically for unknown addresses is what stops the form enumerating users.

Session hooks

Run logic before or after a sign-in or sign-out.

  • They run either side of a sign-in or sign-out rather than on every read.
  • A before hook can refuse the sign-in; an after hook can only react to it.
  • Audit records written here capture the event with the session still in context.

Plugins & multi-tenancy

Organization plugin

Model teams, memberships and invitations.

  • Teams, memberships and invitations arrive as tables plus typed client methods.
  • A user's active organization is what every scoped query is filtered by.
  • Enabling it changes the schema, so it is a migration before it is a feature.

Roles and permissions

Define access rules and check them on the server.

  • Rules are declared once and checked on the server, never only in the interface.
  • A role is per membership, so the same user can be an admin of one team and not another.
  • A client-side check is a convenience; the server check is the actual boundary.

Admin plugin

Impersonate, ban or manage users with an audited path.

  • Impersonation, bans and user management arrive on an audited path rather than ad hoc SQL.
  • Every privileged action is attributable, which is what makes it reviewable afterwards.
  • The plugin's own endpoints need protecting, or it becomes the way in.

Rate limiting

Throttle sign-in attempts to blunt credential stuffing.

  • Throttling sign-in attempts is what makes credential stuffing expensive.
  • Limiting by address alone punishes shared networks and misses distributed attempts.
  • The counter must be shared across instances or each one enforces its own limit.

Custom plugins

Extend the schema, server API and client together.

  • A plugin extends schema, server API and client types as one unit.
  • Shipping the three together is what keeps the client's methods honest.
  • Its migration is still a migration, and it must land before the plugin is enabled.

Migration planning

Roll out a plugin's schema change before enabling it in production.

  • The schema change is deployed and applied before the feature is turned on.
  • A plugin enabled ahead of its columns fails at sign-in, not at deploy.
  • Rolling back the code without rolling back the schema is the safer order.

Sources

  • BetterAuth official documentation

Ask follow-up questions on any topic in your dashboard.

Start learning