Options
List of all the available options for configuring Faire Auth. See Faire Auth Options.
appName
The name of the application.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
appName: "My App",
})baseURL
Base URL for Faire Auth. This is typically the root URL where your application server is hosted. Note: If you include a path in the baseURL, it will take precedence over the default path.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
baseURL: "https://example.com",
})If not explicitly set, the system will check for the environment variable process.env.FAIRE_AUTH_URL
basePath
Base path for Faire Auth. This is typically the path where the Faire Auth routes are mounted. It will be overridden if there is a path component within baseURL.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
basePath: "/api/auth",
})Default: /api/auth
trustedOrigins
List of trusted origins. You can provide a static array of origins, a function that returns origins dynamically, or use wildcard patterns to match multiple domains.
Static Origins
You can provide a static array of origins:
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
trustedOrigins: ["http://localhost:3000", "https://example.com"],
})Dynamic Origins
You can provide a function that returns origins dynamically:
export const auth = faireAuth({
trustedOrigins: async (request: Request) => {
// Return an array of trusted origins based on the request
return ["https://dynamic-origin.com"];
}
})Wildcard Support
You can use wildcard patterns in trusted origins:
export const auth = faireAuth({
trustedOrigins: [
"*.example.com", // Trust all subdomains of example.com
"https://*.example.com", // Trust only HTTPS subdomains
"http://*.dev.example.com" // Trust HTTP subdomains of dev.example.com
]
})secret
The secret used for encryption, signing, and hashing.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
secret: "your-secret-key",
})By default, Faire Auth will look for the following environment variables:
process.env.FAIRE_AUTH_SECRETprocess.env.AUTH_SECRET
If none of these environment variables are set, it will default to "faire-auth-secret-123456789". In production, if it's not set, it will throw an error.
You can generate a good secret using the following command:
openssl rand -base64 32database
Database configuration for Faire Auth.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
database: {
dialect: "postgres",
type: "postgres",
casing: "camel"
},
})Faire Auth supports various database configurations including PostgreSQL, MySQL, and SQLite.
Read more about databases here.
secondaryStorage
Secondary storage configuration used to store session and rate limit data.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
// ... other options
secondaryStorage: {
// Your implementation here
},
})Read more about secondary storage here.
emailVerification
Email verification configuration.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
emailVerification: {
sendVerificationEmail: async ({ user, url, token }) => {
// Send verification email to user
},
sendOnSignUp: true,
autoSignInAfterVerification: true,
expiresIn: 3600 // 1 hour
},
})sendVerificationEmail: Function to send verification emailsendOnSignUp: Send verification email automatically after sign up (default:false)sendOnSignIn: Send verification email automatically on sign in when the user's email is not verified (default:false)autoSignInAfterVerification: Auto sign in the user after they verify their emailexpiresIn: Number of seconds the verification token is valid for (default:3600seconds)
emailAndPassword
Email and password authentication configuration.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
emailAndPassword: {
enabled: true,
disableSignUp: false,
requireEmailVerification: true,
minPasswordLength: 8,
maxPasswordLength: 128,
autoSignIn: true,
sendResetPassword: async ({ user, url, token }) => {
// Send reset password email
},
resetPasswordTokenExpiresIn: 3600, // 1 hour
password: {
hash: async (password) => {
// Custom password hashing
return hashedPassword;
},
verify: async ({ hash, password }) => {
// Custom password verification
return isValid;
}
}
},
})enabled: Enable email and password authentication (default:false)disableSignUp: Disable email and password sign up (default:false)requireEmailVerification: Require email verification before a session can be createdminPasswordLength: Minimum password length (default:8)maxPasswordLength: Maximum password length (default:128)autoSignIn: Automatically sign in the user after sign upsendResetPassword: Function to send reset password emailresetPasswordTokenExpiresIn: Number of seconds the reset password token is valid for (default:3600seconds)revokeSessionsOnPasswordReset: Revoke all sessions when password is reset (default:false)password: Custom password hashing and verification functions
socialProviders
Configure social login providers.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
socialProviders: {
google: {
clientId: "your-client-id",
clientSecret: "your-client-secret",
redirectURI: "https://example.com/api/auth/callback/google"
},
github: {
clientId: "your-client-id",
clientSecret: "your-client-secret",
redirectURI: "https://example.com/api/auth/callback/github"
}
},
})plugins
List of Faire Auth plugins.
import { faireAuth } from "faire-auth";
import { organization, twoFactor } from "faire-auth/plugins";
export const auth = faireAuth({
plugins: [
organization(),
twoFactor(),
],
})user
User configuration options.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
user: {
modelName: "users",
fields: {
email: "emailAddress",
name: "fullName"
},
additionalFields: {
customField: {
type: "string",
}
},
changeEmail: {
enabled: true,
sendChangeEmailVerification: async ({ user, newEmail, url, token }) => {
// Send change email verification
}
},
deleteUser: {
enabled: true,
sendDeleteAccountVerification: async ({ user, url, token }) => {
// Send delete account verification
},
beforeDelete: async (user) => {
// Perform actions before user deletion
},
afterDelete: async (user) => {
// Perform cleanup after user deletion
}
}
},
})modelName: The model name for the user (default:"user")fields: Map fields to different column namesadditionalFields: Additional fields for the user tablechangeEmail: Configuration for changing emaildeleteUser: Configuration for user deletion
session
Session configuration options.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
session: {
modelName: "sessions",
fields: {
userId: "user_id"
},
expiresIn: 604800, // 7 days
updateAge: 86400, // 1 day
disableSessionRefresh: true, // Disable session refresh so that the session is not updated regardless of the `updateAge` option. (default: `false`)
additionalFields: { // Additional fields for the session table
customField: {
type: "string",
}
},
storeSessionInDatabase: true, // Store session in database when secondary storage is provided (default: `false`)
preserveSessionInDatabase: false, // Preserve session records in database when deleted from secondary storage (default: `false`)
cookieCache: {
enabled: true, // Enable caching session in cookie (default: `false`)
maxAge: 300, // 5 minutes
strategy: "compact", // "compact" | "jwt" | "jwe" (default: "compact")
refreshCache: true, // Auto-refresh before expiry without DB query (default: false)
version: "1", // Bump to invalidate all existing caches
},
freshAge: 86400, // 1 day — how fresh a session must be for sensitive operations
},
})modelName: The model name for the session (default:"session")fields: Map fields to different column namesexpiresIn: Expiration time for the session token in seconds (default:604800- 7 days)updateAge: How often the session should be refreshed in seconds (default:86400- 1 day)additionalFields: Additional fields for the session tablestoreSessionInDatabase: Store session in database when secondary storage is provided (default:false)preserveSessionInDatabase: Preserve session records in database when deleted from secondary storage (default:false)freshAge: How old a session can be and still be considered "fresh" for sensitive operations like account deletion (default:86400- 1 day, set0to disable)cookieCache: Enable caching session in cookiestrategy: Encoding strategy —"compact"(base64url + HMAC),"jwt"(JWT spec), or"jwe"(encrypted) (default:"compact")refreshCache: Auto-refresh the cache before expiry without hitting the DB. Settruefor default (80% of maxAge) or{ updateAge: seconds }for custom (default:false)version: Bump this string to invalidate all existing cookie caches (default:"1")
account
Account configuration options.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
account: {
modelName: "accounts",
fields: {
userId: "user_id"
},
encryptOAuthTokens: true, // Encrypt OAuth tokens before storing them in the database
accountLinking: {
enabled: true,
trustedProviders: ["google", "github", "email-password"],
allowDifferentEmails: false
}
},
})modelName: The model name for the accountfields: Map fields to different column names
encryptOAuthTokens
Encrypt OAuth tokens before storing them in the database. Default: false.
updateAccountOnSignIn
If enabled (true), the user account data (accessToken, idToken, refreshToken, etc.) will be updated on sign in with the latest data from the provider.
accountLinking
Configuration for account linking.
enabled: Enable account linking (default:false)trustedProviders: List of trusted providersallowDifferentEmails: Allow users to link accounts with different email addressesallowUnlinkingAll: Allow users to unlink all accounts
verification
Verification configuration options.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
verification: {
modelName: "verifications",
fields: {
userId: "user_id"
},
disableCleanup: false
},
})modelName: The model name for the verification tablefields: Map fields to different column namesdisableCleanup: Disable cleaning up expired values when a verification value is fetched
rateLimit
Rate limiting configuration.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
rateLimit: {
enabled: true,
window: 10,
max: 100,
customRules: {
"/example/path": {
window: 10,
max: 100
}
},
storage: "memory",
modelName: "rateLimit"
}
})enabled: Enable rate limiting (defaults:truein production,falsein development)window: Time window to use for rate limiting. The value should be in seconds. (default:10)max: The default maximum number of requests allowed within the window. (default:100)customRules: Custom rate limit rules to apply to specific paths.storage: Storage configuration. If you passed a secondary storage, rate limiting will be stored in the secondary storage. (options:"memory", "database", "secondary-storage", default:"memory")modelName: The name of the table to use for rate limiting if database is used as storage. (default:"rateLimit")
advanced
Advanced configuration options.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
advanced: {
ipAddress: {
ipAddressHeaders: ["x-client-ip", "x-forwarded-for"],
disableIpTracking: false
},
useSecureCookies: true,
disableCSRFCheck: false,
crossSubDomainCookies: {
enabled: true,
additionalCookies: ["custom_cookie"],
domain: "example.com"
},
cookies: {
session_token: {
name: "custom_session_token",
attributes: {
httpOnly: true,
secure: true
}
}
},
defaultCookieAttributes: {
httpOnly: true,
secure: true
},
cookiePrefix: "myapp",
database: {
// If your DB is using auto-incrementing IDs, set this to true.
useNumberId: false,
// Use your own custom ID generator, or disable generating IDs as a whole.
generateId: (((options: {
model: LiteralUnion<Models, string>;
size?: number;
}) => {
return "my-super-unique-id";
})) | false,
defaultFindManyLimit: 100,
}
},
})ipAddress: IP address configuration for rate limiting and session trackinguseSecureCookies: Use secure cookies (default:false)disableCSRFCheck: Disable trusted origins check (⚠️ security risk)crossSubDomainCookies: Configure cookies to be shared across subdomainscookies: Customize cookie names and attributesdefaultCookieAttributes: Default attributes for all cookiescookiePrefix: Prefix for cookiesgenerateId: Function to generate a unique ID for a model
logger
Logger configuration for Faire Auth.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
logger: {
disabled: false,
disableColors: false,
level: "error",
log: (level, message, ...args) => {
// Custom logging implementation
console.log(`[${level}] ${message}`, ...args);
}
}
})The logger configuration allows you to customize how Faire Auth handles logging. It supports the following options:
disabled: Disable all logging when set totrue(default:false)disableColors: Disable colors in the default logger implementation (default: determined by the terminal's color support)level: Set the minimum log level to display. Available levels are:"info": Show all logs"warn": Show warnings and errors"error": Show only errors"debug": Show all logs including debug information
log: Custom logging function that receives:level: The log level ("info","warn","error", or"debug")message: The log message...args: Additional arguments passed to the logger
Example with custom logging:
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
logger: {
level: "info",
log: (level, message, ...args) => {
// Send logs to a custom logging service
myLoggingService.log({
level,
message,
metadata: args,
timestamp: new Date().toISOString()
});
}
}
})databaseHooks
Database lifecycle hooks for core operations.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
databaseHooks: {
user: {
create: {
before: async (user, ctx) => {
// Modify user data before creation
// ctx is the Hono Context (optional)
return { data: { ...user, customField: "value" } };
},
after: async (user, ctx) => {
// Perform actions after user creation
}
},
update: {
before: async (userData, ctx) => {
// Modify user data before update
// Return false to prevent the update
return { data: { ...userData, updatedAt: new Date() } };
},
after: async (user, ctx) => {
// Perform actions after user update
}
},
delete: {
before: async (user, ctx) => {
// Return false to prevent deletion
},
after: async (user, ctx) => {
// Cleanup after user deletion
}
}
},
session: {
// Same create/update/delete hooks as user
},
account: {
// Same create/update/delete hooks as user
},
verification: {
// Same create/update/delete hooks as user
}
},
})onAPIError
API error handling configuration.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
onAPIError: {
throw: true,
onError: (error, ctx) => {
// Custom error handling
console.error("Auth error:", error);
},
errorURL: "/auth/error"
},
})throw: Throw an error on API error (default:false)onError: Custom error handler — receives(error, ctx)wherectxis the Hono ContexterrorURL: URL to redirect to on error (default:/api/auth/error)exposeMessage: Expose unhandled error messages to client (default:false, use only for debugging)
hooks
Request lifecycle hooks.
import { faireAuth } from "faire-auth";
import { createHook } from "faire-auth/plugins";
export const auth = faireAuth({
hooks: {
before: (options) => createHook()(async (ctx) => {
// Execute before processing the request
console.log("Request path:", ctx.req.path);
}),
after: (options) => createHook()(async (ctx) => {
// Execute after processing the request
})
},
})For more details and examples, see the Hooks documentation.
middleware
Per-route typed Hono middleware, keyed by operationId. Runs before Zod validation in the middleware chain.
import { faireAuth, defineOptions } from "faire-auth";
import { createMiddleware } from "faire-auth/plugins";
const cfg = defineOptions({
baseURL: "http://localhost:3000",
middleware: {
getSession: createMiddleware()(async (ctx, next) => {
console.log("getSession called");
await next();
}),
},
})For more details, see the Hooks & Middleware documentation.
routeHooks
Per-route post-validation hooks, keyed by operationId. Runs after Zod validation but before the route handler. Receives the validation result.
import { defineOptions } from "faire-auth";
const cfg = defineOptions({
baseURL: "http://localhost:3000",
routeHooks: {
signUpEmail: (result, ctx) => {
if (!result.success) return;
const { email } = result.data.json;
if (!email.endsWith("@company.com")) {
return ctx.json({ error: "Only company emails" }, 403);
}
},
},
})For more details, see the Hooks & Middleware documentation.
dto
Response transforms keyed by schema name (user, session, etc.). Applied after the handler, before serialization. Type-threaded through to client inference.
import { defineOptions } from "faire-auth";
const cfg = defineOptions({
baseURL: "http://localhost:3000",
dto: {
user: (user) => ({
id: user.id,
name: user.name,
email: user.email,
}),
},
})For more details, see the Hooks & Middleware documentation.
hono
Hono-specific configuration. Since Faire Auth is built on Hono, this option controls the underlying Hono instance.
import { faireAuth, defineOptions } from "faire-auth";
const cfg = defineOptions({
baseURL: "http://localhost:3000",
hono: {
init: {
// Hono constructor options (e.g. custom getPath, strict mode)
},
openapi: {
enabled: true,
path: "/openapi.json",
version: "3.1",
config: {
openapi: "3.1.1",
info: {
title: "My Auth API",
version: "1.0.0",
},
},
},
},
})init: Hono constructor options passed to the internal Hono instanceopenapi.enabled: Enable the OpenAPI JSON endpoint (default:false)openapi.path: Path for the OpenAPI endpoint, relative to base path (default:"/openapi.json")openapi.version: OpenAPI spec version —"3"or"3.1"(default:"3.1")openapi.config: Full OpenAPI spec configuration object (info, servers, security, tags)
disabledPaths
Disable specific auth paths.
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
disabledPaths: ["/sign-up/email", "/sign-in/email"],
})telemetry
Enable or disable Faire Auth's telemetry collection. (default: false)
import { faireAuth } from "faire-auth";
export const auth = faireAuth({
telemetry: {
enabled: false,
}
})