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.
Qué ocurre sin un contexto
Sección titulada «Qué ocurre sin un contexto»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.
Inicio de sesión con contraseña
Sección titulada «Inicio de sesión con contraseña»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»- 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 contakeActionContext(), que espera como máximo su tope. En los dispositivos táctiles,pointerdownllega justo antes del clic, así que el clic puede esperar hastaSUBMIT_WAIT_MS. - Envíe el contexto (o
nullcon 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 sustatede OAuth y su verificador PKCE (o la cookie cifrada,HttpOnlyy de corta duración que su framework usa para ellos), vinculado a esestate. - Inicie la redirección al proveedor como lo hace hoy. No llame antes a
close(): cerrar puede invalidar el contexto no consumido. - 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
expiresAttodavía deja su margen; de lo contrario, envíenully registreEXPIRED_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»- 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. - Esa página captura y obtiene el contexto con
takeActionContext(), que espera como máximo su tope, y después lo envía (onullcon su motivo) a su backend. - 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.
- 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()Reglas del backend para ambos patrones
Sección titulada «Reglas del backend para ambos patrones»- Envíe exactamente una evaluación de inicio de sesión (etiqueta
login;LOGINen v1) por cada inicio de sesión completado, con contraseña o con proveedor, con los mismos seudónimossubject_refyaccount_refpara 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 alsubject_refcon el que se envió por primera vez: un inicio de sesión con proveedor que asigna la misma cuenta a otra persona devuelve409 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
expiresAtdeje su margen; de lo contrario, envíenull. Ante400 event-context-invalid, evalúe una vez más como una operación nueva connull(wrapper fail-open). - Registre, para cada evaluación, si llevaba un token y, cuando no, el
contextFailuredel 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.
Compruebe que llega la evidencia del SDK
Sección titulada «Compruebe que llega la evidencia del SDK»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:
- 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
OPTIONSal dominio de captura se responde con204; un400ahí significa que la instrumentación de la página añadió un encabezado de solicitud (encabezados de rastreo). - 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_EXCEEDEDen redes lentas), no un único código fijo en cada inicio de sesión con proveedor. - La respuesta de la evaluación. Con evidencia del navegador,
device_intelligence_snapshot_idysdk_versionno sonnull,BOT_AUTOMATIONesDETECTEDoNOT_DETECTED,evidence_coveragees mayor que0ylimitation_codesno contieneCOLLECTOR_NOT_LOADED.data_freshness.maximum_required_age_msmuestra la ventana de evidencia de su aplicación. - 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.
- 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.