Better-Auth Disposable Email Blocker
The `better-auth-no-disposable-emails` package is a plugin for the `better-auth` authentication library, designed to prevent users from signing up or signing in with temporary or disposable email addresses. It integrates with `better-auth`'s plugin system, intercepting specified authentication endpoints (e.g., `/sign-up/email`) and validating the submitted email against a comprehensive list of known disposable email providers, powered by the `mailchecker` library. The current stable version is 0.2.0, indicating it's relatively new and in active development, though a specific release cadence isn't published. Its key differentiator is its seamless integration with `better-auth`, providing a configurable and extensible solution to enhance user quality and reduce spam registrations by blocking transient email accounts.
Common errors
-
TypeError: noDisposableEmails is not a function or its return value is not a plugin.
cause The `noDisposableEmails` plugin function was added to the `plugins` array without being invoked.fixCall the function: `plugins: [noDisposableEmails()]` or `plugins: [noDisposableEmails({...options})]`. -
Error: Peer dependency 'better-auth@>=1.5.0' not met.
cause The `better-auth` package is not installed or its version is older than required.fixInstall or update better-auth: `npm install better-auth@latest` -
400 BAD_REQUEST - DISPOSABLE_EMAIL_NOT_ALLOWED
cause A user attempted to register or sign in with an email address detected as disposable. This is the expected behavior of the plugin.fixInform the user that temporary email addresses are not accepted. The default `errorMessage` or a custom one will be sent to the client. No code change is necessary if this behavior is desired. -
Disposable email passes through on /sign-in/email
cause The `noDisposableEmails` plugin's `paths` option does not include `/sign-in/email`.fixUpdate the plugin configuration to include the desired paths: `noDisposableEmails({ paths: ["/sign-up/email", "/sign-in/email"] })`.
Warnings
- gotcha The `noDisposableEmails` function must be invoked (e.g., `noDisposableEmails()`) when added to the `plugins` array, even if no options are passed. Forgetting the parentheses will result in the plugin not being correctly registered.
- gotcha The plugin only intercepts the paths explicitly listed in its `paths` option. By default, only `/sign-up/email` is checked. If you need to block disposable emails on sign-in, magic links, or OTP requests, you must specify those paths.
- breaking This package is a plugin for `better-auth`. Its functionality depends entirely on the `better-auth` package being installed and correctly configured. Compatibility is guaranteed only for `better-auth` versions `>=1.5.0` as per peer dependencies.
Install
-
npm install better-auth-no-disposable-emails -
yarn add better-auth-no-disposable-emails -
pnpm add better-auth-no-disposable-emails
Imports
- noDisposableEmails
const noDisposableEmails = require('better-auth-no-disposable-emails').noDisposableEmails;import { noDisposableEmails } from 'better-auth-no-disposable-emails'; - noDisposableEmails (default options)
import { noDisposableEmails } from 'better-auth-no-disposable-emails'; // ... plugins: [noDisposableEmails]import { noDisposableEmails } from 'better-auth-no-disposable-emails'; // ... plugins: [noDisposableEmails()] - noDisposableEmails (with options)
import { noDisposableEmails } from 'better-auth-no-disposable-emails'; // ... plugins: [noDisposableEmails({ errorMessage: '...' })]
Quickstart
import { betterAuth } from "better-auth";
import { noDisposableEmails } from "better-auth-no-disposable-emails";
// Mock database adapter for demonstration purposes
const mockDatabaseAdapter = {
getUserByEmail: async (email: string) => {
if (email === 'test@example.com') return { id: '1', email: 'test@example.com' };
return null;
},
createUser: async (email: string, passwordHash: string) => ({
id: String(Date.now()),
email,
}),
updateUser: async (id: string, updates: any) => ({ id, ...updates }),
// Add other necessary methods for a better-auth database adapter
};
export const auth = betterAuth({
database: mockDatabaseAdapter, // Replace with your actual database adapter
emailAndPassword: {
enabled: true,
// In a real app, you'd configure password hashing, JWTs, etc.
getHash: async (password: string) => password + '_hashed', // Placeholder
verifyHash: async (password: string, hash: string) => (password + '_hashed') === hash // Placeholder
},
plugins: [
noDisposableEmails({
errorMessage: "Please use a permanent email address for registration.",
customBlockedDomains: ["temporary.io", "spammail.net"],
paths: ["/sign-up/email", "/sign-in/magic-link"]
}),
],
// ... other better-auth configuration
});
console.log("better-auth instance with disposable email plugin configured.");
console.log("Plugin paths: /sign-up/email, /sign-in/magic-link");