Express.js
Authentication e identidad
Explica cómo autenticar requests, resolver la identidad y crear un actor confiable antes de aplicar autorización, multi-tenancy y reglas del dominio.
- Última actualización
- Actualizada
- Nivel
- Fundamentos
Express.js
Explica cómo autenticar requests, resolver la identidad y crear un actor confiable antes de aplicar autorización, multi-tenancy y reglas del dominio.
Authentication responde “¿quién está actuando?”. Authorization responde “¿puede realizar esta acción sobre este recurso?”. Mezclarlas produce fallos de seguridad difíciles de detectar.
Autenticar consiste en verificar una credencial y convertirla en una identidad interna confiable:
credencial externa
→ verificación
→ identidad normalizada
→ actor de la aplicaciónEl actor puede representar usuario, servicio, API key o proceso interno. Todavía no implica permiso sobre una orden o tenant.
Prueba conocimiento de un secreto. Se utiliza normalmente para iniciar una session o emitir tokens, no para enviarse en cada request.
Valor opaco que referencia estado en servidor.
Quien lo posee puede usarlo. Debe viajar por TLS y almacenarse con cuidado.
Adecuada para integraciones o servicios con scope y rotación. No la trates como password de usuario.
Delegan autenticación o autorización a un proveedor. OpenID Connect añade identidad sobre OAuth 2.0.
Útiles entre servicios en entornos controlados. La red o certificado tampoco reemplazan policies de recurso.
Nunca almacenes password reversible. Utiliza una función diseñada para contraseñas, como Argon2id, con parámetros calibrados.
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 64 * 1024,
timeCost: 3,
parallelism: 1,
});Los valores son ilustrativos; deben calibrarse según hardware y riesgo. Un pepper gestionado externamente puede añadir una capa, pero complica rotación.
Mensajes como “usuario no existe” y “password incorrecta” revelan cuentas. Usa un contrato común:
{ "code": "INVALID_CREDENTIALS" }También cuida diferencias de timing, reset de password y registro.
export function makeAuthenticate(verifier: CredentialVerifier): RequestHandler {
return async (request, response, next) => {
const credential = extractCredential(request);
if (!credential) {
response.status(401).json({ code: 'AUTHENTICATION_REQUIRED' });
return;
}
const identity = await verifier.verify(credential);
response.locals.actor = {
id: identity.subject,
kind: identity.kind,
tenantMemberships: identity.tenantMemberships,
authenticationTime: identity.authenticationTime,
};
next();
};
}El middleware normaliza distintas credenciales a un actor interno.
Una credencial puede ser válida pero la cuenta estar:
Decide qué estado se consulta en cada request y qué puede permanecer en cache/token.
No toda operación necesita el mismo nivel. Ver datos puede aceptar autenticación básica; cambiar método de pago puede exigir autenticación reciente o segundo factor.
El actor puede incluir authLevel y authenticatedAt; la policy decide si requiere step-up.
Un flujo seguro necesita:
Almacena hash, no key completa. Muestra el secreto una sola vez, añade prefijo identificable, scopes, expiración y rotación.
key id → lookup
secret → constant-time verificationNo uses una única key compartida por todos los clientes.
Representan workloads, no personas. Necesitan propietario, scope, rotación y auditoría. Evita cuentas técnicas eternas con permisos de administrador.
router.post('/login', validate(loginSchema), async (_request, response) => {
const input = response.locals.validatedBody;
const user = await authenticatePassword.execute(input);
const session = await sessions.create({ userId: user.id });
response.cookie('__Host-session', session.id, cookieOptions);
response.sendStatus(204);
});El caso de uso verifica credenciales; el handler establece el mecanismo HTTP.
No compares secretos con === cuando importa tiempo constante. Bibliotecas criptográficas deben manejarlo.
Rate limit por IP no basta; combina cuenta, dispositivo, reputación y alertas.
Necesitas revocar sessions/tokens, rotar keys y registrar incidentes.
La identidad puede existir globalmente, pero el tenant activo se resuelve y autoriza aparte.
No conviertas indisponibilidad en “credenciales inválidas”. Responde error operativo.
userId del body.Authentication centralizada reduce duplicación, pero una única capa que consulta demasiado puede añadir latencia. Tokens reducen lookup; sessions mejoran revocación. External IdP reduce manejo de passwords, pero añade dependencia y configuración compleja.
Authorization, ownership y policies decide qué acciones puede ejecutar el actor sobre recursos concretos.