@re-auth/reauth v0.1.0-alpha.12
π ReAuth - Modular Authentication System
ReAuth is a flexible, plugin-based authentication system for Node.js applications. It provides a robust framework for handling various authentication methods while maintaining a clean and extensible architecture.
π Features
- Plugin-based Architecture: Easily extendable with custom authentication methods
- Multiple Authentication Flows: Supports email/password, passwordless, and more
- TypeScript First: Built with TypeScript for enhanced developer experience
- Dependency Injection: Powered by Awilix for clean dependency management
- Session Management: Built-in session handling with token support
- Extensible: Create custom authentication plugins for any use case
π¦ Installation
pnpm add @re-auth/reauth
# or
yarn add @re-auth/reauth
# or
npm install @re-auth/reauthπ οΈ Getting Started
Basic Setup
import { ReAuthEngine, emailPasswordAuth } from '@re-auth/reauth';
import { KnexEntityService, KnexSessionService } from './services';
// Initialize your entity and session services
const entityService = new KnexEntityService(knex);
const sessionService = new KnexSessionService(knex);
// Create an email/password auth plugin
const emailPassword = emailPasswordAuth({
verifyEmail: true,
loginOnRegister: true,
async sendCode(entity, code, email, type) {
// Implement your email sending logic here
console.log(`Sending ${type} code ${code} to ${email}`);
},
});
// Initialize the auth engine
const auth = new ReAuthEngine({
plugins: [emailPassword],
entity: entityService,
session: sessionService,
sensitiveFields: {
password: true,
token: true,
},
});π Built-in Plugins
Email/Password Authentication
import { emailPasswordAuth } from '@re-auth/reauth';
const emailPassword = emailPasswordAuth({
verifyEmail: true, // Require email verification
loginOnRegister: true, // Automatically login after registration
codeType: 'numeric', // Code type for verification/reset ('numeric' | 'alphanumeric' | 'alphabet')
codeLenght: 6, // Length of the verification code
resetPasswordCodeExpiresIn: 30 * 60 * 1000, // 30 minutes
// Required for email verification and password reset
async sendCode(entity, code, email, type) {
// Send email with the code
console.log(`Sending ${type} code ${code} to ${email}`);
},
// Optional: Custom code generator
async generateCode(email, entity) {
return Math.floor(100000 + Math.random() * 900000); // 6-digit code
},
});π§© Creating Custom Plugins
ReAuth supports two types of plugins:
1. Object-Based Plugin
import { AuthPlugin } from '@re-auth/reauth';
const myPlugin: AuthPlugin = {
name: 'my-auth-plugin',
version: '1.0.0',
steps: [
{
name: 'authenticate',
description: 'Custom authentication step',
async run(input, { container }) {
// Your authentication logic here
return {
success: true,
message: 'Authenticated successfully',
status: 'authenticated',
};
},
inputs: ['username', 'password'],
},
],
initialize(container) {
// Initialize your plugin here
},
getSensitiveFields() {
return ['password', 'token'];
},
};2. Class-Based Plugin
import { AuthPlugin, AuthStep } from '@re-auth/reauth';
export class MyAuthPlugin implements AuthPlugin {
name = 'my-auth-plugin';
version = '1.0.0';
steps: AuthStep[] = [];
constructor(private container: any) {
this.steps = [
{
name: 'authenticate',
description: 'Custom authentication step',
run: this.authenticate.bind(this),
inputs: ['username', 'password'],
},
];
}
private async authenticate(input: any) {
// Your authentication logic here
return {
success: true,
message: 'Authenticated successfully',
status: 'authenticated',
};
}
async initialize() {
// Initialize your plugin here
}
getSensitiveFields() {
return ['password', 'token'];
}
}π API Reference
ReAuthEngine
The main authentication engine that manages plugins and authentication flows.
const auth = new ReAuthEngine({
plugins: AuthPlugin[], // Array of authentication plugins
entity: EntityService, // Entity service implementation
session: SessionService, // Session service implementation
sensitiveFields?: { // Fields to redact in logs
[key: string]: boolean;
};
authHooks?: AuthHooks[]; // Global authentication hooks
});Built-in Services
EntityService: Manages user entitiesSessionService: Handles session managementKnexEntityService: Knex-based entity serviceKnexSessionService: Knex-based session service
π License
MIT
π§± Plugin Interface
interface AuthPlugin {
name: string;
version: string;
steps: AuthStep[];
defaultConfig?: Record<string, any>;
requiredInput?: RequiredInputShape;
initialize?(container?: AwilixContainer): void | Promise<void>;
}πͺ Step Structure
Each step is a discrete auth flow like login, register, etc.
interface AuthStep {
name: string;
description: string;
validationSchema?: ValidationSchema;
run(input: AuthInput): Promise<any>;
hooks?: {
before?: HookFunction[];
after?: HookFunction[];
onError?: (error: Error, input: AuthInput) => Promise<void>;
};
}π Validation Schema
type ValidationSchema = Record<string, ((value: any, input: AuthInput) => string | undefined)[]>;You can also use Standard Schema compliant validators (see Standard Schema Support below).
β Required Input Flags
Defines what the plugin step expects:
interface RequiredInputShape {
reqBody?: boolean;
reqQuery?: boolean;
reqParams?: boolean;
reqHeaders?: boolean;
reqMethod?: boolean;
}πͺ Hook Types
type HookFunction = (input: AuthInput, output?: any) => Promise<void>;π¦Plugin Lifecycle
The lifecycle of a plugin follows these steps:
β οΈ Object Plugin Restrictions
- β Do not use
thisinrunfunctions or hooks. - β Capture context using top-level variables or closures.
- β οΈ If plugin requires internal state, switch to class format.
π§ͺ Example Registry
export const authPlugins: AuthPlugin[] = [emailPasswordPlugin, new MagicLinkPlugin(), new OauthPlugin()];β Summary
| Format | this Allowed | Lifecycle Support | Best For |
|---|---|---|---|
| Object-based | β No | β Yes | Lightweight plugins |
| Class-based | β Yes | β Yes | Stateful or complex plugins |
π Standard Schema Support
ReAuth supports Standard Schema for validation, allowing you to use any compatible validation library (like Zod, Valibot, ArkType, etc.) with your plugins.
Using Standard Schema in a Plugin
import { type } from 'arktype';
import { createStandardSchemaRule } from '@the-forgebase/reauth/utils';
// Define schemas using ArkType (which implements standard-schema)
const emailSchema = type('string.email');
const passwordSchema = type('string.alphanumeric >= 3');
// Create validation rules using standard-schema
const loginValidation = {
email: createStandardSchemaRule(emailSchema, 'Please enter a valid email address'),
password: createStandardSchemaRule(passwordSchema, 'Password must be at least 8 characters'),
};Direct Validation with Standard Schema
You can also use the standardValidate utility function to validate data directly:
import { standardValidate } from '@the-forgebase/reauth/utils';
import { type } from 'arktype';
const userSchema = type({
email: 'string.email',
password: 'string.alphanumeric >= 8',
});
try {
const validatedUser = await standardValidate(userSchema, userData);
console.log('Valid user data:', validatedUser);
} catch (error) {
console.error('Validation failed:', error);
}11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago