From 6b77c3585d1c4a5b4ee039aef49aa00e7e8f87a9 Mon Sep 17 00:00:00 2001 From: John Livingston Date: Wed, 5 May 2021 17:06:19 +0200 Subject: [PATCH] Protecting some APIs with an APIKEY. --- server/lib/apikey.ts | 17 +++++++++++++++++ server/lib/middlewares/apikey.ts | 21 +++++++++++++++++++++ server/lib/prosody/config.ts | 6 ++++-- server/lib/routers/api.ts | 6 ++++-- 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 server/lib/apikey.ts create mode 100644 server/lib/middlewares/apikey.ts diff --git a/server/lib/apikey.ts b/server/lib/apikey.ts new file mode 100644 index 00000000..9d5e6047 --- /dev/null +++ b/server/lib/apikey.ts @@ -0,0 +1,17 @@ +/* +For internal API, we will generate an api Key that must be provided as +GET parameter for every API call. +*/ + +async function getAPIKey ({ storageManager }: RegisterServerOptions): Promise { + let value: string = await storageManager.getData('APIKEY') + if (!value) { + value = Math.random().toString(36).slice(2, 12) + await storageManager.storeData('APIKEY', value) + } + return value +} + +export { + getAPIKey +} diff --git a/server/lib/middlewares/apikey.ts b/server/lib/middlewares/apikey.ts new file mode 100644 index 00000000..be85cf4b --- /dev/null +++ b/server/lib/middlewares/apikey.ts @@ -0,0 +1,21 @@ +import type { Request, Response, NextFunction } from 'express' +import { getAPIKey } from '../apikey' + +type CheckAPIKeyMiddlewareFunc = (req: Request, res: Response, next: NextFunction) => Promise + +function getCheckAPIKeyMiddleware (options: RegisterServerOptions): CheckAPIKeyMiddlewareFunc { + return async (req: Request, res: Response, next: NextFunction) => { + const key = req.query.apikey + const apikey = await getAPIKey(options) + if (key !== apikey) { + options.peertubeHelpers.logger.warn('Invalid APIKEY') + res.sendStatus(403) + return + } + next() + } +} + +export { + getCheckAPIKeyMiddleware +} diff --git a/server/lib/prosody/config.ts b/server/lib/prosody/config.ts index d02de123..0f5b8963 100644 --- a/server/lib/prosody/config.ts +++ b/server/lib/prosody/config.ts @@ -3,6 +3,7 @@ import * as path from 'path' import { pluginName, getBaseRouter } from '../helpers' import { ProsodyFilePaths } from './config/paths' import { ProsodyConfigContent } from './config/content' +import { getAPIKey } from '../apikey' async function getWorkingDir ({ peertubeHelpers, storageManager }: RegisterServerOptions): Promise { const logger = peertubeHelpers.logger @@ -94,11 +95,12 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise { const router = getRouter() const logger = peertubeHelpers.logger - router.get('/room', asyncMiddleware( + router.get('/room', asyncMiddleware([ + getCheckAPIKeyMiddleware(options), async (req: Request, res: Response, _next: NextFunction) => { const jid: string = req.query.jid as string || '' logger.info(`Requesting room information for room '${jid}'.`) @@ -85,7 +87,7 @@ async function initApiRouter (options: RegisterServerOptions): Promise { } res.json(roomDefaults) } - )) + ])) router.get('/auth', asyncMiddleware( async (req: Request, res: Response, _next: NextFunction) => {