@magik_io/preset-session
v2.0.0
Published
Session middleware preset for Magik (express-session, store-agnostic)
Maintainers
Readme
@magik_io/preset-session
Session middleware preset for Magik featuring Redis-backed sessions, Passport.js authentication, and flash messages.
Installation
pnpm add @magik_io/preset-sessionFeatures
- 🔧 Fully Configurable - Customize all session components
- 💾 Redis-Backed Sessions - Persistent session storage with Redis
- 🔐 Passport.js Integration - Built-in authentication middleware
- 💬 Flash Messages - Session-based flash message support
- 🎯 Priority Control - Fine-tune middleware execution order
- ⚡ Enable/Disable Components - Only include what you need
- 🍪 Cookie Customization - Full control over session cookies
Prerequisites
This preset requires a Redis connection. Make sure you have Redis installed and a client connection ready.
import { createClient } from 'redis';
const redisClient = createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379'
});
await redisClient.connect();Usage
Quick Start
import { MagikServer } from '@magik_io/magik';
import { sessionPreset } from '@magik_io/preset-session';
import { createClient } from 'redis';
const redisClient = createClient();
await redisClient.connect();
const server = new MagikServer();
server.applyPreset(sessionPreset(redisClient));Custom Session Secret
server.applyPreset(sessionPreset(redisClient, {
session: {
secret: process.env.SESSION_SECRET || 'your-secret-key',
name: 'myapp.sid',
}
}));Custom Priorities
Adjust the execution order of session middleware:
server.applyPreset(sessionPreset(redisClient, {
priority: {
session: 85,
passportInitialize: 80,
passportSession: 79,
flash: 78,
}
}));Disable Specific Components
Only enable what you need:
// Session and flash only, no Passport
server.applyPreset(sessionPreset(redisClient, {
session: { enabled: true },
passport: { enabled: false },
flash: { enabled: true }
}));
// Session and Passport only, no flash messages
server.applyPreset(sessionPreset(redisClient, {
session: { enabled: true },
passport: { enabled: true },
flash: { enabled: false }
}));Advanced Cookie Configuration
Production Secure Cookies
server.applyPreset(sessionPreset(redisClient, {
session: {
cookie: {
secure: true, // Requires HTTPS
httpOnly: true,
sameSite: 'strict',
maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
domain: '.example.com',
path: '/',
}
}
}));Development Cookies
server.applyPreset(sessionPreset(redisClient, {
session: {
cookie: {
secure: false,
httpOnly: true,
sameSite: 'lax',
maxAge: 1000 * 60 * 60, // 1 hour
}
}
}));Session Options
Multiple Session Secrets (Key Rotation)
server.applyPreset(sessionPreset(redisClient, {
session: {
secret: [
process.env.SESSION_SECRET_NEW!,
process.env.SESSION_SECRET_OLD!,
],
}
}));Rolling Sessions
server.applyPreset(sessionPreset(redisClient, {
session: {
rolling: true, // Reset maxAge on every response
resave: false,
saveUninitialized: false,
}
}));Behind Proxy Configuration
server.applyPreset(sessionPreset(redisClient, {
session: {
proxy: true, // Trust first proxy
cookie: {
secure: true,
}
}
}));Session Destruction Behavior
server.applyPreset(sessionPreset(redisClient, {
session: {
unset: 'destroy', // or 'keep'
}
}));Passport Configuration
Custom User Property
server.applyPreset(sessionPreset(redisClient, {
passport: {
enabled: true,
userProperty: 'currentUser', // Default is 'user'
}
}));
// Access in routes as req.currentUser instead of req.userComplete Configuration Example
import { createClient } from 'redis';
const redisClient = createClient({
url: process.env.REDIS_URL,
socket: {
reconnectStrategy: (retries) => Math.min(retries * 50, 500),
},
});
await redisClient.connect();
const isDevelopment = process.env.NODE_ENV === 'development';
server.applyPreset(sessionPreset(redisClient, {
priority: {
session: 80,
passportInitialize: 75,
passportSession: 74,
flash: 73,
},
session: {
enabled: true,
secret: process.env.SESSION_SECRET || 'development-secret',
name: 'app.sid',
resave: false,
saveUninitialized: false,
rolling: true,
proxy: !isDevelopment,
cookie: {
secure: !isDevelopment,
httpOnly: true,
sameSite: isDevelopment ? 'lax' : 'strict',
maxAge: 1000 * 60 * 60 * 24 * (isDevelopment ? 1 : 7),
domain: isDevelopment ? undefined : '.example.com',
},
},
passport: {
enabled: true,
},
flash: {
enabled: true,
},
}));Using Flash Messages
// Set flash message
app.get('/login', (req, res) => {
req.flash('error', 'Invalid credentials');
res.redirect('/login');
});
// Get flash messages
app.get('/login', (req, res) => {
const errors = req.flash('error');
res.render('login', { errors });
});Environment-Based Configuration
const sessionConfig: SessionOptions = {
session: {
secret: process.env.SESSION_SECRET!,
name: process.env.SESSION_NAME || 'sessionId',
cookie: {
secure: process.env.COOKIE_SECURE === 'true',
maxAge: parseInt(process.env.SESSION_MAX_AGE || '86400000'),
domain: process.env.COOKIE_DOMAIN,
},
},
};
server.applyPreset(sessionPreset(redisClient, sessionConfig));Default Configuration
The preset with no options is equivalent to:
sessionPreset(redisClient, {
priority: {
session: 80,
passportInitialize: 75,
passportSession: 74,
flash: 73,
},
session: {
enabled: true,
secret: 'change-this-secret',
name: 'sessionId',
resave: false,
saveUninitialized: false,
cookie: {
path: '/',
httpOnly: true,
secure: process.env.COOKIE_SECURE === 'true',
sameSite: 'lax',
maxAge: 86400000, // 24 hours
},
},
passport: {
enabled: true,
},
flash: {
enabled: true,
},
})API
sessionPreset(redisConnection, options?): MiddlewarePreset
Factory function to create a session preset with Redis-backed storage.
Parameters
- redisConnection (required):
RedisClientType- Connected Redis client instance - options (optional):
SessionOptions- Configuration options
Options
interface SessionOptions {
priority?: {
session?: number;
passportInitialize?: number;
passportSession?: number;
flash?: number;
};
session?: {
enabled?: boolean;
secret?: string | string[];
name?: string;
resave?: boolean;
saveUninitialized?: boolean;
cookie?: {
path?: string;
httpOnly?: boolean;
secure?: boolean;
sameSite?: 'strict' | 'lax' | 'none' | boolean;
maxAge?: number;
domain?: string;
};
rolling?: boolean;
proxy?: boolean;
unset?: 'destroy' | 'keep';
};
passport?: {
enabled?: boolean;
userProperty?: string;
};
flash?: {
enabled?: boolean;
};
}Session Components
Express Session
Provides session support with Redis-backed storage for persistence across server restarts and load balancing.
Passport.js
Authentication middleware that works seamlessly with sessions. Supports various authentication strategies.
Connect Flash
Provides flash message support for displaying one-time messages (e.g., success messages, error messages) stored in the session.
Dependencies
This preset automatically handles dependencies between middleware:
- Passport Initialize depends on Session
- Passport Session depends on Passport Initialize
- Flash depends on Session
Best Practices
- Always use strong secrets in production (use environment variables)
- Enable secure cookies when behind HTTPS
- Use rolling sessions for better security
- Set appropriate maxAge based on your security requirements
- Configure proxy trust when behind a reverse proxy
- Use Redis connection pooling for better performance
- Implement Redis reconnection strategy for reliability
- Monitor Redis connection health
Security Considerations
- Never commit session secrets to version control
- Use HTTPS in production with
secure: truecookies - Set
httpOnly: trueto prevent XSS attacks - Use
sameSite: 'strict'for maximum CSRF protection - Implement session timeout and rotation
- Regularly rotate session secrets
- Monitor for session fixation attacks
License
MIT
