fix: la app renueva sola el permiso de paso de Anubis #19

Closed
HBB wants to merge 0 commits from HBB:fix/anubis-clearance-refresh into main
First-time contributor

Las instancias protegidas por Anubis (entre ellas bookwyrm.social) emiten al iniciar sesión la cookie techaro.lol-anubis-auth, que caduca a los pocos días mientras que sessionid dura un año. Cuando caduca, la instancia responde a cada petición con un 307 hacia su reto y llega la página HTML «Making sure you're not a bot!». Gson, configurado como lenient, la lee como una cadena suelta y Retrofit falla con Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $. En la interfaz aparece como un error de la pantalla en la que estuviera el usuario: lo más habitual es «error al cargar los detalles» al abrir un libro desde una estantería, que no apunta a ningún sitio útil.

La sesión sigue siendo válida: lo único caducado es el permiso de paso. Hasta ahora la única salida era cerrar sesión y volver a entrar, y nada en el mensaje lo sugiere.

Ahora los dos clientes HTTP reconocen el reto —tanto la redirección como haber acabado ya dentro de él— y lo resuelven en un WebView invisible. El reto es JavaScript, así que lo ejecuta el propio motor y no hay que reimplementar el protocolo de Anubis; el WebView además comparte el almacén de cookies con el del login, y usa el mismo User-Agent, que es a quien Anubis emite la cookie. La cookie recién emitida se propaga al tarro de OkHttp y a la sesión guardada, y la petición se repite una sola vez. Si no se consigue renovar, se deja pasar la respuesta y falla como antes.

Un Mutex serializa las renovaciones: varias peticiones fallando a la vez provocan una sola resolución, y las demás reutilizan la cookie ya obtenida.

Verificado en un dispositivo real invalidando el permiso de paso sin tocar la sesión: la app obtuvo una cookie nueva por su cuenta en unos segundos, la guardó y siguió funcionando sin volver a iniciar sesión. Se añaden 8 pruebas unitarias sobre el reconocimiento del reto y la lectura de la cookie.

Queda fuera a propósito: no se comprueba al arrancar si el permiso ya ha caducado. La primera petición tras la caducidad paga los pocos segundos de la renovación y se repite sola, así que comprobarlo antes solo ahorraría esa espera una vez por semana.

Las instancias protegidas por Anubis (entre ellas bookwyrm.social) emiten al iniciar sesión la cookie `techaro.lol-anubis-auth`, que caduca a los pocos días mientras que `sessionid` dura un año. Cuando caduca, la instancia responde a cada petición con un 307 hacia su reto y llega la página HTML «Making sure you're not a bot!». Gson, configurado como lenient, la lee como una cadena suelta y Retrofit falla con `Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $`. En la interfaz aparece como un error de la pantalla en la que estuviera el usuario: lo más habitual es «error al cargar los detalles» al abrir un libro desde una estantería, que no apunta a ningún sitio útil. La sesión sigue siendo válida: lo único caducado es el permiso de paso. Hasta ahora la única salida era cerrar sesión y volver a entrar, y nada en el mensaje lo sugiere. Ahora los dos clientes HTTP reconocen el reto —tanto la redirección como haber acabado ya dentro de él— y lo resuelven en un WebView invisible. El reto es JavaScript, así que lo ejecuta el propio motor y no hay que reimplementar el protocolo de Anubis; el WebView además comparte el almacén de cookies con el del login, y usa el mismo User-Agent, que es a quien Anubis emite la cookie. La cookie recién emitida se propaga al tarro de OkHttp y a la sesión guardada, y la petición se repite una sola vez. Si no se consigue renovar, se deja pasar la respuesta y falla como antes. Un `Mutex` serializa las renovaciones: varias peticiones fallando a la vez provocan una sola resolución, y las demás reutilizan la cookie ya obtenida. Verificado en un dispositivo real invalidando el permiso de paso sin tocar la sesión: la app obtuvo una cookie nueva por su cuenta en unos segundos, la guardó y siguió funcionando sin volver a iniciar sesión. Se añaden 8 pruebas unitarias sobre el reconocimiento del reto y la lectura de la cookie. Queda fuera a propósito: no se comprueba al arrancar si el permiso ya ha caducado. La primera petición tras la caducidad paga los pocos segundos de la renovación y se repite sola, así que comprobarlo antes solo ahorraría esa espera una vez por semana.
Las instancias protegidas por Anubis (entre ellas bookwyrm.social) emiten al
iniciar sesión la cookie techaro.lol-anubis-auth, que caduca a los pocos días
mientras que sessionid dura un año. Cuando caducaba, la instancia respondía a
cada petición con un 307 hacia su reto y llegaba la página HTML "Making sure
you're not a bot!". Gson, configurado como lenient, la leía como una cadena
suelta y Retrofit fallaba con «Expected BEGIN_OBJECT but was STRING at line 1
column 1 path $», que aparecía como un error de la pantalla en la que estuviera
el usuario. La sesión seguía siendo válida: lo único caducado era el permiso de
paso, y la única salida era cerrar sesión y volver a entrar.

Ahora los dos clientes HTTP reconocen el reto —tanto la redirección como haber
acabado ya dentro de él— y lo resuelven en un WebView invisible. El reto es
JavaScript, así que lo ejecuta el propio motor y no hay que reimplementar el
protocolo de Anubis; el WebView además comparte el almacén de cookies con el del
login, y usa el mismo User-Agent, que es a quien Anubis emite la cookie. La
cookie recién emitida se propaga al tarro de OkHttp y a la sesión guardada, y la
petición se repite una sola vez. Si no se consigue renovar, se deja pasar la
respuesta y falla como antes.

Un Mutex serializa las renovaciones: varias peticiones fallando a la vez
provocan una sola resolución, y las demás reutilizan la cookie ya obtenida.

Verificado en un dispositivo real invalidando el permiso de paso sin tocar la
sesión: la app obtuvo una cookie nueva por su cuenta en unos segundos, la guardó
y siguió funcionando sin volver a iniciar sesión.
ferlagod closed this pull request 2026-07-28 13:56:58 +00:00

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ferlagod/rocinante_android!19
No description provided.