Slides
viniciuscampitelli.comGitHub
vcampitelliX Twitter
vcampitelliThis specification defines an API enabling the creation and use of strong, attested, scoped, public key-based credentials by web applications, for the purpose of strongly authenticating usersw3c.github.io/webauthn
The FIDO ("Fast IDentity Online") Alliance is an open industry association launched in February 2013 whose stated mission is to develop and promote authentication standards that "help reduce the world’s over-reliance on passwords"Wikipedia: FIDO Alliance
Ação conjunta da FIDO Alliance com a World Wide Web Consortium (W3C) que criou dois padrões:
WebAuthn
CTAP
86%
das brechas em Basic Web Applications Attacks do Verizon Data Breach Investigations Report envolvem o uso de credenciais roubadas
Qual o primeiro registro
de senhas digitais?
Em 1961, no sistema CTSS do MIT
E o primeiro
vazamento de senhas?
Em 1966, no mesmo sistema
Em questões de segurança:
Em questões de experiência do usuário:
Via Hardware Externo:
Via Plataforma:
Via Software:
The concept of a ceremony is an extension of the concept of a network protocol, with human nodes alongside computer nodes and with communication links that include user interface(s), human-to-human communication, and transfers of physical objects that carry data. What is out-of-band to a protocol is in-band to a ceremony.
— The WebAuthn specification
WebAuthn | Glossário: CerimôniaRegistro
Envolve o processo de Atestação, em que o Servidor pode verificar a autenticidade do Autenticador e verificar suas funcionalidades
Autenticação
Onde ocorre a Asserção, em que o Servidor envia um valor aleatório para o Cliente, que retorna uma assinatura criada pelo Autenticador
Quando o autenticador registra um novo par de chaves para um serviço, ele assina a chave pública com seu certificado de atestação, que é embutido durante a fabricação, sendo específico para aquele modelo de dispositivos
Através do Attestation Statement Format, é possível saber mais informações sobre o tipo do dispositivo que emitiu o par de chaves
Por questões de privacidade, só é recomendado utilizar em situações muito específicas, como por exemplo aplicações governamentais ou de bancos
Attestation and Assertion | MDNPara confirmar que o autenticador é legítimo, há um repositório central com os metadados dos dispositivos reconhecidos em fidoalliance.org/metadata
{
"aaguid": "08987058-cadc-4b81-b6e1-30de50dcbe96",
"metadataStatement": {
"legalHeader": "Submission of this statement and retrieval and use of this statement indicates acceptance of the appropriate agreement located at https://fidoalliance.org/metadata/metadata-legal-terms/.",
"aaguid": "08987058-cadc-4b81-b6e1-30de50dcbe96",
"description": "Windows Hello Hardware Authenticator",
"authenticatorVersion": 1,
"protocolFamily": "fido2",
"schema": 3,
"upv": [{ "major": 1, "minor": 0 }],
"authenticationAlgorithms": [ "rsassa_pkcsv15_sha256_raw" ],
"publicKeyAlgAndEncodings": [ "cose" ],
"attestationTypes": [ "attca" ],
"userVerificationDetails": [
[{ "userVerificationMethod": "eyeprint_internal" }],
[{ "userVerificationMethod": "passcode_internal" }],
[{ "userVerificationMethod": "fingerprint_internal" }],
[{ "userVerificationMethod": "faceprint_internal" }]
],
"keyProtection": [ "hardware" ],
"isKeyRestricted": false,
"matcherProtection": [ "software" ],
"attachmentHint": [ "internal" ],
"tcDisplay": [],
"attestationRootCertificates": [
"MIIF9TCCA92gAwIBAgIQXbYwTgy/J79JuMhpUB5dyzANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE2MDQGA1UEAxMtTWljcm9zb2Z0IFRQTSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDE0MB4XDTE0MTIxMDIxMzExOVoXDTM5MTIxMDIxMzkyOFowgYwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNjA0BgNVBAMTLU1pY3Jvc29mdCBUUE0gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ+n+bnKt/JHIRC/oI/xgkgsYdPzP0gpvduDA2GbRtth+L4WUyoZKGBw7uz5bjjP8Aql4YExyjR3EZQ4LqnZChMpoCofbeDR4MjCE1TGwWghGpS0mM3GtWD9XiME4rE2K0VW3pdN0CLzkYbvZbs2wQTFfE62yNQiDjyHFWAZ4BQH4eWa8wrDMUxIAneUCpU6zCwM+l6Qh4ohX063BHzXlTSTc1fDsiPaKuMMjWjK9vp5UHFPa+dMAWr6OljQZPFIg3aZ4cUfzS9y+n77Hs1NXPBn6E4Db679z4DThIXyoKeZTv1aaWOWl/exsDLGt2mTMTyykVV8uD1eRjYriFpmoRDwJKAEMOfaURarzp7hka9TOElGyD2gOV4Fscr2MxAYCywLmOLzA4VDSYLuKAhPSp7yawET30AvY1HRfMwBxetSqWP2+yZRNYJlHpor5QTuRDgzR+Zej+aWx6rWNYx43kLthozeVJ3QCsD5iEI/OZlmWn5WYf7O8LB/1A7scrYv44FD8ck3Z+hxXpkklAsjJMsHZa9mBqh+VR1AicX4uZG8m16x65ZU2uUpBa3rn8CTNmw17ZHOiuSWJtS9+PrZVA8ljgf4QgA1g6NPOEiLG2fn8Gm+r5Ak+9tqv72KDd2FPBJ7Xx4stYj/WjNPtEUhW4rcLK3ktLfcy6ea7Rocw5y5AgMBAAGjUTBPMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR6jArOL0hiF+KU0a5VwVLscXSkVjAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQsFAAOCAgEAW4ioo1+J9VWC0UntSBXcXRm1ePTVamtsxVy/GpP4EmJd3Ub53JzNBfYdgfUL51CppS3ZY6BoagB+DqoA2GbSL+7sFGHBl5ka6FNelrwsH6VVw4xV/8klIjmqOyfatPYsz0sUdZev+reeiGpKVoXrK6BDnUU27/mgPtem5YKWvHB/soofUrLKzZV3WfGdx9zBr8V0xW6vO3CKaqkqU9y6EsQw34n7eJCbEVVQ8VdFd9iV1pmXwaBAfBwkviPTKEP9Cm+zbFIOLr3V3CL9hJj+gkTUuXWlJJ6wVXEG5i4rIbLAV59UrW4LonP+seqvWMJYUFxu/niF0R3fSGM+NU11DtBVkhRZt1u0kFhZqjDz1dWyfT/N7Hke3WsDqUFsBi+8SEw90rWx2aUkLvKo83oU4Mx4na+2I3l9F2a2VNGk4K7l3a00g51miPiq0Da0jqw30PaLluTMTGY5+RnZVh50JD6nk+Ea3wRkU8aiYFnpIxfKBZ72whmYYa/egj9IKeqpR0vuLebbU0fJBf880K1jWD3Z5SFyJXo057Mv0OPw5mttytE585ZIy5JsaRXlsOoWGRXE3kUT/MKR1UoAgR54c8Bsh+9Dq2wqIK9mRn15zvBDeyHG6+czurLopziOUeWokxZN1syrEdKlhFoPYavm6t+PzIcpdxZwHA+V3jLJPfI="
],
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAACkUlEQVR42uyai3GDMAyGQyegGzACnaCMkBHoBhkhnSAj0A2SDaAT0E6QbEA3cOXW6XEpBtnImMv9utOllxjF/qKHLTdRSm0gdnkAAgACIAACIAACIAACIAgAARAAARAAARAAARBEAFCSJINKkpLuSTtSZbQz76W25zhKkpFWPbtaz6Q75vPuoluuPmqxlZK2yi76s9RznjlpN2K7CrFWaUAHNS0HT0Atw3YpDSjxbdoPuaziG3uk579cvIdeWsbQD7L7NAYoWpKmLy8chueO5reB7KKKrQnQJdDYn9AJZHc5QBT7enINY2hjxrqItsvJWSdxFxKuYlOlWJmE6zPPcsJuN7WFiF7me5DOAws4OyZyG6TOsr/KQziDaJm/mcy2V1V0+T0JeXxqqlrWC9mGGy3O6wwFaI0SdR+EMg9AEAACIAByqViZb+/prgFdN6qb306j3lTWs0BJ76Qjw0ktO+3ad60PQhMrfM9YwqK7lUPe4j+/OR40cDaqJeJ+xo80JsWih1WTBAcb8ysKrb+TfowQKy3v55wbBkk49FJbQusqr4snadL9hEtXC3nO1G1HG6UfxIj5oDnJlHPOVVAerWGmvYQxwc70hiTh7Bidy3/3ZFE6isxf8epNhUCl4n5ftYqWKzMP3IIquaFnquXO0sZ1yn/RWq69SuK6GdPXORfSz4HPnk1bNXO0+UZze5HqKIodNYwnHVVcOUivNcStxj4CGFYhWAWgXgmuF4JzdMhn6wDUm1DpmFyVY7IvQqeTRdod2v2F8lNn/gcpW+rUsOi9mAmFwlSo3Pw9JQ3p+8bhgnAMkPM613BxOBQqc2FEB4SmPQSAAAiAAAiAAAiAAAiAIAAEQAAEQAAEQPco3wIMADOXgFhOTghuAAAAAElFTkSuQmCC",
"authenticatorGetInfo": {
"versions": [ "FIDO_2_0" ],
"aaguid": "08987058cadc4b81b6e130de50dcbe96",
"options": {
"plat": true,
"rk": true,
"up": true
},
"maxCredentialCountInList": 100,
"maxCredentialIdLength": 32,
"transports": [ "internal" ],
"algorithms": [{ "type": "public-key", "alg": -257 }],
"minPINLength": 4,
"firmwareVersion": 19042
}
},
"statusReports": [
{
"status": "FIDO_CERTIFIED_L1",
"effectiveDate": "2020-08-05",
"certificationDescriptor": "Windows Hello Hardware Authenticator",
"certificateNumber": "FIDO20020190418002",
"certificationPolicyVersion": "1.3.6",
"certificationRequirementsVersion": "1.1.0"
},
{
"status": "FIDO_CERTIFIED",
"effectiveDate": "2020-08-05"
}
],
"timeOfLastStatusChange": "2020-08-05"
}
Presença do Usuário
Verificação do Usuário
preferred
, required
ou
discouraged
Criando uma credencial no navegador:
const credential = await navigator.credentials.create({
publicKey: {
challenge: base64url.toBuffer(challengeEnviadoPeloServidor),
rp: {
name: "Vinícius Campitelli",
id: "viniciuscampitelli.com",
},
user: {
id: base64url.toBuffer(user.id),
name: user.name,
displayName: user.displayName,
},
pubKeyCredParams: [{alg: -7, type: "public-key"}], // -7 => ES256
authenticatorSelection: {
authenticatorAttachment: "cross-platform", // ou "platform"
},
timeout: 60000,
attestation: "direct"
}
});
Navigator: credentials property | MDN
Criando uma credencial no navegador:
// console.log(credential);
PublicKeyCredential {
id: "PLdxbMe6vLX3SEDDLQysLV6StR9zLWRss3VH4u6TT192p-snes-IbSajJD_V5G8mZJWLIPxJAlGvwuM",
rawId: ArrayBuffer(59),
response: AuthenticatorAttestationResponse {
clientDataJSON: {
type: "webauthn.create",
challenge: "...", // confira com o challenge anterior
origin: "https://viniciuscampitelli.com"
},
attestationObject: {
authData: {
attestedCredentialData: {
credentialId: …,
credentialPublicKey: …
}
},
fmt: "fido-u2f",
attStmt: {
sig: Uint8Array(70),
x5c: Array(1),
},
},
},
type: "public-key"
}
PublicKeyCredential | MDN
Agora, você deve enviar os dados gerados em credential
para o servidor, que
deve realizar as validações necessárias para iniciar sua sessão
const publicKeyCredentialRequestOptions = {
challenge: Uint8Array.from(
randomStringFromServer, c => c.charCodeAt(0)),
allowCredentials: [{
id: Uint8Array.from(
credentialId, c => c.charCodeAt(0)),
type: 'public-key',
transports: ['usb', 'ble', 'nfc'],
}],
timeout: 60000,
}
const assertion = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions
});
Acesse webauthn.viniciuscampitelli.com ou escaneie o QR Code abaixo:
Se quiser executar localmente:
demo
$ git clone --recursive git@github.com:vcampitelli/slides-webauthn.git
$ cd demo
$ docker compose up -d