Better Auth Custom Credentials Plugin
This package provides a plugin for the `better-auth` library, enabling highly customizable credentials-based authentication. It allows developers to integrate `better-auth` with virtually any backend authentication system, such as Rails, Django, custom APIs, or LDAP, while leveraging `better-auth`'s existing session management infrastructure. Currently at version 0.1.8, the library is in active development, meaning minor versions may introduce breaking changes to its API. Key differentiators include the ability to define flexible input schemas using Zod for robust validation, store arbitrary custom data (like JWTs or permissions) directly within `better-auth` sessions, configure auto sign-up features, and set custom session expiry per authentication method. It offers a comprehensive solution for adapting diverse authentication logic to the `better-auth` ecosystem.
Common errors
-
TypeError: credentialsPlugin is not a function
cause Attempting to import `credentialsPlugin` using CommonJS `require()` syntax or incorrect named import from an ESM-only package.fixEnsure you are using ECMAScript Modules (ESM) import syntax: `import { credentialsPlugin } from 'better-auth-custom-credentials';`. -
ZodError: Invalid input
cause The data sent from the client-side `authClient.signIn.credentials()` call does not conform to the `inputSchema` defined with Zod on the server-side `credentialsPlugin`.fixReview your server-side `inputSchema` and ensure the client-side `signIn.credentials` method is sending an object with the exact keys and types expected by the schema. -
Error: Cannot find module 'better-auth' or 'zod'
cause The `better-auth` or `zod` peer dependencies are not installed in your project.fixInstall the required peer dependencies: `npm install better-auth zod` or `pnpm add better-auth zod`. -
Type 'Partial<User>' is not assignable to type 'User'. Property 'id' is missing in type 'Partial<User>' but required in type 'User'.
cause The `user` object returned by the `verify` function does not contain all required properties as defined by your application's `User` type for Better Auth.fixEnsure the `user` object returned from `verify` includes all mandatory fields (e.g., `id`, `email`, `name`) that your `better-auth` configuration expects for a `User`.
Warnings
- breaking As a pre-1.0 package (version 0.1.8), the API is subject to frequent and significant breaking changes between minor versions. Always consult the latest README and changelog before upgrading.
- gotcha The `verify` function within `credentialsPlugin` must strictly return an object conforming to `{ ok: boolean; reason?: string; user?: User; meta?: Record<string, any> }` on success or failure. An incorrect return type can lead to authentication failures or incomplete session data.
- gotcha When using `createAuthClient` on the client-side, it is crucial to include `credentials: 'include'` in your `fetch` configuration. Omitting this will prevent cookies (like session tokens) from being sent with requests, leading to unauthenticated requests or session management issues.
- gotcha Forgetting to define a robust `inputSchema` using Zod within the `credentialsPlugin` configuration can lead to insecure or unexpected authentication behavior, as input validation will be absent or incomplete.
Install
-
npm install better-auth-custom-credentials -
yarn add better-auth-custom-credentials -
pnpm add better-auth-custom-credentials
Imports
- credentialsPlugin
const credentialsPlugin = require('better-auth-custom-credentials');import { credentialsPlugin } from 'better-auth-custom-credentials'; - extendAuthClientWithCredentials
const extendAuthClientWithCredentials = require('better-auth-custom-credentials').extendAuthClientWithCredentials;import { extendAuthClientWithCredentials } from 'better-auth-custom-credentials'; - z
import { z } from 'zod';
Quickstart
import { createAuthClient } from 'better-auth/react';
import { extendAuthClientWithCredentials } from 'better-auth-custom-credentials';
// Create a basic Better Auth client, ensuring credentials are included for session management.
// This client will interact with your server-side Better Auth setup.
export const authClient = extendAuthClientWithCredentials(
createAuthClient({
fetch: (url, init) => {
return fetch(url, {
...init,
credentials: 'include', // Important: Ensures cookies are sent with requests
cache: 'no-store',
});
},
})
);
async function authenticateAndGetSession() {
console.log('Attempting to sign in with credentials...');
// Sign in using the credentials method. The input object must match the server-side Zod schema.
const result = await authClient.signIn.credentials({
email: 'user@example.com',
otp: '123456',
rememberMe: true,
});
if (result.ok) {
console.log('Sign in successful!');
// Retrieve the session data after successful authentication.
const { data: session } = await authClient.getSession();
const jwt = session?.data?.jwt;
const permissions = session?.data?.permissions;
console.log('Session Data:', session);
console.log('JWT:', jwt);
console.log('Permissions:', permissions);
} else {
console.error('Sign in failed:', result.reason);
}
}
// Example call (in a real app, this would be triggered by a form submission or similar event)
// authenticateAndGetSession();