From fa1a7037b47f2e0114d8abc5a99d29239bd3637b Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 10 Jul 2022 16:07:45 +0200 Subject: refactor: local server import/export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristóf Marussy --- src/internal-server/start/routes.js | 68 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 13 deletions(-) (limited to 'src/internal-server/start/routes.js') diff --git a/src/internal-server/start/routes.js b/src/internal-server/start/routes.js index 79c809f5f..736796bb8 100644 --- a/src/internal-server/start/routes.js +++ b/src/internal-server/start/routes.js @@ -5,6 +5,8 @@ | */ +const { timingSafeEqual } = require('crypto'); + /** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */ const Route = use('Route'); @@ -14,14 +16,38 @@ const migrate = require('./migrate'); migrate(); +async function validateToken(clientToken, response, next) { + const serverToken = process.env.FERDIUM_LOCAL_TOKEN; + const valid = serverToken && + clientToken && + timingSafeEqual(Buffer.from(clientToken, 'utf8'), Buffer.from(serverToken, 'utf8')); + if (valid) { + await next(); + return true; + } + return response.forbidden(); +} + const OnlyAllowFerdium = async ({ request, response }, next) => { const version = request.header('X-Franz-Version'); if (!version) { - return response.status(403).redirect('/'); + return response.forbidden(); } - await next(); - return true; + const clientToken = request.header('X-Ferdium-Local-Token'); + return validateToken(clientToken, response, next); +}; + +const RequireTokenInQS = async ({ request, response }, next) => { + const clientToken = request.get().token; + return validateToken(clientToken, response, next); +} + +const FERDIUM_LOCAL_TOKEN_COOKIE = 'ferdium-local-token'; + +const RequireAuthenticatedBrowser = async({ request, response }, next) => { + const clientToken = request.cookie(FERDIUM_LOCAL_TOKEN_COOKIE); + return validateToken(clientToken, response, next); }; // Health: Returning if all systems function correctly @@ -67,16 +93,32 @@ Route.group(() => { Route.group(() => { Route.get('icon/:id', 'ImageController.icon'); -}).prefix(API_VERSION); +}) + .prefix(API_VERSION) + .middleware(RequireTokenInQS); -// Franz account import -Route.post('import', 'UserController.import'); -Route.get('import', ({ view }) => view.render('import')); +Route.group(() => { + // Franz account import + Route.post('import', 'UserController.import'); + Route.get('import', ({ view }) => view.render('import')); + + // Account transfer + Route.get('export', 'UserController.export'); + Route.post('transfer', 'UserController.importFerdium'); + Route.get('transfer', ({ view }) => view.render('transfer')); -// Account transfer -Route.get('export', 'UserController.export'); -Route.post('transfer', 'UserController.importFerdium'); -Route.get('transfer', ({ view }) => view.render('transfer')); + // Index + Route.get('/', ({ view }) => view.render('index')); +}).middleware(RequireAuthenticatedBrowser); -// Index -Route.get('/', ({ view }) => view.render('index')); +Route.get('token/:token', ({ params: { token }, response }) => { + if (validateToken(token)) { + response.cookie(FERDIUM_LOCAL_TOKEN_COOKIE, token, { + httpOnly: true, + sameSite: true, + path: '/', + }); + return response.redirect('/'); + } + return response.forbidden(); +}); -- cgit v1.2.3-70-g09d2