openvibers/openvibe.media Commits
Sign-out everywhere deliveries verify: POST /internal/events is mounted before express.json(), which consumed the raw body its signature is over (every delivery answered 401). The test holds the order
Changes
@@@ -62,6 +62,9 @@ if (drill.enabled) app.use(drill.readOnly);// Object API v2 content uploads read the raw request body, so they sit ahead of the body parsers.app.put('/api/v2/:app/objects/:id/content', ...require('./objects/routes').contentHandlers);app.put('/api/v2/:app/objects/:id/multipart/:uploadId/parts/:n', ...require('./objects/routes').partHandlers);++// Network's sign-out-everywhere cutoffs (server/revocations.js): signed, loopback-only. Before the JSON++// parser, which would consume the raw body the signature is over.++app.post('/internal/events', ...require('./revocations').handler());app.use(express.json({ limit: '2mb' }));// ── Visitor sign-in (OAuth client `media` on the Network; same module as Community/Tools) ──@@@ -93,8 +96,6 @@ app.get('/manifest.webmanifest', (_req, res) => res.type('application/manifest+jconst pastes = require('./pastes/routes');app.post('/internal/avatar-ingest', internalOnly, require('./avatars/ingest').createIngestHandler({ db: require('./db/database'), config, screenshotsDir: pastes.SCREENSHOTS_DIR, generateSlug: pastes.generateSlug }));}--// Network's sign-out-everywhere cutoffs (server/revocations.js): signed, loopback-only, like the rest of /internal.--app.post('/internal/events', ...require('./revocations').handler());const userAuth = require('./user-auth');const userAuthConfig = {baseUrl: config.publicUrl, networkUrl: config.network.url, networkInternalUrl: config.network.internalUrl,@@@ -22,7 +22,11 @@ const ev = (over = {}) => ({ event_id: 'evt_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3', event_t(async () => {const app = express();++ // As in server/index.js: mounted before the JSON parser (the signature is over the raw body).++ const src = fs.readFileSync(path.join(__dirname, '../server/index.js'), 'utf8');++ assert.ok(src.indexOf("app.post('/internal/events'") < src.indexOf("app.use(express.json("), 'the events route comes before express.json()');app.post('/internal/events', ...revocations.handler());++ app.use(express.json());const srv = http.createServer(app);await new Promise((r) => srv.listen(0, '127.0.0.1', r));const url = `http://127.0.0.1:${srv.address().port}/internal/events`;
@@ -62,6 +62,9 @@ if (drill.enabled) app.use(drill.readOnly);
@@ -62,6 +62,9 @@ if (drill.enabled) app.use(drill.readOnly);
// Object API v2 content uploads read the raw request body, so they sit ahead of the body parsers.
// Object API v2 content uploads read the raw request body, so they sit ahead of the body parsers.
app.put('/api/v2/:app/objects/:id/content', ...require('./objects/routes').contentHandlers);
app.put('/api/v2/:app/objects/:id/content', ...require('./objects/routes').contentHandlers);
app.put('/api/v2/:app/objects/:id/multipart/:uploadId/parts/:n', ...require('./objects/routes').partHandlers);
app.put('/api/v2/:app/objects/:id/multipart/:uploadId/parts/:n', ...require('./objects/routes').partHandlers);
+// Network's sign-out-everywhere cutoffs (server/revocations.js): signed, loopback-only. Before the JSON
+// parser, which would consume the raw body the signature is over.
+app.post('/internal/events', ...require('./revocations').handler());
app.use(express.json({ limit: '2mb' }));
app.use(express.json({ limit: '2mb' }));
// ── Visitor sign-in (OAuth client `media` on the Network; same module as Community/Tools) ──
// ── Visitor sign-in (OAuth client `media` on the Network; same module as Community/Tools) ──
@@ -93,8 +96,6 @@ app.get('/manifest.webmanifest', (_req, res) => res.type('application/manifest+j
@@ -93,8 +96,6 @@ app.get('/manifest.webmanifest', (_req, res) => res.type('application/manifest+j
const pastes = require('./pastes/routes');
const pastes = require('./pastes/routes');
app.post('/internal/avatar-ingest', internalOnly, require('./avatars/ingest').createIngestHandler({ db: require('./db/database'), config, screenshotsDir: pastes.SCREENSHOTS_DIR, generateSlug: pastes.generateSlug }));
app.post('/internal/avatar-ingest', internalOnly, require('./avatars/ingest').createIngestHandler({ db: require('./db/database'), config, screenshotsDir: pastes.SCREENSHOTS_DIR, generateSlug: pastes.generateSlug }));
}
}
-// Network's sign-out-everywhere cutoffs (server/revocations.js): signed, loopback-only, like the rest of /internal.
-app.post('/internal/events', ...require('./revocations').handler());
const userAuth = require('./user-auth');
const userAuth = require('./user-auth');
const userAuthConfig = {
const userAuthConfig = {
baseUrl: config.publicUrl, networkUrl: config.network.url, networkInternalUrl: config.network.internalUrl,
baseUrl: config.publicUrl, networkUrl: config.network.url, networkInternalUrl: config.network.internalUrl,
@@ -22,7 +22,11 @@ const ev = (over = {}) => ({ event_id: 'evt_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3', event_t
@@ -22,7 +22,11 @@ const ev = (over = {}) => ({ event_id: 'evt_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3', event_t
(async () => {
(async () => {
const app = express();
const app = express();
+ // As in server/index.js: mounted before the JSON parser (the signature is over the raw body).
+ const src = fs.readFileSync(path.join(__dirname, '../server/index.js'), 'utf8');
+ assert.ok(src.indexOf("app.post('/internal/events'") < src.indexOf("app.use(express.json("), 'the events route comes before express.json()');
app.post('/internal/events', ...revocations.handler());
app.post('/internal/events', ...revocations.handler());
+ app.use(express.json());
const srv = http.createServer(app);
const srv = http.createServer(app);
await new Promise((r) => srv.listen(0, '127.0.0.1', r));
await new Promise((r) => srv.listen(0, '127.0.0.1', r));
const url = `http://127.0.0.1:${srv.address().port}/internal/events`;
const url = `http://127.0.0.1:${srv.address().port}/internal/events`;