mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-07-19 09:34:07 +00:00
* docs: PR3 GDPR anonymous identity hardening design spec
* docs: PR3 GDPR anon identity implementation plan
* feat(gdpr): ensureAuthorTokenCookie helper — HttpOnly server-set author token
* feat(gdpr): set HttpOnly author-token cookie from the pad routes
* feat(gdpr): read author token from cookie first, keep message.token fallback
* feat(gdpr): stop generating the author token client-side
* test(gdpr): server sets + reuses the HttpOnly author-token cookie
* fix+test(gdpr): parse token cookie from handshake Cookie header
socket.io handshake doesn't run cookie-parser, so socket.request.cookies
is undefined. Parse the Cookie header directly in handleClientReady so
the HttpOnly token actually resolves. Playwright spec covers HttpOnly
attribute, reload-stability, and context-isolation.
* docs(gdpr): token cookie is now HttpOnly + server-set
* fix(gdpr): close two HttpOnly token bypasses
Qodo review:
- Timeslider still ran the pre-PR3 JS-cookie path: it read
Cookies.get('${cp}token') (which HttpOnly hides), then generated a
fresh plaintext token and overwrote the server's HttpOnly cookie with
it, and sent token in every socket message. Strip the token read/
write entirely from timeslider.ts and from the outgoing message
shape; the server reads the cookie off the socket.io handshake just
like on /p/:pad.
- tokenTransfer re-issued the author cookie without HttpOnly, undoing
the hardening the first time a user transferred a session. Re-set
it as HttpOnly + Secure (on HTTPS) + SameSite=Lax. Also stop
trusting the body-supplied token on POST: read it off req.cookies
server-side so the client never needs JS access to the token.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9014d3a7c4
commit
49bc33f019
13 changed files with 1049 additions and 31 deletions
|
|
@ -366,13 +366,34 @@ exports.handleMessage = async (socket:any, message: ClientVarMessage) => {
|
|||
if (!thisSession) throw new Error('message from an unknown connection');
|
||||
|
||||
if (message.type === 'CLIENT_READY') {
|
||||
// Prefer the HttpOnly author-token cookie over the in-message token (GDPR
|
||||
// PR3). Legacy clients (pre-PR3 browsers or API consumers) still send
|
||||
// `token` in the CLIENT_READY payload — honour it one more release, warn
|
||||
// once so the migration is visible in logs. The socket.io handshake does
|
||||
// not run cookie-parser, so pull the cookie directly from the Cookie
|
||||
// header.
|
||||
const cookiePrefix = settings.cookie?.prefix || '';
|
||||
const cookieHeader: string = socket.request?.headers?.cookie || '';
|
||||
const cookieName = `${cookiePrefix}token`;
|
||||
const cookieMatch = cookieHeader.split(/;\s*/).find(
|
||||
(c) => c.split('=')[0] === cookieName);
|
||||
const cookieToken = cookieMatch ? decodeURIComponent(cookieMatch.split('=').slice(1).join('=')) : null;
|
||||
const legacyToken = typeof message.token === 'string' ? message.token : null;
|
||||
const resolvedToken = cookieToken || legacyToken;
|
||||
if (!cookieToken && legacyToken && !thisSession.legacyTokenWarned) {
|
||||
messageLogger.warn(
|
||||
'client sent author token via CLIENT_READY message; cookie migration ' +
|
||||
'will take effect on next HTTP response. ' +
|
||||
'See docs/superpowers/specs/2026-04-19-gdpr-pr3-anon-identity-design.md');
|
||||
thisSession.legacyTokenWarned = true;
|
||||
}
|
||||
// Remember this information since we won't have the cookie in further socket.io messages. This
|
||||
// information will be used to check if the sessionId of this connection is still valid since it
|
||||
// could have been deleted by the API.
|
||||
thisSession.auth = {
|
||||
sessionID: message.sessionID,
|
||||
padID: message.padId,
|
||||
token: message.token,
|
||||
token: resolvedToken,
|
||||
};
|
||||
|
||||
// Pad does not exist, so we need to sanitize the id
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue