@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
this
inrun
functions 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);
}
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
5 months ago
5 months ago
5 months ago