Ir al contenido
En producción, en modo shadow: FingerTrackID recomienda, su sistema decide.Estado →

Inicio de sesión con Google, OAuth y otras redirecciones

Un inicio de sesión con contraseña permanece en su página hasta el envío, así que la receta de captura lo cubre. Un inicio de sesión a través de Google o de otro proveedor OAuth/OIDC normalmente no: el navegador sale de su página hacia el proveedor y vuelve a un callback en su servidor. Esta página muestra cómo conservar la evidencia del navegador en ese flujo y cómo verificarla.

Por qué una redirección pierde el contexto

Sección titulada «Por qué una redirección pierde el contexto»

El SDK conserva su sesión, sus observaciones, los handles de los eventos y el token solo en la memoria de la página. Nunca los escribe en el almacenamiento, y no debe hacerlo: el token es una credencial de un solo uso para un evento de negocio. Una navegación de página completa lo descarta todo. Si la página inicia el SDK y después navega hacia el proveedor:

  • la primera solicitud del SDK puede quedar cortada por la navegación, de modo que ninguna captura llega a FingerTrackID;
  • incluso una captura completada es inútil una vez perdido su handle, porque solo esa página podría haber pedido el contexto del evento;
  • su callback se ejecuta en el servidor, donde no hay SDK, así que el inicio de sesión se evalúa con event_context_token: null.

Nada falla de forma visible: el inicio de sesión funciona y la evaluación se almacena. Lo que falta es la evidencia del navegador.

Su backend sigue enviando la evaluación del inicio de sesión (etiqueta login; LOGIN en v1) con event_context_token: null, que el esquema de la solicitud acepta como “no se aportó ninguna captura”. La evaluación almacenada tiene entonces:

Campo Sin evidencia del navegador
assessment_status INCONCLUSIVE
trust_score null (sin puntuación; ni 0 ni 100)
device_intelligence_snapshot_id, device_intelligence_snapshot_version, sdk_version, device_id null
signals Los 13 indicadores en NOT_EVALUATED
limitation_codes Por ejemplo COLLECTOR_NOT_LOADED
evidence_coverage 0

device_intelligence_snapshot_id: null es la forma fiable de saber, solo a partir de la respuesta, que no se adjuntó evidencia del navegador.

Use las recetas de la página de captura, para un POST de formulario clásico o para una aplicación de una sola página. El contexto va con la solicitud que su backend evalúa: el formulario de contraseña, o el formulario del código MFA cuando su inicio de sesión lo pide. El backend evalúa después de haber verificado la contraseña y cualquier MFA, usando el token solo mientras su expiresAt deje tiempo suficiente (wrapper fail-open).

Inicios de sesión con redirección: dos patrones

Sección titulada «Inicios de sesión con redirección: dos patrones»

Ambos patrones producen un contexto para el inicio de sesión y lo llevan hasta su backend sin ponerlo nunca en una URL, en el state de OAuth ni en el almacenamiento del navegador. Elija según cuánto tiempo pasan los usuarios en el proveedor en comparación con la ventana de evidencia de su aplicación:

Patrón Captura Conviene cuando Costo
A. Antes de la redirección En la primera intención hacia “Continuar con Google”, y se toma en su clic El viaje de ida y vuelta al proveedor cabe holgadamente dentro de la ventana Hasta su tope antes de la redirección
B. Después del callback En una página intermedia suya, antes de terminar la sesión Los usuarios pueden pasar mucho tiempo en el proveedor (elección de cuenta, contraseña, 2FA del proveedor), o la ventana es de 60 segundos Una página adicional, que espera hasta su tope

Con una ventana de 60 segundos, el tiempo que se pasa en el proveedor cuenta en contra del token, así que el patrón B es la opción más fiable. Con 300 segundos, el patrón A cubre la mayoría de los viajes de ida y vuelta al proveedor. Los inicios de sesión con ventana emergente, One Tap y FedCM no salen de la página, y puede que el usuario nunca toque un botón suyo: llame a prepareNextAction() en el primer focusin o pointerdown del formulario de inicio de sesión o del contenedor que aloja el inicio de sesión, en el pointerenter, focus o pointerdown del botón de inicio de sesión, o cuando su código muestre el aviso de One Tap o FedCM tras una acción del usuario. Nunca al cargar la página: no prepare cuando One Tap o FedCM se muestran por sí solos al cargar la página, porque un aviso mostrado en cada carga abriría una captura que cuenta como uso (la unidad de uso) en cada carga, también para los visitantes que nunca inician sesión. Tome el contexto con takeActionContext() cuando llegue la credencial y envíelo con la solicitud que envía la credencial, como en un inicio de sesión con contraseña. Sin una preparación previa, el callback de la credencial espera hasta su tope mientras se inicia la captura, y a menudo llega a su backend con null.

Patrón A: tome el contexto en el clic, antes de redirigir

Sección titulada «Patrón A: tome el contexto en el clic, antes de redirigir»
  1. Llame a prepareNextAction() de la receta de captura en la primera intención hacia el botón de Google (pointerenter, focus, pointerdown), nunca al cargar la página, para que el contexto pueda estar listo en el clic. En el clic, tómelo con takeActionContext(), que espera como máximo su tope. En los dispositivos táctiles, pointerdown llega justo antes del clic, así que el clic puede esperar hasta SUBMIT_WAIT_MS.
  2. Envíe el contexto (o null con su motivo) a su backend en una solicitud del mismo origen y protegida contra CSRF. El backend lo conserva en el servidor, en la sesión previa al inicio de sesión que ya guarda su state de OAuth y su verificador PKCE (o la cookie cifrada, HttpOnly y de corta duración que su framework usa para ellos), vinculado a ese state.
  3. Inicie la redirección al proveedor como lo hace hoy. No llame antes a close(): cerrar puede invalidar el contexto no consumido.
  4. En el callback, después de verificar la respuesta del proveedor y cualquier MFA propio, tome el contexto almacenado y elimínelo (un solo uso). Envíe el token si su expiresAt todavía deja su margen; de lo contrario, envíe null y registre EXPIRED_BEFORE_CALLBACK.

Si su biblioteca de autenticación inicia el flujo del proveedor desde el navegador (una llamada del estilo de signIn('google')), mantenga esa llamada como último paso y envíe el contexto en su propia solicitud justo antes, como arriba. La página se descarta en la redirección sin close(); su sesión del SDK ocupa una de sus plazas de sesión concurrente hasta que se agoten sus 30 minutos.

// prepareNextAction and takeActionContext come from the collection recipe; csrfToken and
// startGoogleSignIn stand for your existing CSRF token and provider redirect.
// The first intent prepares the context; a page load alone opens no session and bills nothing.
for (const intent of ['pointerenter', 'focus', 'pointerdown'])
googleButton.addEventListener(intent, () => prepareNextAction())
googleButton.addEventListener('click', async (event) => {
event.preventDefault()
googleButton.disabled = true // Show progress; the wait is bounded by SUBMIT_WAIT_MS.
const { context, failure } = await takeActionContext()
try {
// Your endpoint: stores { context, failure } server-side with the OAuth state.
await fetch('/auth/login-context', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken },
body: JSON.stringify({ eventContext: context, contextFailure: failure }),
})
} catch {
// The login must not depend on this request; the callback then assesses with null.
}
startGoogleSignIn() // Your existing redirect to the provider, unchanged.
})

Patrón B: capture en una página posterior al callback

Sección titulada «Patrón B: capture en una página posterior al callback»
  1. El callback verifica la respuesta del proveedor, pero todavía no termina la sesión. Almacena en el servidor un inicio de sesión pendiente de corta duración (vinculado al navegador, por ejemplo con la misma sesión previa al inicio de sesión) y redirige a una página intermedia suya, como /login/continue, en uno de los orígenes permitidos de la aplicación.
  2. Esa página captura y obtiene el contexto con takeActionContext(), que espera como máximo su tope, y después lo envía (o null con su motivo) a su backend.
  3. El backend verifica el inicio de sesión pendiente, ejecuta cualquier MFA propio, evalúa el inicio de sesión, después termina la sesión como lo hace hoy y responde indicando adónde ir a continuación.
  4. La página llama a close() después de esa respuesta y continúa la navegación.

La página intermedia siempre debe terminar el inicio de sesión: mantenga la espera acotada y dele un formulario <noscript> (o un simple botón “Continuar”) que envíe sin contexto. Si el usuario nunca llega a /login/finish, el inicio de sesión pendiente caduca como cualquier inicio de sesión abandonado. Cuando su aplicación pide su propio MFA después del proveedor, esa página de MFA ya es la página posterior al callback: use la receta de inicio de sesión con contraseña en su formulario y omita la página adicional.

// On /login/continue. takeActionContext and closeSdk come from the collection recipe.
async function finishLogin() {
const { context, failure } = await takeActionContext()
const response = await fetch('/login/finish', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken },
body: JSON.stringify({ eventContext: context, contextFailure: failure }),
})
const { next } = await response.json() // Your own response shape.
await closeSdk() // The backend has answered: free the session slot (at most 1500 ms).
window.location.assign(next)
}
finishLogin()
  • Envíe exactamente una evaluación de inicio de sesión (etiqueta login; LOGIN en v1) por cada inicio de sesión completado, con contraseña o con proveedor, con los mismos seudónimos subject_ref y account_ref para la misma persona y la misma cuenta. Nunca envíe el identificador del sujeto del proveedor ni el correo electrónico. Una cuenta permanece vinculada al subject_ref con el que se envió por primera vez: un inicio de sesión con proveedor que asigna la misma cuenta a otra persona devuelve 409 binding-conflict (referencias de persona y de cuenta).
  • Acepte el contexto solo de la solicitud que su propia página envió para este inicio de sesión; elimine un contexto almacenado tras su primer uso y nunca lo use para otro inicio de sesión.
  • Envíe el token solo mientras expiresAt deje su margen; de lo contrario, envíe null. Ante 400 event-context-invalid, evalúe una vez más como una operación nueva con null (wrapper fail-open).
  • Registre, para cada evaluación, si llevaba un token y, cuando no, el contextFailure del navegador o su propio motivo (NO_CONTEXT_RECEIVED, EXPIRED_BEFORE_CALLBACK). Nunca registre el token.
  • El inicio de sesión en sí nunca espera a FingerTrackID más allá de su propio presupuesto, y nunca falla por su causa.

Realice estas comprobaciones en cada origen permitido que use, para un inicio de sesión con contraseña y para cada proveedor, antes de activar la integración para todos:

  1. Panel de red del navegador. Las solicitudes a su dominio de captura se completan con una respuesta antes de que la página navegue a otra parte. Una solicitud mostrada como cancelada justo antes de una redirección significa que la captura se ejecutó demasiado tarde o que la redirección no esperó. Cada solicitud OPTIONS al dominio de captura se responde con 204; un 400 ahí significa que la instrumentación de la página añadió un encabezado de solicitud (encabezados de rastreo).
  2. Los registros de su backend. La mayoría de los inicios de sesión llevan un token. Los inicios de sesión sin token tienen un motivo, y los motivos son los esperados (por ejemplo WAIT_EXCEEDED en redes lentas), no un único código fijo en cada inicio de sesión con proveedor.
  3. La respuesta de la evaluación. Con evidencia del navegador, device_intelligence_snapshot_id y sdk_version no son null, BOT_AUTOMATION es DETECTED o NOT_DETECTED, evidence_coverage es mayor que 0 y limitation_codes no contiene COLLECTOR_NOT_LOADED. data_freshness.maximum_required_age_ms muestra la ventana de evidencia de su aplicación.
  4. Consola, Integração e saúde. Última coleta muestra una hora reciente en lugar de nenhuma coleta na janela; en Da coleta à avaliação, Coletas aceitas crece con sus inicios de sesión y Correlacionadas (evaluaciones que encontraron su captura del navegador) se mantiene cerca de Avaliações; Correlação navegador → backend muestra esa proporción. Estas cifras cubren las últimas 24 horas registradas y no son en tiempo real.
  5. Consola, Acessos. Abra un inicio de sesión con proveedor: Cobertura de evidência es mayor que cero, el indicador Automação (robô) muestra Detectado o Não detectado en lugar de Não avaliado, y las limitaciones no incluyen Coletor não carregado.

Si todos los inicios de sesión con proveedor fallan estas comprobaciones mientras los inicios de sesión con contraseña las superan, la redirección está descartando el contexto: aplique el patrón A o B. Consulte también la lista de verificación de integración.