Ir al contenido

FundamentosLección 02

Identidad, autenticación y autorización

¿Quién eres? ¿Puedes hacer esto? Las dos preguntas que responde todo sistema seguro, los factores de autenticación y los modelos de permisos.

Básico13 min de lectura

Al terminar sabrás

  • Separar identificación, autenticación, autorización y auditoría.
  • Elegir factores de autenticación y entender por qué unos resisten el phishing y otros no.
  • Comparar RBAC, permisos finos, ABAC y autorización por relación (dueño del recurso).
  • Reconocer cuándo un fallo es de autenticación (401) y cuándo de autorización (403).

Todo control de acceso, desde la puerta de tu casa hasta una API con millones de usuarios, responde dos preguntas en orden: ¿quién eres? y ¿puedes hacer esto? Confundirlas es el origen de la mayoría de agujeros de seguridad en aplicaciones reales.

  1. Peticióncon credenciales… o sin ellas
  2. Autenticación¿quién eres?
  3. Autorización¿puedes hacer esto con este recurso?
  4. Recursonota, cuenta, pedido…
Autenticar es un paso; autorizar ocurre en cada acceso, y depende del recurso.
ConceptoPreguntaEjemploSi falla
Identificación¿Quién dices ser?El usuario escribe ana—
Autenticación (authn)¿Lo puedes probar?Contraseña correcta + código del móvil401 Unauthorized
Autorización (authz)¿Tienes permiso para esto?ana puede borrar su nota, no la de luis403 Forbidden (o 404)
Auditoría (accounting)¿Qué hizo y cuándo?Registro: “ana borró la nota 41 a las 10:02”—

Una credencial es la prueba de identidad. Se agrupan en tres factores:

  • Algo que sabes: contraseña, PIN.
  • Algo que tienes: el móvil (app de códigos, notificación), una llave física, un passkey guardado en el dispositivo.
  • Algo que eres: huella, cara. En la práctica desbloquean un factor “que tienes” (el passkey del móvil), no viajan al servidor.

La autenticación multifactor (MFA) combina factores de categorías distintas: robar una contraseña ya no basta. Pero no todos los segundos factores son iguales:

MétodoFactor¿Resiste phishing?Comentario
Contraseña solaSabesNoSe reutiliza, se filtra, se adivina
Código por SMSTienesNoVulnerable a SIM swapping y a páginas falsas que reenvían el código
App TOTP (códigos de 6 dígitos)TienesNoMucho mejor que SMS, pero una web falsa puede pedirte el código y usarlo al instante
Enlace mágico por emailTienes (tu buzón)ParcialTan seguro como la cuenta de correo
Passkey / llave FIDO2 (WebAuthn)Tienes (+ eres)SíLa clave está ligada al dominio: en examp1e.com simplemente no funciona

Una vez sabes quién es, ¿cómo decides qué puede hacer? Hay cuatro modelos, y casi todas las aplicaciones reales combinan varios.

Los usuarios tienen roles (ADMIN, USER, SUPPORT) y las reglas se escriben sobre roles: “solo ADMIN entra en /admin”. Es simple y suficiente en muchas aplicaciones. El problema aparece cuando los roles empiezan a multiplicarse: ADMIN_SIN_FACTURACION, SUPPORT_SOLO_LECTURA…

En vez de preguntar “¿quién eres?” se pregunta “¿qué puedes hacer?”: notes:read, notes:write, billing:refund. Los roles se convierten en paquetes de permisos guardados en la base de datos, y el código solo comprueba permisos. En OAuth2 estos permisos se llaman scopes.

La decisión combina atributos del usuario, del recurso y del contexto: “un médico puede ver la historia clínica si pertenece a su hospital y está de guardia y la petición viene de la red interna”. Muy expresivo, más difícil de razonar y de probar.

La decisión depende de la relación entre el usuario y el recurso: es el dueño, es miembro del equipo que lo comparte, lo invitaron como editor. Es el modelo de Google Drive o GitHub, y el que más se olvida en APIs.

Evita

// Cualquier usuario autenticado borra cualquier nota
void delete(Long id, User current) {
if (!current.hasRole("USER")) throw new AccessDenied();
notes.deleteById(id);
}

Prefiere

// Solo el dueño (o un admin) borra la nota
void delete(Long id, User current) {
Note note = notes.findById(id).orElseThrow(NotFound::new);
boolean owner = note.owner().equals(current.name());
if (!owner && !current.hasRole("ADMIN")) throw new NotFound();
notes.delete(note);
}
  • Por función (function level): ¿puede este usuario usar esta operación? “Solo admins llaman a GET /api/admin/stats”. Se resuelve con reglas por URL o por método.
  • Por objeto (object level): ¿puede usar esta operación sobre este recurso concreto? “Solo el dueño borra la nota 42”. Requiere consultar el dato, así que vive en el servicio o en la consulta a la base de datos.

Necesitas los dos. El primero es grueso y barato; el segundo es fino y es donde están los datos.

Mini lab · 10 min

¿Autenticación o autorización?

Objetivo: Clasificar fallos reales y decidir el código HTTP correcto para cada uno.

Para cada situación indica si es un problema de autenticación o de autorización, qué código HTTP debería devolver la API y qué control falta (si falta alguno).

  1. Una petición llega sin cabecera Authorization a GET /api/notes.
  2. luis, autenticado, pide GET /api/notes/42, que pertenece a ana.
  3. ana envía un token caducado.
  4. ana, con rol USER, llama a GET /api/admin/stats.
  5. Un atacante prueba 5 000 contraseñas contra la cuenta admin.
Pista

Para el caso 2 piensa en qué revela un 403 que no revele un 404.

Mostrar respuestaOcultar respuesta
#TipoRespuestaComentario
1Autenticación401No hay credencial: hay que pedirla (WWW-Authenticate).
2Autorización por objeto404 (o 403)Un 403 confirma que la nota 42 existe; un 404 no revela nada. Lo importante es que la consulta filtre por dueño.
3Autenticación401La credencial ya no es válida; el cliente debe renovar el token.
4Autorización por función403Sabemos quién es, pero su rol no basta.
5Autenticación (fuerza bruta)401 en cada intento + rate limiting / bloqueo progresivoLa autenticación sola no lo frena: falta un control de disponibilidad y abuso, y MFA para que una contraseña adivinada no sea suficiente.