Advanced
Security
Secure your CanxJS applications with built-in security features and best practices.
Security Headers
XSS, CSRF, Content-Type protection
Rate Limiting
Built-in request rate limiting
Password Hashing
Argon2id/bcrypt via Bun
Input Validation
Schema-based validation
Security Middleware
app.ts
1import { createApp, security, rateLimit, cors } from "canxjs";23const app = createApp({ port: 3000 });45// Security headers middleware6app.use(security({7xssProtection: true, // X-XSS-Protection8contentTypeOptions: true, // X-Content-Type-Options: nosniff9frameOptions: "DENY", // X-Frame-Options10hsts: { // Strict-Transport-Security11maxAge: 31536000,12includeSubDomains: true13},14contentSecurityPolicy: "default-src 'self'",15referrerPolicy: "strict-origin-when-cross-origin"16}));1718// Rate limiting19app.use(rateLimit({20windowMs: 60000, // 1 minute21max: 100 // 100 requests per minute22}));2324// CORS configuration25app.use(cors({26origin: ["https://example.com"],27methods: ["GET", "POST", "PUT", "DELETE"],28credentials: true29}));
Authentication
auth.ts
1import { MiddlewareHandler } from "canxjs";23export const authMiddleware: MiddlewareHandler = async (req, res, next) => {4const token = req.header("authorization")?.replace("Bearer ", "");56if (!token) {7return res.status(401).json({8error: "Authentication required",9code: "MISSING_TOKEN"10});11}1213try {14// Verify JWT token15const payload = await verifyJWT(token, process.env.JWT_SECRET!);1617// Store user in request context18req.context.set("user", payload);19req.context.set("userId", payload.sub);2021return next();22} catch (error) {23return res.status(401).json({24error: "Invalid or expired token",25code: "INVALID_TOKEN"26});27}28};2930// Protected routes31app.get("/api/profile", authMiddleware, profileHandler);32app.group("/api/admin", (router) => {33router.middleware(authMiddleware, adminMiddleware);34router.get("/users", listUsers);35});
Password Hashing
passwords.ts
1// Using Bun's built-in password hashing2const hash = async (password: string) => {3return await Bun.password.hash(password, {4algorithm: "argon2id", // or "bcrypt"5memoryCost: 65536,6timeCost: 37});8};910const verify = async (password: string, hash: string) => {11return await Bun.password.verify(password, hash);12};1314// Usage15app.post("/register", async (req, res) => {16const { email, password } = await req.body();1718const hashedPassword = await hash(password);19const user = await User.create({ email, password: hashedPassword });2021return res.status(201).json({ user });22});2324app.post("/login", async (req, res) => {25const { email, password } = await req.body();26const user = await User.query().where("email", "=", email).first();2728if (!user || !await verify(password, user.password)) {29return res.status(401).json({ error: "Invalid credentials" });30}3132const token = await signJWT({ sub: user.id }, { expiresIn: "7d" });33return res.json({ token });34});
Input Validation
validation.ts
1import { validate } from "canxjs";23app.post("/users", async (req, res) => {4const data = await req.body();56const result = validate(data, {7name: ["required", "string", "min:2", "max:100"],8email: ["required", "email"],9password: ["required", "string", "min:8"],10age: ["number", "min:18"]11});1213if (!result.valid) {14return res.status(400).json({15error: "Validation failed",16details: Object.fromEntries(result.errors)17});18}1920const user = await User.create(result.data);21return res.status(201).json(user);22});
CSRF Protection
csrf.ts
1import { csrf } from "canxjs";23// Apply CSRF protection4app.use(csrf({5cookie: true,6cookieName: "_csrf",7headerName: "x-csrf-token"8}));910// CSRF token endpoint11app.get("/api/csrf-token", (req, res) => {12return res.json({ token: req.context.get("csrfToken") });13});
Best Practices
best-practices.ts
1// Environment variables2const config = {3jwtSecret: process.env.JWT_SECRET!,4dbPassword: process.env.DB_PASSWORD!,5apiKey: process.env.API_KEY!6};78// Never log sensitive data9app.use(async (req, res, next) => {10console.log(`${req.method} ${req.path}`);11// DON'T: console.log(req.header("authorization"))12return next();13});1415// Secure cookies16res.cookie("session", token, {17httpOnly: true, // Not accessible via JavaScript18secure: true, // HTTPS only19sameSite: "Strict",20maxAge: 8640021});2223// Sanitize user input before database24const sanitized = input.replace(/<[^>]*>/g, "");