Paralelo 37 · XauenDevs · Jaén
Fast Identity Online 2.0 El paraguas: el estándar abierto de autenticación sin contraseñas.
La API del W3C que tu página web llama. Es JavaScript: navigator.credentials
Client To Authenticator Protocol Cómo el navegador habla con el aparato que guarda las claves.
Correo: albertthegreat@hotmail.com
(creado en 2004)
Contraseña maestra: P4$$w0rd
"Lleva una mayúscula, un cuatro, dos dólares y un cero. Es criptografía cuántica."
— Motivo de su orgullo
haveibeenpwned.com
El foro de petancas de Albacete guardaba las contraseñas en MD5 plano en un MySQL de 2011.
Treinta años metiéndole parches a algo roto por diseño
Mayúsculas, minúsculas, números, caracteres raros y el grupo sanguíneo.
"Tu contraseña caduca en 90 días"
→ Primavera2026!, Verano2026!
SIM swapping te saluda con la mano.
Fatiga de push: le das a "Aceptar" a las 3 AM solo para que el móvil se calle.
Usuario y servidor comparten el mismo secreto.
Si el servidor cae, caen todos.
El usuario tiene la llave privada en su hardware.
El servidor solo tiene la cerradura (clave pública).
Validando origen de firma:
banc0-santander-phishing.com != banco-santander.com
Firma rechazada matemáticamente.
Inicia sesión con tu rostro o huella. El TPM de tu PC es el hardware criptográfico.
FaceID / TouchID. Las claves se sincronizan de forma encriptada vía iCloud Keychain.
Huella digital en el móvil. Respaldado por Google Password Manager y el chip Titan.
Ya estás usando criptografía asimétrica FIDO2 en tu día a día sin saberlo.
¡Tenemos llaves Nitrokey 3A aquí en la sala para probar en directo!
Express
Angular
@simplewebauthn
import { generateRegistrationOptions, verifyRegistrationResponse } from '@simplewebauthn/server';
// 4 Endpoints mágicos
app.post('/auth/register/begin', ...);
app.post('/auth/register/complete', ...);
app.post('/auth/login/begin', ...);
app.post('/auth/login/complete', ...);
// (Bonus) Curiosear qué se ha guardado
app.get('/auth/users', ...);
// ⚠️ ATENCIÓN: Discrepancias de origen = Error #1
const rpID = 'localhost';
const expectedOrigin = 'http://localhost:4200';
let verification;
try {
verification = await verifyAuthenticationResponse({
response: body,
expectedChallenge,
expectedOrigin,
expectedRPID,
authenticator: {
credentialID: authenticator.credentialID,
credentialPublicKey: authenticator.credentialPublicKey,
counter: authenticator.counter, // 🛡️ El contador interno
},
});
} catch (error) { ... }
// Si a nuestro servidor le llega una petición con
// un número <= que en el login anterior...
// ¡Peligro! Hardware clonado o petición repetida.
Un atacante roba tu llave un rato y en un laboratorio logra extraer la memoria, creando un clon físico exacto.
Ahora existen dos llaves en el mundo con la misma clave privada. Las firmas de ambas son matemáticamente idénticas e indistinguibles.
import { startRegistration, startAuthentication } from '@simplewebauthn/browser';
@Injectable({ providedIn: 'root' })
export class AuthService {
async startRegistration(username: string) {
// 1. Pedimos opciones al backend
const options = await this.api.getRegistrationOptions(username);
// 2. Levanta el cuadro de diálogo nativo del SO
const response = await startRegistration(options);
// 3. Enviamos resultado al backend
await this.api.verifyRegistration(username, response);
}
}
Autenticado en milisegundos sin escribir una sola tecla.
¡Y entra a la primera!
Exactamente igual que con la Nitrokey.
La belleza de los estándares abiertos: a tu código le da igual el fabricante del silicio.
Session Hijacking. Si te roban la cookie ya emitida, FIDO2 no te salva.
El ataque de la llave inglesa de 5 dólares de XKCD.
Poner el dedo sin mirar la pantalla para qué estás dando permiso.

"El futuro no es sin contraseñas...
es con una autenticación que por fin
está a la altura de las personas."
yosoy@antoniotirado.com · @xtoxico · normapro.es
¡Quedan micrófonos abiertos para dudas!
(y veníos a probar las llaves Nitrokey y Pico en directo)