EN · DE · RU · FR · ES

#2762: webauthn.js

projectforge-webapp/src/utilities/webauthn.js Utilidades de conversión de credenciales WebAuthn · projectforge-webapp/src/utilities/webauthn-json.js 86 líneas · 80 código · 1 comentario · 5 en blanco
La capa de conversión de credenciales WebAuthn (FIDO2/U2F) desarrollada a medida por ProjectForge. Este módulo proporciona el puente de codificación/decodificación entre la API nativa PublicKeyCredential del navegador (que utiliza valores binarios ArrayBuffer) y la API JSON del lado del servidor (que espera cadenas codificadas en base64url). Tres funciones principales manejan distintas etapas del ciclo de vida: convertPublicKeyCredentialRequestOptions decodifica el desafío proporcionado por el servidor y los ID de usuario al formato ArrayBuffer para la API del navegador; convertRegisterCredential empaqueta una credencial recién creada en la forma JSON que el servidor espera para el registro; convertAuthenticateCredential hace lo mismo para las aserciones de autenticación.

Arquitectura

Funciones auxiliares internas

decodeBase64url — Convierte una cadena base64 segura para URL en un ArrayBuffer. Utiliza el puente atob: primero reconstruye el base64 estándar (reemplazando -+, _/, añadiendo relleno), luego decodifica mediante atob y copia el charCode de cada carácter en un Uint8Array respaldado por un nuevo ArrayBuffer.

bufferToBase64url — La operación inversa: itera sobre una vista Uint8Array, construye una cadena binaria mediante String.fromCharCode, codifica con btoa y luego convierte al formato seguro para URL.

convertCredentials — Función auxiliar extraída durante una refactorización que convierte un array de objetos descriptores de credenciales (con campos rawId e id) de cadenas base64url a ArrayBuffer, tanto para las listas allowCredentials como excludeCredentials.

Registro vs. Autenticación

Registro (convertRegisterCredential) empaqueta: rawId, clientDataJSON, attestationObject y transports de la respuesta de credencial, más metadatos de la solicitud (requestId, challenge, sessionToken). Autenticación (convertAuthenticateCredential) empaqueta: authenticatorData, signature, userHandle en lugar de los campos de atestación. Ambas envuelven el resultado en la misma estructura de sobre que esperan los endpoints REST del servidor.

Evolución del enfoque

Este archivo representa la implementación de WebAuthn en producción, distinta de la librería webauthn-json.js incorporada. El equipo comenzó con una decodificación base64 manual mediante manipulación de bits (usando una tabla de búsqueda inversa), luego refactorizó al enfoque más simple basado en atob/btoa. Las funciones separadas de registro/autenticación y la función auxiliar convertCredentials se extrajeron de una conversión de credenciales inicialmente monolítica.

Historial de Git

CommitQué cambió
9c86a74e5Se extrajeron los bucles de conversión inline de allowCredentials/excludeCredentials en una función auxiliar compartida convertCredentials(dest, src). Se redujo la duplicación: ambas listas de credenciales ahora llaman a la misma función auxiliar. También se añadió aquí la conversión de excludeCredentials de la función original convertPublicKeyCredentialRequestOptions, completando el manejo de listas de credenciales.
c6ba8d11cDos adiciones significativas: (1) Se añadió la conversión de listas de credenciales dentro de convertPublicKeyCredentialRequestOptions para manejar arrays allowCredentials — el rawId y el id de cada credencial se decodifican de base64url; (2) Se añadió convertAuthenticateCredential como función dedicada para aserciones de autenticación (anteriormente, registro y autenticación eran manejados por una única función convertCredential). La función antigua fue renombrada a convertRegisterCredential para clarificar su propósito.
4c5cc21e9Se refactorizó convertCredential para que devuelva el objeto resultado directamente en lugar de asignarlo a una variable result intermedia, y se añadió el campo challenge al sobre de salida — una corrección crítica ya que el servidor necesita el desafío original para verificar la credencial.
4a70ca329Se corrigió la extracción de campos de la respuesta de credencial usando desestructuración: const { response } = credential; — el código anterior leía incorrectamente clientDataJSON, attestationObject y transports del objeto credential de nivel superior en lugar de credential.response, lo que habría producido valores undefined. Esta fue una corrección de error crítica.
ddccb2e68Refactorización importante del enfoque de codificación/decodificación base64url. El decodificador manual original de manipulación de bits (usando una tabla de búsqueda inversa y desplazamiento de bits manual) fue reemplazado por el enfoque más simple basado en atob/btoa. También se convirtió convertPublicKeyCredentialRequestOptions de basado en mutación (modificando la entrada in situ) a basado en copia (usando JSON.parse(JSON.stringify(...)) para clonar profundamente primero). Se añadió la primera versión de convertCredential para la codificación de registro.
05c32c27fCommit inicial de WebAuthn: se creó el decodificador base64url y la primera versión de convertPublicKeyCredentialRequestOptions. Se usó el nombre de parámetro registerData y se accedió a challenge/user.id mediante registerData.publicKey.challenge, reflejando una forma de API anterior que luego fue simplificada.