Deno, como entorno de ejecución moderno para JavaScript y TypeScript, ofrece varias ventajas en términos de seguridad. Su enfoque en la seguridad por diseño incluye la gestión de permisos granular y un runtime sin acceso implícito al sistema. Sin embargo, la seguridad en aplicaciones Deno no solo depende del entorno, sino también de cómo se implementan funcionalidades clave como la autenticación y autorización. Este artículo explora cómo construir aplicaciones seguras en Deno con ejemplos prácticos y buenas prácticas.
Introducción a la seguridad en Deno Link to heading
Ventajas de Deno en términos de seguridad Link to heading
- Sistema de permisos: Deno requiere permisos explícitos para acceder a archivos, red y entorno.
- Tipado estático: TypeScript mejora la robustez del código.
- Integración nativa con WebAssembly (WASM): Reduce vulnerabilidades por código nativo inseguro.
A pesar de estas ventajas, los desarrolladores deben implementar medidas adicionales para proteger sus aplicaciones, especialmente en lo relacionado con la autenticación y autorización.
Autenticación en Deno Link to heading
La autenticación verifica la identidad de los usuarios. Una implementación segura considera:
- Uso de protocolos modernos como OAuth 2.0 o OpenID Connect (OIDC).
- Encriptación de contraseñas con algoritmos seguros (bcrypt, Argon2).
- Tokens seguros (JWT con HS256 o RS256).
Ejemplo práctico: Autenticación basada en JWT Link to heading
import { create, verify } from "https://deno.land/x/djwt/mod.ts";
const secretKey = "your-secret-key";
// Generar un token
async function generateToken(payload: Record<string, unknown>) {
const jwt = await create({ alg: "HS256", typ: "JWT" }, payload, secretKey);
return jwt;
}
// Verificar un token
async function verifyToken(token: string) {
try {
const payload = await verify(token, secretKey, "HS256");
return payload;
} catch (error) {
throw new Error("Token inválido");
}
}
// Ejemplo de uso
const token = await generateToken({ id: 1, role: "admin" });
console.log("Token generado:", token);
const payload = await verifyToken(token);
console.log("Payload verificado:", payload);
Buenas prácticas para la autenticación Link to heading
- Usar HTTPS: Protege los tokens en tránsito.
- Implementar expiración de tokens: Minimiza riesgos en caso de compromiso.
- Almacenar contraseñas de forma segura:
import { hash, compare } from "https://deno.land/x/bcrypt/mod.ts";
const password = "securepassword";
const hashedPassword = await hash(password);
console.log("Contraseña hasheada:", hashedPassword);
const isValid = await compare(password, hashedPassword);
console.log("Contraseña válida:", isValid);
Autorización en Deno Link to heading
La autorización determina qué recursos puede acceder un usuario autenticado.
Ejemplo práctico: Middleware para roles Link to heading
Un middleware puede garantizar que solo ciertos roles accedan a rutas específicas:
import { Context } from "https://deno.land/x/oak/mod.ts";
async function roleMiddleware(ctx: Context, next: () => Promise<unknown>, allowedRoles: string[]) {
const token = ctx.request.headers.get("Authorization")?.replace("Bearer ", "");
if (!token) {
ctx.response.status = 401;
ctx.response.body = { error: "Token no proporcionado" };
return;
}
try {
const payload = await verifyToken(token);
if (!allowedRoles.includes(payload.role)) {
ctx.response.status = 403;
ctx.response.body = { error: "Acceso denegado" };
return;
}
await next();
} catch (error) {
ctx.response.status = 401;
ctx.response.body = { error: "Token inválido" };
}
}
// Ejemplo de uso
router.get(
"/admin",
(ctx, next) => roleMiddleware(ctx, next, ["admin"]),
(ctx) => {
ctx.response.body = { message: "Bienvenido, admin" };
},
);
Buenas prácticas para la autorización Link to heading
- Principio de menor privilegio: Limitar accesos a lo estrictamente necesario.
- Políticas basadas en roles (RBAC): Simplifican la gestión de permisos.
- Registro de eventos de acceso: Proporciona trazabilidad.
Medidas adicionales de seguridad Link to heading
- CORS: Configurar correctamente para evitar accesos no autorizados.
import { oakCors } from "https://deno.land/x/cors/mod.ts";
app.use(oakCors({
origin: "https://example.com",
}));
- Validación de datos:
import { z } from "https://deno.land/x/zod/mod.ts";
const userSchema = z.object({
username: z.string().min(3),
password: z.string().min(8),
});
try {
const userData = userSchema.parse({ username: "test", password: "secure" });
console.log("Datos válidos:", userData);
} catch (error) {
console.error("Error de validación:", error);
}
- Monitoreo y auditoría: Implementar registros de eventos sensibles.
- Uso de secretos seguros: Gestionar claves de API y configuraciones sensibles mediante herramientas como Deno Deploy Secrets.
Conclusión Link to heading
La seguridad en aplicaciones Deno va más allá de las capacidades intrínsecas del entorno. Una implementación adecuada de autenticación y autorización, junto con medidas complementarias, garantiza aplicaciones robustas y protegidas contra amenazas modernas. Aplicar las mejores prácticas descritas y mantenerse actualizado con las últimas vulnerabilidades es esencial para mantener la confianza y la integridad de tus aplicaciones.