@samueleoraziodurante/better-auth-gdpr
v1.0.0
Published
Better Auth plugin to elegantly handle dynamic GDPR and TOS consents
Maintainers
Readme
Better Auth GDPR Plugin
A powerful and dynamic plugin for Better Auth to seamlessly handle GDPR, Terms of Service, and custom consent flags during user registration.
Why this plugin?
When using complex authentication methods in Better Auth (like the OPAQUE protocol or Passkeys), injecting custom fields into the sign-up payload can be tricky due to strict type checking and network constraints.
This plugin solves the problem elegantly:
- Dynamic Schema: Define any custom boolean fields you need (e.g.,
privacyPolicy,newsletter,ageConsent). - Body Injection: It intercepts the frontend request and securely injects your consents into the JSON body.
- Server-Side Enforcement: It validates the required fields on the server before creating the user.
- 100% Type-Safe: Fully compatible with
$InferServerPlugin, meaning your database schema and frontend client are automatically typed.
Installation
npm install better-auth-gdpr
# or
yarn add better-auth-gdpr
# or
pnpm add better-auth-gdpr
# or
bun add better-auth-gdpr1. Server Setup
Import the gdprPlugin in your server-side auth.ts file. You can define as many custom consent fields as you want. Set required: true if the user must accept them to register.
// server/auth.ts
import { betterAuth } from "better-auth";
import { gdprPlugin } from "better-auth-gdpr";
export const auth = betterAuth({
database: /* your db config */,
plugins: [
gdprPlugin({
termsOfService: { required: true },
privacyPolicy: { required: true },
newsletter: { required: false, defaultValue: false }, // Optional!
isOver18: { required: true }
}),
// ... your other plugins (opaque, passkey, etc.)
]
});Update your Database
Since the plugin dynamically adds these fields to your user table, remember to run the Better Auth CLI to migrate your database:
npx @better-auth/cli generate
# or
bunx @better-auth/cli generate2. Client Setup
Add the gdprClientPlugin to your frontend client configuration.
// client/auth.ts
import { createAuthClient } from "better-auth/react"; // or /client, /vue, /svelte
import { gdprClientPlugin } from "better-auth-gdpr/client";
export const authClient = createAuthClient({
baseURL: "http://localhost:3000",
plugins: [
gdprClientPlugin(),
// ... other client plugins
],
});3. Usage in your Frontend
Using the plugin is incredibly simple. Right before you call any sign-up method, use authClient.gdpr.setConsent() to load the user's choices into memory. The plugin will automatically attach them to the next sign-up request!
import { authClient } from "./auth";
async function handleSignUp(email, password) {
// 1. Prepare the consents based on your UI checkboxes
authClient.gdpr.setConsent({
termsOfService: true,
privacyPolicy: true,
newsletter: false,
isOver18: true,
});
// 2. Call the sign-up method (works with email, opaque, etc.)
// The plugin intercepts this call and securely injects the consents!
const { data, error } = await authClient.signUp.opaque({
email,
password,
name: "John Doe",
});
// 3. Optional but RECOMMENDED: Clear the memory after the attempt
// This prevents old consents from leaking into future requests if the user retries
authClient.gdpr.clearConsent();
if (error) {
// If a required consent is missing, the server will block it and return a 400 APIError
console.error("Sign up failed:", error.message);
return;
}
console.log("User created! Consents saved:", data.user.privacyPolicy);
}Features
- Protocol Agnostic: Works perfectly with standard Email/Password, OPAQUE, Passkeys, and OAuth.
- No CORS Configuration Needed: Unlike header-based workarounds, this plugin injects data directly into the request body, avoiding annoying preflight CORS issues.
- Fully Typed: Thanks to Better Auth's inference engine,
data.user.newsletterwill be automatically typed as abooleanin your frontend code.
License
MIT
