Plugins
Plugins are a key part of Better Auth, they let you extend the base functionalities. You can use them to add new authentication methods, features, or customize behaviors.
Better Auth offers comes with many built-in plugins ready to use. Check the plugins section for details. You can also create your own plugins.
Using a Plugin
Plugins can be a server-side plugin, a client-side plugin, or both.
To add a plugin on the server, include it in the plugins
array in your auth configuration. The plugin will initialize with the provided options.
Client plugins are added when creating the client. Most plugin require both server and client plugins to work correctly.
Creating a Plugin
To create a plugin you need to pass an object that satsfies the BetterAuthPlugin
interface.
The only required property is id
, which is a unique identifier for the plugin.
Endpoints
To add endpoints to the server, you can pass endpoints
that requires an object with the key being any string
and teh value being AuthEndpoint
.
To create an Auth Endpoint you'll need to import createAuthEndpoint
from better-auth
.
Better Auth uses a library called Better Call to create endpoints. Better call is a simple web framework made by the same author of Better Auth.
Create Auth endpoints wraps around createEndpoint
from Better Call. Inside the req
object, it'll provide you with an object called context
that give you access better-auth specefic contexts including options
, db
, baseURL
and more.
Context Object
appName
: The name of the application. Defaults to "Better Auth".options
: The options passed to the Better Auth instance.tables
: Core tables defination. It is an object which has the table name as the key and the schema defination as the value.baseURL
: the baseURL of the auth server. This includes the path. For example, if the server is running onhttp://localhost:3000
, the baseURL will behttp://localhost:3000/api/auth
by default unless changed by the user.session
: The session configuration. IncludesupdateAge
andexpiresIn
values.secret
: The secret key used for various purposes. This is defined by the user.authCookie
: The defualt cookie configuration for core auth cookies.logger
: The logger instance used by Better Auth.db
: The kysely instance used by Better Auth to interact with the database.adapter
: This is the same as db but it give youorm
like functions to interact with the database. (we recommend using this overdb
unless you need raw sql queries or for peroframnce reasons)intenralAdapter
: this are intenral db calls that are used by Better Auth. You can use this calls for example to create session instead of usingadapter
directly.intenralAdapter.createSession(userId)
createAuthCookie
: This is a helper function that let's you get a cookiename
andoptions
for either toset
orget
cookies. It implements things like__secure
prefix and__host
prefix for cookies based on
For other properties, you can check the Better Call documentation and the source code .
Rules for Endpoints
- Makes sure you use kebab-case for the endpoint path.
- Make sure to only use
POST
orGET
methods for the endpoints. - Any function that modifies a data should be a
POST
method. - Any function that fetches data should be a
GET
method. - Make sure to use the
createAuthEndpoint
function to create the endpoint. - Make sure your paths are unique to avoid conflicts with other plugins.
Schema
You can define a database schema for your plugin by passing a schema
object. The schema object should have the table name as the key and the schema definition as the value.
Fields
By default better-auth will create an id
field for each table. You can add additional fields to the table by adding them to the fields
object.
The key is the column name and the value is the column definition. The column definition can have the following properties:
type
: The type of the filed. It can be string
, number
, boolean
, date
.
required
: if the field should be required on a new record. (default: false
)
returned
: if the field should be returned when fetching records. (default: true
)
unique
: if the field should be unique. (default: false
)
reference
: if the field is a reference to another table. (default: null
) It takes an object with the following properties:
model
: The table name to reference.field
: The field name to reference.onDelete
: The action to take when the referenced record is deleted. (default:null
)
Other Schema Properties
disableMigration
: if the table should not be migrated. (default: false
)
if you add additional fields to a user
or session
table, the types will be inferred automatically.
Don't store sensitive information in user
or session
table. Crate a new table if you need to store sensitive information.
Middleware
You can add middleware to the server by passing a middleware
array. The middleware array should contain an array of middleware objects with a path
and middleware
property.
The path can be a string or a path matcher. It uses the same path matcher as better-call
.
If you throw an APIError
from the middleware or returned a Response
object, the request will be stopped and the response will be sent to the client.
On Request & On Response
Additional to middlewares you can also hook into right before a request is made and right after a response is returned. This is mostly useful if you wnat to do something that affects all requests or responses.
On Request
The onRequest
function is called right before the request is made. It takes two parameters: the request
and the context
object.
Here’s how it works:
- Continue as Normal: If you don't return anything, the request will proceed as usual.
- Interrupt the Request: To stop the request and send a response, return an object with a
response
property that contains aResponse
object. - Modify the Request: You can also return a modified
request
object to change the request before it's sent.
On Response
The onResponse
function is executed immediately after a response is returned. It takes two parameters: the response
and the context
object.
Here’s how to use it:
- Modify the Response: You can return a modified response object to change the response before it is sent to the client.
- Continue Normally: If you don’t return anything, the response will be sent as is.
Hooks
Hooks are similar to middlewares. But they run even when the endpoint is called directly on the server.
When to use Middelware, Hooks, On Request, On Response
- Middlewares: You should use middlewares when you want to use a route matcher to target a group of routes. And you want to run the middleware only when the routes are called through a request.
- Hooks: You should use hooks when you want to target a specific route or request. And you want to run the hook even if the endpoint is called directly.
- On Request & On Response: You should use on request and on response when you want to do something that affects all requests or responses.
Rate Limit
You can define custom rate limit rules for your plugin by passing a rateLimit
array. The rate limit array should contain an array of rate limit objects.
Client
If your endpoints needs to be called from the client, you'll need to also create a client plugin. Better Auth clients can infer the endpoints from the server plugins. You can also add additional client side logic.
Endpoint Inference
Endpoints are inferred from the server plugin by adding a $InferServerPlugin
key to the client plugin.
The client infers the path
as an object and converts kebab-case to camelCase. For example, /my-plugin/hello-world
becomes myPlugin.helloWorld
.
getActions
If you need to add additional methods or what not to the client you can use the getActions
function. This function is called with the fetch
function from the client.
Better Auth uses Better fetch to make requests. Better fetch is a simple fetch wrapper made by the same author of Better Auth.
As a general guideline, ensure that each function accepts only one argument, with an optional second argument for fetchOptions to allow users to pass additional options to the fetch call. The function should return an object containing data and error keys.
If your use case involves actions beyond API calls, feel free to deviate from this rule.
getAtoms
This is only useful if you want to provide hooks
like useSession
.
Get atoms is called with the fetch
function from better fetch and it should return an object with the atoms. This atoms should be created using nanostore. The atoms will be resolved by each framework useStore
hook provided by nanostore.
See built in plugins for examples of how to use atoms properly.
pathMethods
by default, infered paths use GET
method if they don't require a body and POST
if they do. You can override this by passing a pathMethods
object. The key should be the path and the value should be the method ("POST" | "GET").
fetchPlugins
If you need to use better fetch plugins you can pass them to the fetchPlugins
array. You can read more about better fetch plugins in the better fetch documentation.
atomListners
This is only useful if you want to provide hooks
like useSession
and you want to listen to the atoms and re-evalue the atoms when the atom changes.
You can see how this is used in the built in plugins.