openvibers/openvibe.watch Commits
Sign-in no longer hangs on phones (no Clear-Site-Data on the callback or sign-out) (#117)
Changes
@@@ -174,8 +174,8 @@ function createSso({ config, keys, sessions, fetchImpl = globalThis.fetch, now =avatarUrl: claims.avatar_url, profileColor: claims.profile_color,});setSessionCookie(res, session);-- // Whatever this browser kept of the site was drawn for a guest: drop it.-- res.set('Clear-Site-Data', '"cache"');++ // No Clear-Site-Data here or on sign-out: Chrome holds such an answer (and the cookies it sets) until the++ // cache is cleared, which on phones left people on the account chooser with no session (2026-10-28).return res.redirect(next);} catch (err) {log.warn(`[sso] sign-in refused: ${(err && err.code) || (err && err.message) || err}`);@@@ -206,7 +206,6 @@ function createSso({ config, keys, sessions, fetchImpl = globalThis.fetch, now =const token = req.cookies && req.cookies[SESSION_COOKIE];if (token) { try { await sessions.revoke(token); } catch { /* the cookie is cleared anyway */ } }clearSessionCookie(res);-- res.set('Clear-Site-Data', '"cache"');return res.redirect(303, sanitizeNext(req.query.next, config));});@@@ -87,7 +87,7 @@ t('sign-in with the stand-in Network: PKCE, a session, and /auth/me', async () =// Sign-out revokes the session: the same cookie no longer reads a person.const bye = await svc.get('/auth/logout', { cookie: out.cookie, method: 'POST', form: {} });assert.strictEqual(bye.status, 303);-- assert.strictEqual(bye.headers.get('clear-site-data'), '"cache"', 'what the browser kept of the site is dropped');++ assert.strictEqual(bye.headers.get('clear-site-data'), null, 'no Clear-Site-Data: Chrome holds such an answer until its cache is cleared (phones hung, 2026-10-28)');const after = await svc.get('/watches', { cookie: out.cookie });assert.match(after.text, /Sign in with OpenVibe/);
@@ -174,8 +174,8 @@ function createSso({ config, keys, sessions, fetchImpl = globalThis.fetch, now =
@@ -174,8 +174,8 @@ function createSso({ config, keys, sessions, fetchImpl = globalThis.fetch, now =
avatarUrl: claims.avatar_url, profileColor: claims.profile_color,
avatarUrl: claims.avatar_url, profileColor: claims.profile_color,
});
});
setSessionCookie(res, session);
setSessionCookie(res, session);
- // Whatever this browser kept of the site was drawn for a guest: drop it.
- res.set('Clear-Site-Data', '"cache"');
+ // No Clear-Site-Data here or on sign-out: Chrome holds such an answer (and the cookies it sets) until the
+ // cache is cleared, which on phones left people on the account chooser with no session (2026-10-28).
return res.redirect(next);
return res.redirect(next);
} catch (err) {
} catch (err) {
log.warn(`[sso] sign-in refused: ${(err && err.code) || (err && err.message) || err}`);
log.warn(`[sso] sign-in refused: ${(err && err.code) || (err && err.message) || err}`);
@@ -206,7 +206,6 @@ function createSso({ config, keys, sessions, fetchImpl = globalThis.fetch, now =
@@ -206,7 +206,6 @@ function createSso({ config, keys, sessions, fetchImpl = globalThis.fetch, now =
const token = req.cookies && req.cookies[SESSION_COOKIE];
const token = req.cookies && req.cookies[SESSION_COOKIE];
if (token) { try { await sessions.revoke(token); } catch { /* the cookie is cleared anyway */ } }
if (token) { try { await sessions.revoke(token); } catch { /* the cookie is cleared anyway */ } }
clearSessionCookie(res);
clearSessionCookie(res);
- res.set('Clear-Site-Data', '"cache"');
return res.redirect(303, sanitizeNext(req.query.next, config));
return res.redirect(303, sanitizeNext(req.query.next, config));
});
});
@@ -87,7 +87,7 @@ t('sign-in with the stand-in Network: PKCE, a session, and /auth/me', async () =
@@ -87,7 +87,7 @@ t('sign-in with the stand-in Network: PKCE, a session, and /auth/me', async () =
// Sign-out revokes the session: the same cookie no longer reads a person.
// Sign-out revokes the session: the same cookie no longer reads a person.
const bye = await svc.get('/auth/logout', { cookie: out.cookie, method: 'POST', form: {} });
const bye = await svc.get('/auth/logout', { cookie: out.cookie, method: 'POST', form: {} });
assert.strictEqual(bye.status, 303);
assert.strictEqual(bye.status, 303);
- assert.strictEqual(bye.headers.get('clear-site-data'), '"cache"', 'what the browser kept of the site is dropped');
+ assert.strictEqual(bye.headers.get('clear-site-data'), null, 'no Clear-Site-Data: Chrome holds such an answer until its cache is cleared (phones hung, 2026-10-28)');
const after = await svc.get('/watches', { cookie: out.cookie });
const after = await svc.get('/watches', { cookie: out.cookie });
assert.match(after.text, /Sign in with OpenVibe/);
assert.match(after.text, /Sign in with OpenVibe/);