openvibers/openvibe.chat Commits

Chat: Live's legacy token cookie authenticates nothing (C-05) (#72)

OP OpenVibers committed 11 Oct 2026 · cf3b1164d1 · 2 files, +23 −8

This closes compatibility register C-05: Chat reads only the bearer and the Network `ov_token` cookie.

- **What the cookie was:** Live's legacy `token` cookie held the same token as `ov_token`, always set beside it with the same 7-day lifetime, so every browser with one has both. Live stops setting and reading `token` in its own PR.
- **Already gone:** WebSocket `?token=` authentication, the other half of C-05, was removed earlier.
- **This PR:** `extractTokenFrom` loses its `legacyCookie` option and reads only the bearer and `ov_token`, from cookie-parser and from the raw Cookie header (upgrades). `banExemptionToken` uses the same function.
- **Test:** `test/legacy-token-cookie.test.js` checks that a lone `token` cookie authenticates nothing, whether on REST, on the raw header, or for the upgrade ban exemption, and that `ov_token` and the bearer still do.

`ov test`: the covering files and the new test pass.

Changes

ddiff --git a/server/auth/auth.js b/server/auth/auth.js
iindex 28926e3..13702e2 100644
---- a/server/auth/auth.js
++++ b/server/auth/auth.js
@@@ -35,20 +35,19 @@ function apiTokenAllows(req, scopes) {
}
/**
-- * Extract the token and where it came from (Bearer header, the Network `ov_token` cookie, or Live's
-- * legacy `token` cookie). Internal: extractToken returns the token alone.
++ * Extract the token and where it came from: the Bearer header or the Network `ov_token` cookie. Live's legacy
++ * `token` cookie is not read (Live no longer sets it; compatibility register C-05). Internal: extractToken returns
++ * the token alone.
*/
--function extractTokenFrom(req, { legacyCookie = true } = {}) {
++function extractTokenFrom(req) {
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
return { token: authHeader.slice(7), from: 'header' };
}
-- // The Network session cookie is shared with the browser. REST still accepts Live's legacy
-- // 'token' cookie (as Live does); WebSocket upgrades ignore it (legacyCookie: false).
++ // The Network session cookie is shared with the browser.
if (req.cookies) {
if (req.cookies.ov_token) return { token: req.cookies.ov_token, from: 'ov_token_cookie' };
-- if (legacyCookie && req.cookies.token) return { token: req.cookies.token, from: 'legacy_cookie' };
}
// Raw Node/WebSocket upgrade requests do not go through cookie-parser,
@@@ -65,7 +64,6 @@ function extractTokenFrom(req, { legacyCookie = true } = {}) {
try { parsed[key] = decodeURIComponent(value); } catch { parsed[key] = value; }
}
if (parsed.ov_token) return { token: parsed.ov_token, from: 'ov_token_cookie' };
-- if (legacyCookie && parsed.token) return { token: parsed.token, from: 'legacy_cookie' };
}
return { token: null, from: null };
@@@ -97,7 +95,7 @@ function extractWsToken(req) {
* extractWsToken or its first message.
*/
function banExemptionToken(req) {
-- return extractTokenFrom(req, { legacyCookie: false }).token;
++ return extractTokenFrom(req).token;
}
/**
ddiff --git a/test/legacy-token-cookie.test.js b/test/legacy-token-cookie.test.js
nnew file mode 100644
iindex 0000000..2baad13
---- /dev/null
++++ b/test/legacy-token-cookie.test.js
@@@ -0,0 +1,17 @@
++'use strict';
++// Compatibility register C-05: Chat reads the Bearer header and the Network `ov_token` cookie only. Live's legacy
++// `token` cookie (the same token under another name; Live no longer sets it) authenticates nothing, on REST or on
++// the ban-exemption check of a WebSocket upgrade.
++const assert = require('assert');
++const { extractToken, banExemptionToken } = require('../server/auth/auth');
++
++assert.strictEqual(extractToken({ headers: { authorization: 'Bearer bot' } }), 'bot');
++assert.strictEqual(extractToken({ headers: {}, cookies: { ov_token: 'net' } }), 'net');
++assert.strictEqual(extractToken({ headers: { cookie: 'ov_token=net' } }), 'net', 'the raw Cookie header (upgrades)');
++assert.strictEqual(extractToken({ headers: {}, cookies: { token: 'legacy' } }), null, 'a lone legacy cookie authenticates nothing');
++assert.strictEqual(extractToken({ headers: { cookie: 'token=legacy' } }), null, 'nor through the raw Cookie header');
++assert.strictEqual(extractToken({ headers: {}, cookies: { token: 'legacy', ov_token: 'net' } }), 'net');
++assert.strictEqual(banExemptionToken({ headers: { cookie: 'token=legacy' } }), null);
++assert.strictEqual(banExemptionToken({ headers: { cookie: 'ov_token=net' } }), 'net');
++
++console.log('legacy token cookie: Chat reads the bearer and ov_token only — all checks passed');