Skip to main content
A plugin is a plain object with an id, an optional init function and optional hooks. @glinr/theauth-email, the discovery plugin and the telemetry plugin are built this way. You pass plugins to createTheAuth({ plugins: [...] }).

A complete plugin

ping-plugin.ts

The context passed to init

init may return { context }; those values are merged into theauth.plugins.getContext().

Endpoints

An endpoint has a method, a path relative to the mount point, a handler(request, ctx) that takes a Web Request and returns a Response, and optional metadata:
  • rateLimit: { window, max }: window is in seconds. Counted per client IP, in memory, per process. Over the limit the router returns 429.
  • requireAuth: when true, the router calls getUser first and returns 401 if there is no session.
  • description: used for documentation.
Paths support :param segments. The router copies captured values into the request URL as _param_<name> query parameters, as shown above. The handler ctx also gives you db, getUser(request) and getSession(token). The JSON, body-parsing and cookie helpers that built-in plugins use are internal, so write small equivalents in your own plugin (the json function above is one).

Lifecycle hooks

Serving plugin endpoints

theauth.plugins.handleRequest(request, basePath?) returns a Response, or null when no endpoint matches, so you can fall through to the rest of your app. theauth.plugins.getEndpoints() lists every registered endpoint, which is what the framework adapters use to mount routes. Strip your mount prefix by passing it as basePath.

Notes

  • schema on a plugin is for Drizzle type safety only. Tables are created by addMigration.
  • AuthPlugin is a deprecated alias of TheAuthPlugin.
  • Plugin rate limits are per process. Behind several instances, enforce limits at your gateway as well.
Last modified on October 8, 2026