En la web abierta, un toque de passkey abre el autenticador del sistema e inicia sesión. Dentro de un WebView integrado, ese mismo flujo es el que se rompe: WebAuthn depende de capacidades del navegador y la plataforma que el WebView no ofrece de forma fiable, y las passkeys se vinculan al dominio de la app host, no al tuyo. Un runtime propio del host hace la ponte del autenticador nativo del dispositivo: una API que inicia sesión en cada motor.

Android: el WebView no soporta WebAuthn

Las guías de integración autorizadas son explícitas: el WebView de sistema de Android "no soporta WebAuthn", y FIDO en Android depende de que Google Play Services llegue a la página. Dentro de un WebView integrado, la ceremonia no garantiza un autenticador de plataforma, así que navigator.credentials.create() y .get() pueden lanzar error o no hacer nada en silencio. Incluso donde el motor subyacente podría soportarlo, quien controla el WebView es la app host, no un navegador real, así que la ceremonia completa de passkey que Safari o Chrome ejecutan no está asegurada. La matriz de compatibilidad de Yubico confirma el cuadro: en Android, el soporte FIDO lo entrega Google Play Services, no el componente WebView.

iOS: navigator.credentials falta en WKWebView

En iOS la situación es más aguda. Los informes de desarrolladores y las guías de passkeys muestran que navigator.credentials solo está disponible en SFSafariViewController y ASWebAuthenticationSession, no en el WKWebView que la mayoría de las apps embeben —llamarlo produce "WebAuthn not implemented on iOS". Peor aún, las passkeys dentro de un WKWebView se vinculan a los Associated Domains de la app host, no a tu dominio de relying party: un usuario que llega a tu sitio dentro de Instagram o TikTok no puede usar tus passkeys porque el WebView está vinculado a su dominio, no al tuyo. La UI condicional —el autocompletado de passkey que aparece en el campo de usuario— tampoco se soporta dentro de un WebView.

Qué se rompe cuando las passkeys mueren

  • El inicio sin contraseña termina en callejón sin salida. El inicio rápido y resistente al phishing es el que falla dentro del navegador integrado.
  • El MFA con llave de seguridad falla. El segundo factor WebAuthn y las credenciales detectables nunca arrancan.
  • Los usuarios caen en contraseñas y OTP. Las rutas más lentas y propensas al abandono se vuelven las únicas.
  • Los fallos son invisibles. Una ceremonia que nunca arranca no deja llamada al servidor, así que el analytics muestra un abandono inexplicado, no un error.

La solución del runtime

Un runtime propio del host hace la ponte del autenticador nativo del dispositivo. La página llama a una API uniforme —runtime.createPasskey() y runtime.authenticateWithPasskey()— y el host maneja FIDO2 / Play Services en Android y ASAuthorizationPlatformPublicKeyCredentialProvider en iOS (o abre una ASWebAuthenticationSession para el paso de autenticación). Los Associated Domains que el host controla vinculan la passkey a tu sitio. Una integración, cada motor, un inicio real respaldado por hardware.

DimensiónWebViewRuntime propio del host
API WebAuthnAusente / inconsistentePonte uniforme
Ruta AndroidEl WebView no tiene WebAuthnFIDO2 / Play Services
Ruta iOSWKWebView: navigator.credentials ausenteASAuthorization nativo
Vinculación de dominioApp host, no tu sitioAssociated Domains del host
UI condicionalNo en WebViewNativa
ObservabilidadFallo silencioso en clienteVisible en backend

Una app nativa inicia sesión con passkey en cada dispositivo. Un WebView estándar en casi ninguno. Un runtime da a la página un autenticador — y un inicio real, respaldado por hardware, al final.

Fuentes