openvibers/openvibe.community Commits

A guest's session probe answers 200, not 401 (browser check, WS-Q task 3): GET /auth/me with no session credential at all answers { user: null }, which the shared navbar reads as signed out. It asks on every page view, and the 401 logged a console error on each. A credential that is present but invalid or expired still answers 401. Test: auth.test.js

OP OpenVibers committed 26 Sept 2026 · 564c610325 · 2 files, +14 −2


Changes

ddiff --git a/server/auth/routes.js b/server/auth/routes.js
iindex f2037ba..b253c60 100644
---- a/server/auth/routes.js
++++ b/server/auth/routes.js
@@@ -21,7 +21,7 @@
// swap the assertion for tokens (jwt-bearer grant), set the
// same cookies as the callback
// GET /auth/logout → clear cookies (+ best-effort refresh revoke), hint=guest
--// GET /auth/me → offline-verify ov_token, return profile
++// GET /auth/me → offline-verify ov_token, return profile ({ user: null } for a guest)
// POST /auth/refresh → rotate tokens via refresh_token grant
//
// Cookies (all host-only — openvibe.community has no subdomains):
@@@ -386,7 +386,10 @@ function createAuthRoutes(config, auth) {
// ── GET /auth/me ─────────────────────────────────────────
router.get('/me', async (req, res) => {
const token = extractToken(req);
-- if (!token) return res.status(401).json({ error: 'Not authenticated' });
++ // No credential at all (a guest) is signed out, not an error: the shared navbar asks this on every
++ // page view, and a 401 logged a console error on each (browser check, OpenVibe.Host). A credential
++ // that is present but invalid or expired still answers 401.
++ if (!token) return res.set('Cache-Control', 'private, no-store').json({ user: null });
const claims = await auth.verify(token);
if (!claims) return res.status(401).json({ error: 'Invalid or expired token' });
res.json({ user: claimsToUser(claims), expires_at: claims.exp ? claims.exp * 1000 : null });
ddiff --git a/test/auth.test.js b/test/auth.test.js
iindex bfbc925..b15cc1b 100644
---- a/test/auth.test.js
++++ b/test/auth.test.js
@@@ -78,6 +78,15 @@ const { boot, check, done } = require('./helpers/app');
assert.strictEqual(bad.status, 401);
});
++ await check('/auth/me: a guest is signed out (200 { user: null }), a bad cookie alone is 401', async () => {
++ const guest = await fetch(`${t.base}/auth/me`); // no jar: no cookie, no token at all
++ assert.strictEqual(guest.status, 200);
++ assert.deepStrictEqual(await guest.json(), { user: null });
++ assert.strictEqual(guest.headers.get('cache-control'), 'private, no-store');
++ const bad = await fetch(`${t.base}/auth/me`, { headers: { cookie: 'ov_token=garbage' } });
++ assert.strictEqual(bad.status, 401, 'a present but invalid cookie');
++ });
++
await check('silent login with a valid ov_token skips the Network and 302s to next; non-silent and bad tokens still go', async () => {
assert.ok(t.jar.has('ov_token'), 'precondition: signed in');
const short = await t.get('/auth/login?silent=1&next=/pastes%3Fsort%3Dviews');