Verify las prácticas recomendadas de seguridad de la API

La API Vonage Verify es un servicio seguro y fiable para la verificación de números de teléfono y la autenticación multifactorial (MFA). Sin embargo, al igual que cualquier sistema de autenticación, su seguridad general depende en igual medida de cómo se integre con ella tu aplicación de backend. Esta guía explica los aspectos de seguridad más importantes que debes tener en cuenta en tu propia implementación para proteger a tus usuarios.

Nota: Las prácticas recomendadas de esta guía se aplican a todos los canales de la API de Verify, incluidos SMS, voz, WhatsApp, autenticación silenciosa y cualquier otro canal compatible. Aunque algunos ejemplos hacen referencia a los flujos de autenticación silenciosa, los principios subyacentes son universales.

Comprender el modelo de confianza

La API Vonage Verify cumple una función específica: comprueba si un determinado request_id y code El par es correcto. Lo que no puede hacer es determinar si la persona que envía ese par es la misma que inició inicialmente la solicitud de verificación.

Se trata de una distinción fundamental. La API de Verify funciona a nivel de red: no tiene conocimiento alguno de las sesiones de los usuarios, del estado de inicio de sesión ni del contexto de la aplicación. Tu backend se encarga de asociar una solicitud de verificación a un usuario y una sesión concretos. Si tu backend no impone esta restricción, un atacante que consiga un request_id y code par (procedente de una sesión diferente, de una solicitud anterior o al interceptar un flujo del lado del cliente) puede utilizarlo para autenticarse como cualquier número de teléfono que elija.

Por lo tanto, el modelo de seguridad debe entenderse como dos capas complementarias:

  • La responsabilidad de Vonage: Generar un… criptográficamente correcto code, entregarlo de forma segura y verificar el request_id/code par.
  • Tu responsabilidad: Asegurarse de que el request_id y code Las solicitudes enviadas para su verificación son aquellas que tu backend ha iniciado para el usuario autenticado en la sesión actual.

Iniciar siempre la verificación en el lado del servidor

Nunca permitas que tu aplicación cliente (aplicación móvil, navegador o front-end) envíe una solicitud de verificación directamente a la API de Vonage Verify. Todas las llamadas a POST /v2/verify debe realizarse desde tu servidor backend.

Esto garantiza que:

  • Tus credenciales de la API nunca se revelan al cliente.
  • El número de teléfono utilizado en la verificación es el que figura en tu sistema para ese usuario, no un valor facilitado por el cliente en tiempo de ejecución.
  • Tu backend mantiene el control total sobre el ciclo de vida de la verificación.

Patrón incorrecto (no hagas esto):

Client → POST /v2/verify (directly to Vonage, with phone number from user input)

Patrón correcto:

Client → POST /your-backend/start-verification
Backend → POST /v2/verify (to Vonage, using phone number from your database)
Backend stores request_id in session/database
Backend → returns request_id (or nothing) to client

Almacena el «request_id» en el servidor y vincúlalo a la sesión del usuario

Cuando la API de Vonage Verify responde a una solicitud de inicio de verificación, devuelve un request_id. Este valor debe almacenarse de forma segura en tu backend —por ejemplo, en una sesión del lado del servidor o en un registro de la base de datos— y vincularse explícitamente a:

  • El usuario o la cuenta concretos que inician la verificación.
  • Se está verificando el número de teléfono.
  • La sesión o transacción de autenticación actual.

Cuando el cliente envíe posteriormente un código para su verificación, tu backend debe:

  1. Recuperar el request_id desde su propia sesión o base de datos (no desde el cliente).
  2. Llame a POST /v2/verify/{request_id} utilizando únicamente los datos almacenados en el servidor request_id.

Nunca aceptes el request_id como información facilitada por el cliente. Si tu backend toma el request_id a partir de una solicitud del cliente y la transmite directamente a Vonage, un atacante puede proporcionar un request_id de cualquier verificación válida anterior —incluida una correspondiente a un número de teléfono diferente o a otro usuario— y la API devolverá un resultado de validación satisfactorio.

Ejemplo de implementación correcta (Node.js/Express):

// Start verification — called from your app backend only
app.post('/start-verification', async (req, res) => {
  const user = await getUserFromSession(req.session.userId);

  // Phone number comes from YOUR database, not the client request
  const { request_id } = await vonage.verify.start({
    brand: 'YourApp',
    workflow: [{ channel: 'sms', to: user.phoneNumber }]
  });

  // Store request_id server-side, bound to the user session
  req.session.pendingVerification = {
    request_id,
    phoneNumber: user.phoneNumber,
    userId: user.id,
    createdAt: Date.now()
  };

  res.json({ status: 'verification_started' });
});

// Check code — request_id is retrieved from session, never from client
app.post('/check-code', async (req, res) => {
  const { code } = req.body;
  const pending = req.session.pendingVerification;

  if (!pending || !pending.request_id) {
    return res.status(400).json({ error: 'No active verification for this session' });
  }

  const result = await vonage.verify.check(pending.request_id, code);

  if (result.status === 'completed') {
    // Clear the pending verification after success
    delete req.session.pendingVerification;
    res.json({ verified: true });
  } else {
    res.status(401).json({ verified: false });
  }
});

Nunca confíes en los parámetros proporcionados por el cliente a la hora de tomar decisiones de seguridad

Tu aplicación cliente puede enviar datos a tu servidor como parte del proceso de verificación (por ejemplo, un request_id (devuelto al cliente para su uso en una redirección de autenticación silenciosa). Trata todos estos valores como entradas no fiables:

  • No utilizar un archivo proporcionado por el cliente request_id para llamar al punto final de verificación «Verify».
  • No utilizar un número de teléfono facilitado por el cliente para determinar qué usuario se está verificando.
  • No se basan en el estado del lado del cliente para determinar si una verificación se ha realizado con éxito.

La función del cliente se limita a: activar acciones en tu backend (mediante llamadas a la API autenticadas a tu propio servidor) y, en el caso de la autenticación silenciosa, ejecutar el check_url redirigir a través de la red del operador de telefonía móvil. Tu sistema de fondo debe realizar un seguimiento y verificar el resultado de forma independiente.

Implementar la gestión del ciclo de vida de la verificación por sesión

Cada intento de verificación debe limitarse a una única sesión y a un único usuario. Implementa los siguientes controles del ciclo de vida en tu backend:

  • Una solicitud activa por usuario: Antes de iniciar una nueva verificación, comprueba si hay alguna pendiente request_id Ya existe para ese usuario. Cancélala o deja que caduque antes de crear una nueva.
  • Plazo de caducidad breve para las solicitudes pendientes: Si el usuario no completa la verificación en un plazo razonable (por ejemplo, 5 minutos), invalida la sesión almacenada request_id en tu backend y requieren una nueva verificación para poder empezar.
  • Consumo de un solo uso: Una vez que la verificación se haya completado con éxito, elimina inmediatamente el request_id de tu sesión/base de datos. Un request_id Nunca deberían reutilizarse dentro de tu aplicación.
  • Anular tras intentos fallidos: Tras un número configurable de intentos fallidos de envío del código, cancela la solicitud de verificación y pide al usuario que vuelva a empezar.

Aplicar la limitación de tasa a nivel de aplicación

Aunque la API de Vonage Verify incluye protecciones antifraude integradas, también deberías implementar una limitación de rate en tu propia aplicación para reducir el riesgo de ataques de enumeración, inundación o de fuerza bruta:

  • Limitar las solicitudes de verificación por número de teléfono: Limitar el número de solicitudes de verificación que se pueden iniciar para un número de teléfono determinado dentro de un intervalo de tiempo (por ejemplo, no más de 3 solicitudes por hora).
  • Limitar las solicitudes por cuenta de usuario o dirección IP: Evitar que una sola cuenta u origen genere un número excesivo de solicitudes de verificación.

Estos controles son distintos —y complementarios— del sistema de limitación de tráfico y antifraude a nivel de plataforma de Vonage. Para obtener más información sobre las protecciones contra el fraude integradas en Vonage, consulta el Guía del sistema antifraude.

Distinguir entre el registro y la verificación

Hay dos momentos concretos en los que se utiliza la verificación del número de teléfono en las aplicaciones habituales:

  1. Inscripción (registrar un número de teléfono para la autenticación de dos factores): El usuario está añadiendo un nuevo número de teléfono a su cuenta. Esto suele hacerse una sola vez y debe asociarse al registro de la cuenta del usuario autenticado.
  2. Verificación (utilizando la autenticación de dos factores al iniciar sesión): El usuario demuestra que sigue siendo el titular del número de teléfono registrado durante el proceso de registro.

Estos dos flujos requieren controles de seguridad distintos:

Durante inscripción, comprueba que el número de teléfono que se va a registrar no esté ya asociado a otra cuenta y asegúrate de que el usuario haya iniciado sesión antes de añadir el número.

Durante verificación al iniciar sesión, asegúrate de que el número de teléfono utilizado en la solicitud de la API Verify coincida con el que figura en tu base de datos para ese usuario —nunca con el facilitado por el cliente al iniciar sesión—. Un atacante que conozca el número de teléfono de un usuario no debería poder iniciar una solicitud de Verify en su nombre.

Orientaciones adicionales sobre la autenticación silenciosa

La autenticación silenciosa introduce un flujo de redireccionamiento específico de varios pasos en el que el check_url El usuario debe seguir estos pasos desde su dispositivo móvil a través de la red del operador. Se recomienda prestar especial atención a lo siguiente:

  • Guarda el request_id de inmediato tras llamar /v2/verify y antes de enviar cualquier respuesta al cliente. Vincúlala a la sesión del usuario tal y como se describe en el Guarda el request_id Del lado del servidor y vincularlo a la sesión del usuario.
  • No pases el request_id al cliente a menos que sea estrictamente necesario para el flujo de redireccionamiento de la autenticación silenciosa. Si es imprescindible pasarlo (para que el cliente siga el check_url), considéralo un token de corta duración y de un solo uso, y Verifylo con tu sesión en el paso de comprobación del código.
  • Forzar el uso de datos móviles para la redirección: La check_url Debe realizarse a través de la red del operador de telefonía móvil, no a través de Wi-Fi. Si la solicitud se realiza a través de Wi-Fi, se producirá un error y se perderá la prueba de posesión de la tarjeta SIM a nivel del operador. Utiliza el SDK de Vonage para Android o iOS para garantizar el cumplimiento de este requisito al desarrollar aplicaciones móviles nativas. Los SDK también proporcionan comprobaciones de conectividad integradas, gestión de tiempos de espera en las redirecciones (hasta 10 redirecciones, con un tiempo de espera de 5 segundos cada una) y excepciones tipadas que te permiten responder a los fallos con precisión. Consulta el Guía de buenas prácticas para la autenticación silenciosa para obtener más detalles sobre la implementación.
  • Comprueba que hay conexión de datos móviles antes de iniciar la autenticación silenciosa: Si el dispositivo no dispone de una conexión de datos móviles activa, no inicies el paso de «Autenticación silenciosa». En su lugar, pasa directamente al siguiente canal de tu flujo de trabajo (SMS, voz, etc.). Iniciar una solicitud de «Autenticación silenciosa» sin datos móviles provocará un error y añadirá una latencia innecesaria antes de llegar al canal de reserva. El SDK de Vonage lanza un sdk_no_data_connectivity excepción cuando se detecte esta condición durante la ejecución: tu aplicación debería detectarla y actuar de inmediato, en lugar de esperar a que se agote el tiempo de espera predeterminado de 60 segundos.
  • Gestionar las excepciones del SDK y activar rápidamente la conmutación por error del backend: Si el SDK lanza una excepción durante el flujo de autenticación silenciosa (por ejemplo, sdk_no_data_connectivity, sdk_connection_error, o sdk_redirect_error), tu aplicación móvil debe notificarlo inmediatamente a tu servidor. A continuación, tu servidor debería llamar a la POST /v2/verify/{request_id}/next_workflow punto final para pasar la verificación al siguiente canal sin esperar. Si no se realiza ninguna acción, la plataforma agotará automáticamente el tiempo de espera tras 60 segundos y pasará al siguiente flujo de trabajo; sin embargo, activar esto desde tu backend minimiza inmediatamente el tiempo de espera del usuario y mantiene el ciclo de vida de la verificación bajo tu control, en consonancia con el Implementar la gestión del ciclo de vida de la verificación por sesión. No confíes en que el cliente resuelva el problema por sí mismo: la gestión de excepciones debe dar lugar a una transición de estado impulsada por el backend.
  • Confirma siempre el resultado en el lado del servidor: No te fíes de que el cliente informe de que la redirección de la autenticación silenciosa se ha realizado con éxito. Tu servidor debe recibir el estado de verificación definitivo y tomar la decisión de autorización de forma independiente.

Lista de comprobación resumida

Antes de implementar una integración de la API de Verify en el entorno de producción, comprueba lo siguiente:

  • Todas las llamadas a POST /v2/verify se realizan únicamente en el lado del servidor.
  • El número de teléfono que aparece en la solicitud de verificación procede de tu base de datos, no de los datos introducidos por el cliente.
  • El request_id se almacena en el servidor (en la sesión o en la base de datos) y nunca se acepta desde el cliente.
  • El request_id está vinculado al usuario y a la sesión concretos que iniciaron la verificación.
  • Las verificaciones pendientes se anulan una vez transcurrido un plazo determinado.
  • Las verificaciones completadas o fallidas se eliminan de inmediato.
  • Se ha establecido una limitación de tráfico a nivel de aplicación por número de teléfono, por usuario y por dirección IP.
  • Los procesos de registro y verificación de inicio de sesión se gestionan por separado con controles de seguridad distintos.
  • Los flujos de redireccionamiento de la autenticación silenciosa se realizan a través de datos móviles y los resultados se confirman en el servidor.

Recursos relacionados