fedorthinks

Curso exprés · No. 08

Dos preguntas se esconden detrás de una sola palabra, «auth». La autenticación prueba quién sos; la autorización decide qué tenés permitido hacer. Confundilas, salteá cualquiera de las dos, o confiá en el cliente, y la puerta queda abierta.

22 conceptos · un diagrama para cada uno · hoja de referencia al final

§ 01

Detrás de la palabra «auth» se esconden dos preguntas distintas. La mayoría de los bugs de seguridad vienen de confundirlas — o de responder una y olvidar la otra.

Authentication (authN) — ¿quién sos?

Mostrar tu pasaporte en el aeropuerto — probar que realmente sos la persona que decís ser.

Este es el concepto de Authentication (authN), y significa probar la identidad: un login, una passkey, un token que dice «esta realmente es Alice». Normalmente ocurre una vez por sesión. Si la errás, un impostor entra haciéndose pasar por otra persona. Pero probar quién sos no dice nada sobre qué te está permitido hacer — esa es la otra pregunta, completamente distinta.

Credentialpassword · passkey · tokenVerifyAuthNIdentityuser = Aliceanswers one question: WHO is this?
La authN convierte una credencial (contraseña, passkey, token) en una identidad — y responde solo a la pregunta «¿quién es?».
ConceptAuthentication (authN)· probar la identidad
Qué es
Comprobar que el usuario es quien dice ser.
Cómo funciona

El usuario presenta una credencial (contraseña, passkey, token); el sistema la verifica y establece una identidad.

Ejemplo
Login con email y contraseña: «esta es Alice».
Trampa
Saber quién es alguien no dice qué puede hacer.
Relaciones

Alimenta a Authorization; se hace con Password Hashing, MFA, Passkeys, OIDC.

Authorization (authZ) — ¿qué te está permitido hacer?

Una tarjeta llave de hotel — no prueba nada sobre tu nombre, pero abre tu habitación y no las otras, y no la oficina del gerente.

Este es el concepto de Authorization (authZ): decidir qué tiene permitido hacer una identidad — leer esto, editar aquello, nunca tocar el panel de admin. A diferencia de la authN, hay que verificarla en cada request, porque un solo usuario logueado puede tocar cien cosas distintas. Saber quién es alguien no es permiso para hacer nada en particular.

WhoAlice, editorActioneditResourcedoc #42Policy checkAuthZAllowDenyon every request
La authZ recibe quién, qué acción y qué recurso — y en cada request decide: permitir o denegar.
ConceptAuthorization (authZ)· decidir permisos
Qué es
Decidir qué puede hacer esta identidad con este recurso.
Cómo funciona

En cada request: quién + acción + recurso → regla → permitir o denegar.

Ejemplo

Alice, la editora, puede editar el doc #42, pero no abrir el panel de admin.

Trampa

Verificar una vez y olvidarse. Hay que verificar en cada request, del lado del servidor.

Relaciones

Modelos — Least Privilege, RBAC, ABAC, Ownership Check; fallo — Broken Access Control.

Dos capas — nunca las colapses

Un club nocturno: el patovica revisa tu documento en la puerta una vez, y el barman igual revisa que tengas la edad cada vez que pedís un trago. Dos chequeos, dos momentos.

El error clásico es fusionar las dos — probar la identidad una vez y confiar en eso para siempre, o meter cada permiso dentro de un token de login y nunca volver a verificar. La authN ocurre en la puerta; la authZ ocurre en cada puerta de adentro. Mantenelas separadas, y verificá la segunda constantemente.

front door: who are you?every inner door: may you?UserAuthNonce per loginGET /orders/7AuthZ checkPUT /docs/3AuthZ checkDELETE /users/9AuthZ check
La authN es una puerta de entrada. La authZ es un chequeo en cada puerta interior — es decir, en cada request.

Don't Roll Your Own Auth — nunca la armes por tu cuenta

No soldás tu propia bóveda de banco con chapa en el garaje — comprás una construida y probada por gente que no hace otra cosa.

Esta es la práctica de Don't Roll Your Own Auth. La identidad es el cimiento sobre el que se apoya todo lo demás, y es tremendamente fácil equivocarse de forma sutil. Usá estándares y librerías probadas — protocolos establecidos, una librería o proveedor de auth curtido en batalla — no un esquema ingenioso que inventaste vos. La historia de la seguridad está llena de auth casera que parecía andar bien hasta que de golpe dejó de hacerlo.

PracticeDon't Roll Your Own Auth· estándares antes que hacerlo a mano
Problema
La auth casera parece andar bien hasta que alguien la rompe.
Idea
Usar protocolos, librerías y proveedores probados.
Ejemplo

En vez de tu propio esquema de tokens — OIDC y la auth de tu framework.

Coste
Hay que aprender la herramienta de otro e integrarla bien.
Cuándo usarlo
Casi siempre.
Relaciones
Lleva a Auth Provider; estándares — OAuth 2.0, OIDC.

El mapa: 22 conceptos en seis grupos

Un llavero: primero ves todo el manojo, después aprendés qué llave abre qué puerta.

Los conceptos del curso se agrupan en seis grupos. Cada uno responde su propia pregunta: qué son las dos «auth», cómo probar la identidad, cómo seguir logueado, cómo dar acceso sin contraseña, cómo decidir permisos, y cómo suele romperse todo.

Two questionsAuthenticationAuthorizationNo DIY authProving identityPassword hashingMFAPasskeysStaying logged inSessionJWThttpOnly cookieDelegated accessOAuth 2.0OIDCAPI keyPermissionsLeast privilegeRBACABACOwnership checkFailure modesIDORToken leakageTrusting the client
Seis grupos de conceptos — los capítulos 1–6 los siguen. El capítulo 7 es cómo elegir, más la hoja de referencia.

Cada concepto de abajo recibe el mismo tratamiento: su nombre en inglés (el término con el que vas a buscar en la documentación), una imagen de la vida real, un diagrama y una ficha con campos. Al final, una hoja de referencia con todos los conceptos.

La autenticación es la puerta. La autorización es cada puerta de adentro. Si te salteás la segunda, la primera no vale nada.

§ 02

La autenticación se reduce a probar que sos vos. Los factores van desde la contraseña, débil pero universal, hasta la passkey moderna, resistente al phishing.

Password Hashing — contraseñas, el default débil

Una palabra secreta compartida con el portero — sirve hasta que alguien la escucha, la adivina, o la usás en todos lados.

Las contraseñas son universales y el factor común más débil: se reutilizan, se adivinan, se les hace phishing. Si hay que usarlas, la regla innegociable es nunca guardarlas como texto. Guardá un hash lento y con sal (Argon2, bcrypt) — eso es Password Hashing — para que una base de datos robada no entregue las contraseñas de todos. (Más sobre esto en el capítulo de errores.)

Passwordhunter2+ saltrandom, per userSlow hashArgon2 · bcryptDB stores$argon2id$…Stolen DBonly hashescracking is slow, one user at a time
Contraseña + sal aleatoria → hash lento → solo se guarda el hash. Una base de datos robada no entrega ninguna contraseña.
PracticePassword Hashing· hash lento con sal
Problema

Contraseñas guardadas como texto: una filtración y el atacante las tiene todas.

Idea

Guardar no la contraseña sino un hash lento con una sal — distinta para cada usuario.

Ejemplo

Al hacer login, calcular Argon2/bcrypt de la contraseña tipeada y comparar.

Coste
El login es un poco más lento — a propósito.
Cuándo usarlo
Siempre, si guardás contraseñas.
Relaciones
El anti-ejemplo es Plaintext / Fast Hash; sumá MFA encima.

MFA — algo que sabés, tenés, sos

Una caja de seguridad del banco necesita tu llave y la del banco. Una sola no abre nada.

MFA (Multi-Factor Authentication), o doble factor, exige una segunda prueba además de la contraseña — algo que tenés (un código de una app, una llave de seguridad) o algo que sos (una huella digital). Así, ni una contraseña robada sirve por sí sola. Un código de app autenticadora (TOTP) es sólido; los códigos por SMS son débiles (se pueden interceptar) pero mejores que nada. MFA es la mejora de seguridad más grande y barata que podés agregar.

Something you knowpasswordSomething you haveTOTP app · security keySomething you arefingerprint · faceAccess2+ factorsany 2 of 3SMS code: weak (interceptable)
Tres tipos de factores: saber, tener, ser. Para entrar hacen falta al menos dos distintos.
PracticeMFA· Multi-Factor Authentication, 2FA
Problema
Una contraseña robada = acceso total a la cuenta.
Idea
Exigir un segundo factor de otro tipo: «tener» o «ser».
Ejemplo
Contraseña + un código TOTP de seis dígitos de una app autenticadora.
Coste

Un paso extra al hacer login; los códigos por SMS se pueden interceptar.

Cuándo usarlo
Donde importe; obligatorio en cuentas de admin.
Relaciones

Refuerza Password Hashing; las Passkeys son el siguiente paso.

Passkeys — el futuro sin contraseñas

Una llave que solo funciona en la única puerta para la que fue cortada — falsificá el sitio, copiá la foto de la cerradura, y la llave simplemente no gira.

Las passkeys (basadas en el estándar WebAuthn) reemplazan las contraseñas por un par de claves criptográficas atado a tu dispositivo y al sitio real, así que no hay nada que phishear, reutilizar o filtrar — y Apple, Google y Microsoft ya las usan por defecto. La clave privada nunca sale de tu dispositivo; el sitio solo ve una firma. Hacia ahí va la autenticación: nada que robar.

Your deviceholds private keyreal-site.comstores public keyfake-site.comwrong origin1. challenge2. signature✗ no signature herekey never leaves device
El sitio manda un desafío, el dispositivo responde con una firma. Un sitio de phishing en otra dirección no recibe ninguna firma.
ConceptPasskeys· WebAuthn, login sin contraseña
Problema
A las contraseñas les hacen phishing, se reutilizan y se filtran.
Idea

Un par de claves: la privada queda en el dispositivo, el sitio guarda la pública. Entrar es una firma.

Ejemplo
Entrar con la huella o con Face ID en vez de tipear una contraseña.
Coste

Necesita soporte del dispositivo y un camino de recuperación de respaldo.

Cuándo usarlo

Como login principal donde los usuarios tengan dispositivos modernos.

Relaciones

Reemplaza a Password Hashing; por sí sola, más fuerte que MFA por SMS.

Una contraseña es un secreto que podés perder. Una passkey es una prueba que no. Sumá un segundo factor en cualquier caso.

§ 03

HTTP te olvida entre un request y otro, así que después de entrar el sistema necesita una forma de seguir reconociéndote. Dos enfoques, con un compromiso real.

Stateless HTTP — HTTP no tiene memoria

Un negocio donde el empleado te olvida en cuanto te das vuelta — así que necesitás un ticket para demostrar, en tu próximo paso, que ya pagaste.

HTTP es stateless (sin estado): cada request es independiente; el servidor no recuerda que te logueaste hace un segundo. Entonces, después de la autenticación te dan algo — una cookie o un token — que mandás con cada request para decir «sigo siendo yo». Todo lo que sigue son dos formas de hacerlo. (Esto es la falta de estado del curso de protocolos.)

Request 1+ cookie / tokenit's still meRequest 2+ cookie / tokenit's still meRequest 3+ cookie / tokenit's still meServerforgets between calls
El servidor no recuerda ningún request anterior, así que cada request lleva consigo una cookie o un token.
ConceptStateless HTTP· sin memoria entre requests
Qué es
El servidor no recuerda los requests anteriores del cliente.
Consecuencia

Después del login necesitás un «pase» que viaje con cada request.

Ejemplo

El navegador adjunta la cookie a cada request a ese sitio por sí solo.

Relaciones
Dos respuestas — Session y JWT.

Session — el servidor recuerda

Un guardarropa — vos tenés un ticket numerado, y toda la información real está detrás del mostrador bajo ese número.

Con las sesiones, el servidor guarda quién sos y te da una cookie que contiene solo un id de sesión aleatorio. En cada request, busca el id. El servidor es la fuente de verdad, así que desloguear o bloquear a alguien es instantáneo — basta con borrar la sesión. El costo es que el servidor tiene que guardar y consultar ese estado. El default correcto para la mayoría de las apps web.

Browsercookie: sid=8f3a…Serverlooks up the sidSession store8f3a → AliceDelete sessionlogout / ban = instantrevoke
La cookie contiene solo un id. El servidor lo busca en el almacén de sesiones. Borrás la sesión — el usuario queda afuera al instante.
PatternSession· sesión del lado del servidor
Problema
HTTP no recuerda quién sos entre un request y otro.
Idea

El servidor guarda los datos del login; el cliente tiene solo un id de sesión aleatorio.

Ejemplo
Cookie sid=8f3a… → en el almacén, 8f3a → Alice.
Coste
El servidor necesita un almacén y una consulta en cada request.
Cuándo usarlo
Una app web normal. Este es el default.
Relaciones

La alternativa es JWT; el id vive en una httpOnly Cookie; la revocación es instantánea.

JWT — el token lleva la verdad

Una pulsera de festival con tu nivel de acceso ya impreso y sellado contra manipulación — el guardia revisa el sello, no una lista de invitados.

Un JWT (JSON Web Token) es un token firmado que guarda el cliente y que contiene la identidad y sus claims; el servidor solo verifica la firma, sin consultar nada. Eso lo hace stateless y fácil de escalar entre servicios — pero difícil de revocar: un token filtrado sigue siendo válido hasta que vence. Por eso se mantienen vidas cortas y se combina con un refresh token. Excelente para APIs y microservicios; exagerado para una app web simple.

headeralgpayloadsub: alice · role · expsignaturesigned by issuer..Clientholds the JWTAPIverify signatureLeaked JWTvalid until expno lookup · statelessso: short expiry + refresh token
JWT = header.payload.signature. La API verifica la firma sin base de datos. Un token filtrado vive hasta exp — de ahí las vidas cortas y el refresh token.
PatternJWT· JSON Web Token
Problema

Muchos servicios, y hacer que cada uno consulte un almacén de sesiones compartido es caro.

Idea
Poner la identidad y los permisos dentro del propio token y firmarlo.
Ejemplo

Payload sub: alice, role: editor, exp: …; cada servicio verifica la firma por su cuenta.

Coste
Difícil de revocar: un token filtrado es válido hasta que vence.
Cuándo usarlo

APIs y microservicios — un JWT de vida corta + un refresh token.

Relaciones
La alternativa a Session; la amenaza es Token Leakage.

httpOnly Cookie — importa dónde lo guardás

Una llave en un cajón con llave frente a una llave pegada con cinta en la puerta de entrada — la misma llave, una seguridad muy distinta.

Un token en el navegador debe ir en una cookie httpOnly (JavaScript no puede leerla), no en localStorage, donde cualquier script inyectado puede robarlo. El lugar donde se guarda es parte de la seguridad: si lo hacés mal, un solo bug de XSS le entrega todas las sesiones a un atacante. Cómo transportás y guardás la credencial es tan importante como la credencial misma.

httpOnly cookieJS can't read itlocalStorageany script can read itInjected scriptXSSsteals token✗ blocked
Un script inyectado (XSS) puede leer localStorage, pero no puede leer una cookie httpOnly.
PracticehttpOnly Cookie· una cookie que JavaScript no puede leer
Problema
Un token en localStorage lo roba cualquier script inyectado.
Idea
Guardar el token en una cookie con el flag httpOnly — JS no la ve.
Ejemplo
Set-Cookie: sid=…; HttpOnly.
Coste
Casi ninguno — es el default correcto en el navegador.
Relaciones

Guarda un id de Session o un JWT; protege contra Token Leakage.

Sesiones: el servidor recuerda, y puede olvidarte al instante. JWT: el token recuerda, y no es fácil quitárselo.

§ 04

Muchas veces no querés manejar la contraseña para nada — querés que los usuarios entren con una cuenta que ya tienen, o que un servicio actúe en nombre de otro. Para eso sirven OAuth2 y OIDC.

OAuth 2.0 — dar acceso sin compartir la contraseña

Una llave de valet que arranca el auto y abre la puerta, pero no el baúl ni la guantera — entregás acceso limitado, no todo tu llavero.

Este es el protocolo OAuth 2.0. Permite que un usuario le dé a tu app acceso limitado a su cuenta en otro servicio — tu app lee su Google Calendar — sin darte nunca su contraseña de Google. El otro servicio le entrega a tu app un access token limitado por un scope («leer el calendario, nada más»). Trata de autorización delegada, no de identidad.

UserAuth serverGoogleYour appclientResource APICalendar1. logs in there + consentsyour app never sees the password2. access token · scope: read calendar3. call the API with the token
El usuario inicia sesión en Google y da su consentimiento. La app recibe un token de alcance acotado y llama a la API con él. Nunca ve la contraseña.
ProtocolOAuth 2.0· autorización delegada
Problema

Una app necesita acceso a la cuenta de alguien en otro lado, pero no puede tener la contraseña.

Idea

El servicio dueño le emite a la app un access token con un scope acotado.

Ejemplo
Tu app lee el Google Calendar del usuario — y solo eso.
Coste
Un protocolo complejo; hacer el baile de tokens a mano es peligroso.
Cuándo usarlo
Actuar en nombre de un usuario en otro servicio.
Relaciones
No dice quién es el usuario — eso es OIDC encima.

OIDC — OAuth2 que además dice quién sos

La llave de valet, ahora con un documento con foto sujeto a ella — no solo «qué abre esta llave», sino «y acá está a quién pertenece».

OAuth2 por sí solo te dice a qué puede acceder una app, no quién es el usuario. OpenID Connect (OIDC) agrega encima una capa fina de identidad — un ID token con claims verificados (esta es Alice, este es su email). Es lo que está detrás de «Entrar con Google» y del single sign-on (SSO). Cuando querés login social o SSO, OIDC es el estándar.

"Log in with Google" · SSOOpenID Connect (OIDC)ID token: WHO the user isOAuth 2.0access token: WHAT the app may reachidentityaccess
OIDC es una capa fina sobre OAuth 2.0: junto al access token («qué se permite») viene un ID token («quién es»).
ProtocolOIDC· OpenID Connect
Problema
OAuth2 da acceso pero no dice quién es el usuario.
Idea
Agregar un ID token con datos de identidad verificados.
Ejemplo

El botón «Entrar con Google»; entrar a herramientas del trabajo con SSO.

Coste
Dependés de un proveedor de identidad externo.
Cuándo usarlo
Login social y single sign-on.
Relaciones

Construido sobre OAuth 2.0; una forma de hacer Authentication.

API Key — la credencial simple para máquinas

Una llave de repuesto que le das a un contratista de confianza — sin nombre, solo «quien la tenga puede entrar».

Una API key es una cadena secreta larga que identifica a un programa, no a una persona — se usa para acceso entre servicios y programático. Simple y efectiva, pero es la credencial: quien la encuentre, entra. Por eso se acota su alcance, se rota, y nunca se sube a git ni se pone en una URL. Sirve para máquinas; no reemplaza una identidad real de usuario.

Service Aa program, not a personAPIchecks key + scopeheader: X-API-Key: sk_…✗ never in git✗ never in a URL↻ scope + rotate
El programa manda la clave en un header; la API verifica la clave y su alcance. Nunca en git, nunca en una URL, rotada con regularidad.
ToolAPI Key· credencial de máquina
Problema
Un programa necesita entrar a una API sin humano y sin login.
Idea
Un secreto largo que identifica al programa.
Ejemplo
Un backend llama a una API de pagos con la clave en un header.
Coste
La clave es el acceso: quien la encuentra, entra.
Cuándo usarlo
De máquina a máquina. No para loguear personas.
Relaciones

Acotala con Least Privilege; la amenaza principal es Token Leakage.

OAuth2 pide prestado el acceso sin la contraseña. OIDC suma «y acá está quién es». Usá el estándar — no inventes tu propio baile de tokens.

§ 05

Una vez que sabés quién es alguien, decidís qué puede tocar. Los modelos van desde roles gruesos hasta políticas finas — y la regla debajo de todos es denegar por defecto.

Deny by Default / Least Privilege — prohibido salvo que se permita

La credencial de un empleado nuevo que no abre nada hasta que se le concede cada puerta de forma explícita — en vez de abrirlo todo hasta que alguien se acuerde de cerrar unas pocas.

La base de la autorización son dos reglas. Deny by default: todo está prohibido salvo que se permita explícitamente. Least privilege: cada identidad recibe el acceso mínimo que necesita, no más. Los sistemas abiertos por defecto filtran — siempre alguien se olvida de restringir el nuevo endpoint. Los sistemas cerrados por defecto fallan de forma segura. Empezá desde el «no» y concedé con intención.

RequestExplicit grant?Allowthe minimum neededDenythe defaultyesno / unknown
Un permiso explícito — dejalo pasar, y solo con el mínimo necesario. Sin permiso, o poco claro — denegar.
PrincipleLeast Privilege· denegar por defecto
Problema

Alguien se olvidó de cerrar el nuevo endpoint — y está abierto para todos.

Idea
«No» por defecto; conceder solo el mínimo necesario.
Ejemplo
Un empleado nuevo recibe acceso solo a su propio proyecto.
Coste
Hay que conceder permisos explícitamente con más frecuencia.
Cuándo usarlo
Siempre — es la base de todo modelo de permisos.
Relaciones
El cimiento de RBAC, ABAC, Ownership Check.

RBAC — permisos por rol

Un teatro donde el tipo de entrada — platea, palco, pase de backstage — decide adónde podés ir, sin nombrarte a vos personalmente.

RBAC (Role-Based Access Control) agrupa permisos en roles — admin, editor, lector — y asigna usuarios a roles. Simple, legible y suficiente para la mayoría de las apps: «los editores pueden publicar, los lectores no». Se vuelve grueso cuando las reglas dependen del contexto o del registro concreto, y ahí entran los siguientes modelos.

usersrolespermissionsAliceadmineverythingBobeditorpublish · editChenviewerread
Usuario → rol → conjunto de permisos. Los permisos van a los roles, no directamente a las personas.
ModelRBAC· Role-Based Access Control
Problema
Dar permisos a cada persona por separado es un caos.
Idea
Los permisos van a los roles; los roles van a los usuarios.
Ejemplo
«Los editores pueden publicar; los lectores solo pueden leer».
Coste
Grueso cuando una regla depende del contexto o del registro concreto.
Cuándo usarlo
La mayoría de las apps.
Relaciones
Más fino — ABAC; siempre sumá un Ownership Check.

ABAC — permisos por política

Una regla en vez de una lista — «los gerentes pueden aprobar gastos de menos de 10k, en horario laboral, desde un dispositivo de la empresa» — evaluada de nuevo cada vez.

ABAC (Attribute-Based Access Control) decide a partir de atributos del usuario, del recurso y del contexto — rol y monto y hora y dispositivo. Mucho más flexible que los roles fijos, y mucho más complejo. La señal para adoptarlo: estás apilando más de un par de condiciones if a medida sobre tus chequeos de rol.

User attributesrole = managerResource attributesexpense: 8kContext14:00 · company laptopPolicyamount < 10k AND …Allow / Denyevaluated every time
Los atributos del usuario, del recurso y del contexto entran en una política que decide de nuevo en cada request.
ModelABAC· Attribute-Based Access Control
Problema

Los permisos dependen no solo del rol sino del monto, la hora, el dispositivo.

Idea

Una regla de política sobre atributos del usuario, del recurso y del contexto.

Ejemplo

Un gerente aprueba un gasto de menos de 10k, en horario laboral, desde una laptop del trabajo.

Coste
Mucho más difícil de escribir, leer y testear.
Cuándo usarlo

Cuando a tus roles ya les pegaste más de un par de if a medida.

Relaciones
Crece a partir de RBAC; se apoya en Least Privilege.

Ownership Check — ¿podés tocar este registro?

Tenés un carnet de biblioteca válido (un rol), pero eso no te deja leer las notas garabateadas en el libro que otro tiene prestado.

El ownership check (autorización a nivel de objeto) es el chequeo que más se olvida: incluso un «editor» válido solo debe editar sus propios documentos, no los de todos. El rol dice «los editores pueden editar»; igual tenés que verificar que este editor es dueño de esta fila. Olvidarlo es el bug de control de acceso más común — cambiás el id en la URL y estás en los datos de otro. Verificá siempre el objeto, no solo el rol.

PUT /docs/42by BobRole checkeditor? ✓Owner checkdoc 42 owner = Bob?Allowonly if both passthe most-missed check
Dos chequeos: el rol («¿es editor?») y la propiedad («¿este doc es suyo?»). Permitir solo si pasan ambos.
PracticeOwnership Check· authZ a nivel de objeto
Problema

El rol permite «editar documentos» — y el usuario edita los de otros.

Idea
Además del rol, verificar que este objeto le pertenece a este usuario.
Ejemplo

Antes de PUT /docs/42, verificar que el dueño del doc 42 es el usuario actual.

Coste
Un chequeo extra en cada acceso a un objeto.
Cuándo usarlo
Siempre, cuando los datos tienen dueño.
Relaciones
Complementa a RBAC/ABAC; sin él — IDOR.

Denegá por defecto. Concedé lo mínimo. Y preguntá siempre no solo «qué rol» sino «de quién es el registro».

§ 06

La auth falla de un puñado de formas bien conocidas — las mismas, una y otra vez, app tras app. Conocerlas es la mitad de la defensa.

Broken Access Control / IDOR — olvidarse de verificar

Un edificio donde la puerta de entrada está vigilada pero todas las puertas internas están sin llave — una vez adentro, podés caminar a cualquier lado.

Broken Access Control es la vulnerabilidad web número uno: un endpoint autentica al usuario pero se olvida de verificar que esté autorizado para lo que pidió. Su forma más común es IDOR (Insecure Direct Object Reference) — cambiar /orders/123 por /orders/124 y ver el pedido de otra persona, porque el servidor nunca verificó la propiedad. Filtraciones de millones de registros se explican justo por esto. Verificá la authZ en cada request, del lado del servidor, contra el objeto real.

Boblogged inGET /orders/123Bob's order ✓GET /orders/124Ann's order!ServerauthN ✓ · owner check ✗fix: WHERE id = 124 AND owner = current_user
Bob entró honestamente, pero el servidor no verifica la propiedad — cambiás el id en la URL y ves el pedido de otro.
Anti-patternBroken Access Control / IDOR· falta de chequeo de permisos
Qué es

El usuario está autenticado, pero no se verifican sus derechos sobre el objeto.

Cómo se ve
/orders/123 → /orders/124 — y aparece el pedido de otro.
Daño
Filtraciones de millones de registros.
Arreglo

authZ en cada request, del lado del servidor: WHERE id = 124 AND owner = current_user.

Relaciones
Se cura con Ownership Check y Least Privilege.

Plaintext / Fast Hash — guardar mal las contraseñas

Guardar las llaves de repuesto de todas las casas de la calle en un frasco de vidrio en el porche.

Guardar contraseñas en texto plano — o con un hash rápido como MD5 — significa que una sola filtración de la base expone a todos, y las contraseñas reutilizadas comprometen también las otras cuentas. Las contraseñas hay que hashearlas de forma lenta e individual (Argon2, bcrypt) para que sea caro crackearlas incluso si las roban. Que el hash sea lento es el objetivo, no un defecto.

MD5 / SHA-1fast hashCracked fastevery leaked user exposedArgon2 / bcryptslow + saltedToo costlyeven when stolenattacker guesses: cheapattacker guesses: expensive
Un hash rápido — intentos baratos, contraseñas crackeadas rápido. Un hash lento con sal — cada intento es caro.
Anti-patternPlaintext / Fast Hash· contraseñas en texto o MD5
Qué es
Contraseñas en la base de datos tal cual o bajo un hash rápido.
Daño

Una filtración expone todas las contraseñas; las contraseñas reutilizadas abren también otras cuentas.

Arreglo
Un hash lento con sal: Argon2 o bcrypt.
Relaciones
La versión correcta es Password Hashing.

Token Leakage — filtrar y confiar en tokens

Escribir el código de la alarma en un papelito pegado en la puerta — la cerradura está bien; vos regalaste el secreto.

Token leakage es la forma en que escapan los tokens y las claves. Se filtran por URLs (que se loguean), el localStorage del navegador (que un script puede leer) y secretos subidos a git. Y un token hay que verificarlo, no confiar en él porque apareció — uno alterado o vencido debe rechazarse. Tratá toda credencial como algo que algún día se va a filtrar: vidas cortas, rotación, y nunca en un lugar que se loguee o se raspe.

Token / API key?token= in URLends up in logslocalStorageread by XSSgit commitpublic foreverServer verifiessignature · expiry · scopeshort-lived · rotatable
Tres caminos clásicos de filtración: URLs en logs, localStorage y git. La defensa: el servidor verifica cada token, las vidas son cortas, las claves rotan.
Anti-patternToken Leakage· tokens y claves filtrados
Qué es
Una credencial termina en un lugar donde se puede leer o encontrar.
Cómo se ve

?token= en una URL, un token en localStorage, una clave en un commit de git.

Daño
Quien encuentre el token, entra.
Arreglo

Verificar firma y vencimiento; vidas cortas, rotación; una httpOnly Cookie en el navegador.

Relaciones
Duele más con JWT y API Key.

Trusting the Client — creerle a lo que dice el navegador

Un negocio que deja que los clientes escriban sus propias etiquetas de precio y nunca las verifica en la caja.

Este es el anti-patrón de confiar en el cliente. Todo lo que manda el cliente — un campo oculto de un formulario, un rol en una cookie, un flag isAdmin=false — se puede falsificar. El navegador, la app, el request: todo está bajo control del usuario. Cada chequeo real debe ocurrir en el servidor, que el usuario no puede editar. El cliente es una sugerencia; el servidor es la autoridad.

CLIENT · user-controlledhidden form fieldcookie: role=adminisAdmin=falseServerre-checks everything itselfsuggestionthe authority
Todo lo que está del lado del cliente lo puede cambiar el usuario. Solo el servidor toma la decisión.
Anti-patternTrusting the Client· chequeos del lado del cliente
Qué es
Decisiones de permisos tomadas a partir de datos que mandó el cliente.
Cómo se ve

Un rol en una cookie, un campo oculto, un flag isAdmin en el request.

Daño
El usuario se otorga permisos a sí mismo.
Arreglo
Cada chequeo en el servidor; el cliente solo sugiere.
Relaciones
Una causa común de Broken Access Control.

Casi toda filtración de auth es una de estas: un chequeo que se salteó, un secreto mal guardado, o un cliente al que se le creyó.

§ 07

La buena auth consiste sobre todo en usar herramientas probadas correctamente y verificar permisos sin descanso — no en ser ingenioso. Así se elige.

Auth Provider — usá una librería o un proveedor

No fabricás tus propios cinturones de seguridad — instalás unos certificados, diseñados por especialistas y probados en choques durante años.

Para casi todo el mundo, lo correcto es no armar la auth por tu cuenta: usá la auth de tu framework, o un auth provider (Auth0, Clerk, Supabase, Cognito y similares) que maneje el hashing, las sesiones, MFA, OAuth y los casos borde que nunca se te ocurrirían. Tu trabajo es integrarlo bien y encargarte de la autorización — la parte que solo vos conocés.

Auth library / providerPassword hashingSessions · tokensMFA · passkeysOAuth · OIDCYour appowns AuthZ: the rulesidentity
El proveedor maneja la identidad: hashes, sesiones, MFA, OAuth. Tu app es dueña de las reglas de acceso.
ToolAuth Provider· librería o servicio de auth
Problema
La auth hecha a mano casi siempre termina con agujeros.
Idea
Entregar la authN a una herramienta probada; quedarte con la authZ.
Ejemplo

Auth0, Clerk, Supabase, Cognito, o la auth incorporada de tu framework.

Coste
Una dependencia de un proveedor; hay que integrarlo bien.
Cuándo usarlo
Casi siempre.
Relaciones
Pone en práctica Don't Roll Your Own Auth.

Match the mechanism to the app — elegí el mecanismo según la app

Una llave de casa, una de auto y una tarjeta de hotel son todas «llaves» — elegís según la puerta, no según la moda.

Sesiones para una app web normal (simples, revocables al instante); JWTs de vida corta más refresh cuando necesitás escala sin estado entre servicios; OIDC para login social y SSO; API keys para máquina a máquina. Sumá MFA en todos lados donde importe, sobre todo en cuentas de admin. Elegí según la forma de tu app, no según lo que suena avanzado.

Normal web appSessionsMany services / APIsShort JWT + refreshSocial login / SSOOIDCMachine to machineAPI keyAdmin / high risk+ MFA
La necesidad a la izquierda, el mecanismo a la derecha. Elegí según la forma de la app.
Antes de lanzar la auth
  • ¿Las contraseñas se hashean de forma lenta (Argon2/bcrypt), y nunca se guardan como texto?
  • ¿Hay MFA disponible, y es obligatorio para los admins?
  • ¿Cada endpoint verifica la authZ — el rol y la propiedad del objeto?
  • ¿Los tokens van en cookies httpOnly, de vida corta, y nunca en URLs ni en git?
  • ¿El chequeo real está en el servidor, sin confiar nunca en roles que manda el cliente?
  • ¿Uso una librería/proveedor probado en vez de un esquema armado a mano?
Señales de que está roto
  • Cambiar un id en la URL muestra los datos de otro.
  • Un permiso vive en una cookie o campo oculto que el cliente puede editar.
  • Contraseñas guardadas en texto plano o MD5.
  • No hay forma de revocar a un usuario logueado salvo esperar al vencimiento.
  • Sin MFA en las cuentas que pueden hacer más daño.
  • Escribiste vos tu propio esquema de tokens o de criptografía.
Señales de que lo hiciste bien
  • La authN y la authZ están separadas, y la authZ se verifica en cada request.
  • Cada acceso a un objeto verifica que este usuario es dueño de esto.
  • Las credenciales están hasheadas, acotadas, de vida corta y rotables.
  • El servidor es la autoridad; nada confía en el cliente.
  • Podés revocar el acceso y ver quién hizo qué en un log.
  • El trabajo pesado está en una librería o proveedor probado, no en tu propio código.

Cómo se conecta todo

El camino de un huésped de hotel: un pasaporte en la recepción, una tarjeta llave en la mano, y cada puerta decide por sí misma si abre.

Los factores de login (contraseña, MFA, passkey, OIDC, API key) llevan a la authN. Su resultado viaja con cada request en una sesión o un JWT, mejor guardado en una cookie httpOnly. En cada request, la authZ decide por roles o por política — y siempre verifica la propiedad del objeto.

Password + hashMFAPasskeyOAuth2 / OIDCAPI keyAuthNwho?SessionJWThttpOnly cookiecarries itAuthZmay?every requestRBAC / ABACOwnership
De izquierda a derecha: factores → authN → sesión o JWT → authZ en cada request → roles/política + propiedad.

Hoja de referencia: los 22 conceptos

Dos preguntas

Authentication (authN)probar la identidad

Probar quién sos. Normalmente una vez por login.

Authorization (authZ)decidir permisos

Decidir qué podés hacer. En cada request.

Don't Roll Your Own Authestándares antes que hacerlo a mano

Usar estándares y librerías probadas, no un esquema propio.

Probar quién sos

Password Hashinghash lento con sal

Guardar un hash lento con sal (Argon2, bcrypt), nunca la contraseña.

MFAmultifactor, 2FA

Un segundo factor: algo que tenés o que sos. La mejora grande más barata.

PasskeysWebAuthn

Un par de claves en el dispositivo, login por firma. Nada que phishear.

Seguir logueado

Stateless HTTPsin memoria entre requests

El servidor olvida los requests — cada uno necesita un pase.

Sessionsesión del lado del servidor

La cookie tiene un id; la verdad está en el servidor. Revocación instantánea. El default.

JWTJSON Web Token

Un token firmado con claims adentro. Sin consulta, pero difícil de revocar.

httpOnly Cookieuna cookie que JS no puede leer

Donde va un token del navegador. XSS no la puede leer.

Acceso delegado

OAuth 2.0autorización delegada

Acceso a la cuenta de alguien con un token de alcance acotado, sin contraseña.

OIDCOpenID Connect

OAuth2 + un ID token: «y acá está quién es». Login social y SSO.

API Keycredencial de máquina

Un secreto para programas. Alcance acotado, rotación, nunca en git ni en una URL.

Permisos

Least Privilegedenegar por defecto

«No» por defecto; conceder solo el mínimo necesario.

RBACRole-Based Access Control

Permisos por rol: admin, editor, lector.

ABACAttribute-Based Access Control

Permisos por una política sobre atributos del usuario, del recurso y del contexto.

Ownership CheckauthZ a nivel de objeto

No solo «qué rol» sino «de quién es el registro».

Cómo se rompe

Broken Access Control / IDORfalta de chequeo de permisos

Se salteó el chequeo: cambiás el id en la URL, ves los datos de otro.

Plaintext / Fast Hashcontraseñas en texto o MD5

Una filtración de la base — todas las contraseñas afuera.

Token Leakagetokens filtrados

Tokens en URLs, localStorage, git. Quien encuentre uno, entra.

Trusting the Clientchequeos del lado del cliente

El cliente es una sugerencia; el servidor es la autoridad.

Hacerlo bien

Auth Providerlibrería o servicio de auth

Entregá la authN a una herramienta probada; quedate con la authZ.

La auth no es donde te ponés ingenioso. Es donde usás los estándares correctamente, denegás por defecto, y nunca, jamás, confiás en el cliente.

Fin del curso exprés · 7 capítulos · 22 conceptos

Lo que viene es profundidad: el OWASP Top 10 y sus hojas de referencia, las especificaciones de OAuth 2.0 y OpenID Connect, y las guías de tu propio auth provider. Pero llevá las dos preguntas a todos lados — ¿quién sos, y qué te está permitido hacer? La primera respondela con una herramienta probada, y la segunda en tu servidor, cada vez.