@nerdlat/auth
Version:
Authentication library similar to Clerk for React and Express applications
148 lines (147 loc) • 5.88 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAuthRouter = createAuthRouter;
exports.requireAuth = requireAuth;
// src/server/createAuthRouter.ts
const express_1 = __importDefault(require("express"));
const jwt_1 = require("./jwt");
const users_1 = require("./users");
function createAuthRouter(options = {}) {
const router = express_1.default.Router();
const cookieName = options.sessionCookie || 'auth-token';
// Middleware para parsear cookies si no existe
router.use((req, res, next) => {
if (!req.cookies && req.headers.cookie) {
req.cookies = {};
req.headers.cookie.split(';').forEach(cookie => {
const [name, value] = cookie.trim().split('=');
req.cookies[name] = value;
});
}
next();
});
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ error: 'Email and password are required' });
}
const user = users_1.users.find(u => u.email === email && u.password === password);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = (0, jwt_1.signToken)(user);
const userResponse = { id: user.id, email: user.email }; // No devolver password
res.cookie(cookieName, token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 días
});
if (options.onUserLogin) {
options.onUserLogin(userResponse);
}
res.json(userResponse);
}
catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
router.post('/signup', (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ error: 'Email and password are required' });
}
if (options.validateEmail && !options.validateEmail(email)) {
return res.status(400).json({ error: 'Invalid email format' });
}
if (options.validatePassword && !options.validatePassword(password)) {
return res.status(400).json({ error: 'Password does not meet requirements' });
}
if (users_1.users.find(u => u.email === email)) {
return res.status(400).json({ error: 'User already exists' });
}
const id = users_1.users.length + 1;
const user = { id, email, password };
users_1.users.push(user);
const token = (0, jwt_1.signToken)(user);
const userResponse = { id: user.id, email: user.email };
res.cookie(cookieName, token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 7 * 24 * 60 * 60 * 1000
});
if (options.onUserCreate) {
options.onUserCreate(userResponse);
}
res.json(userResponse);
}
catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
router.get('/me', (req, res) => {
try {
const token = req.cookies[cookieName];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
const decoded = (0, jwt_1.verifyToken)(token);
const user = users_1.users.find(u => u.id === decoded.id);
if (!user) {
return res.status(401).json({ error: 'User not found' });
}
res.json({ id: user.id, email: user.email });
}
catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
});
router.post('/logout', (req, res) => {
res.clearCookie(cookieName);
res.json({ message: 'Logged out successfully' });
});
router.post('/reset-password', (req, res) => {
try {
const { email, newPassword } = req.body;
if (!email || !newPassword) {
return res.status(400).json({ error: 'Email and new password are required' });
}
if (options.validatePassword && !options.validatePassword(newPassword)) {
return res.status(400).json({ error: 'Password does not meet requirements' });
}
const user = users_1.users.find(u => u.email === email);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
user.password = newPassword;
res.json({ message: 'Password reset successfully' });
}
catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
return router;
}
// Middleware para proteger rutas
function requireAuth(cookieName = 'auth-token') {
return (req, res, next) => {
try {
const token = req.cookies[cookieName];
if (!token) {
return res.status(401).json({ error: 'Authentication required' });
}
const decoded = (0, jwt_1.verifyToken)(token);
req.user = decoded; // Agregar usuario al request
next();
}
catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
};
}