proxyAuth: persist the secret token

This commit is contained in:
Girish Ramakrishnan
2022-02-01 17:16:25 -08:00
parent 46144ae07a
commit aeef815bf7
4 changed files with 50 additions and 13 deletions
+18
View File
@@ -4,13 +4,16 @@
exports = module.exports = {
get,
getString,
set,
setString,
del,
ACME_ACCOUNT_KEY: 'acme_account_key',
ADDON_TURN_SECRET: 'addon_turn_secret',
SFTP_PUBLIC_KEY: 'sftp_public_key',
SFTP_PRIVATE_KEY: 'sftp_private_key',
PROXY_AUTH_TOKEN_SECRET: 'proxy_auth_token_secret',
CERT_PREFIX: 'cert',
@@ -30,6 +33,14 @@ async function get(id) {
return result[0].value;
}
async function getString(id) {
assert.strictEqual(typeof id, 'string');
const result = await database.query(`SELECT ${BLOBS_FIELDS} FROM blobs WHERE id = ?`, [ id ]);
if (result.length === 0) return null;
return result[0].value.toString('utf8');
}
async function set(id, value) {
assert.strictEqual(typeof id, 'string');
assert(value === null || Buffer.isBuffer(value));
@@ -37,6 +48,13 @@ async function set(id, value) {
await database.query('INSERT INTO blobs (id, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value=VALUES(value)', [ id, value ]);
}
async function setString(id, value) {
assert.strictEqual(typeof id, 'string');
assert(value === null || typeof value === 'string');
await database.query('INSERT INTO blobs (id, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value=VALUES(value)', [ id, Buffer.from(value) ]);
}
async function del(id) {
await database.query('DELETE FROM blobs WHERE id=?', [ id ]);
}
-1
View File
@@ -42,7 +42,6 @@ exports = module.exports = {
DYNDNS_INFO_FILE: path.join(baseDir(), 'platformdata/dyndns-info.json'),
DHPARAMS_FILE: path.join(baseDir(), 'platformdata/dhparams.pem'),
FEATURES_INFO_FILE: path.join(baseDir(), 'platformdata/features-info.json'),
PROXY_AUTH_TOKEN_SECRET_FILE: path.join(baseDir(), 'platformdata/proxy-auth-token-secret'),
VERSION_FILE: path.join(baseDir(), 'platformdata/VERSION'),
SSHFS_KEYS_DIR: path.join(baseDir(), 'platformdata/sshfs'),
SFTP_KEYS_DIR: path.join(baseDir(), 'platformdata/sftp/ssh'),
+13 -12
View File
@@ -1,5 +1,7 @@
'use strict';
const blobs = require('./blobs.js');
// heavily inspired from https://gock.net/blog/2020/nginx-subrequest-authentication-server/ and https://github.com/andygock/auth-server
exports = module.exports = {
@@ -14,7 +16,6 @@ const apps = require('./apps.js'),
debug = require('debug')('box:proxyAuth'),
ejs = require('ejs'),
express = require('express'),
fs = require('fs'),
hat = require('./hat.js'),
http = require('http'),
HttpError = require('connect-lastmile').HttpError,
@@ -31,16 +32,16 @@ const apps = require('./apps.js'),
util = require('util');
let gHttpServer = null;
let TOKEN_SECRET = null;
let gTokenSecret = null;
function jwtVerify(req, res, next) {
const token = req.cookies.authToken;
if (!token) return next();
jwt.verify(token, TOKEN_SECRET, function (error, decoded) {
jwt.verify(token, gTokenSecret, function (error, decoded) {
if (error) {
debug('clearing token', error);
debug('jwtVerify: clearing token', error);
res.clearCookie('authToken');
return next(new HttpError(403, 'Malformed token or bad signature'));
}
@@ -95,7 +96,7 @@ async function loginPage(req, res, next) {
try {
finalContent = ejs.render(translatedContent, { title, icon, dashboardOrigin });
} catch (e) {
debug('Error rendering proxyauth-login.ejs', e);
debug('loginPage: Error rendering proxyauth-login.ejs', e);
return next(new HttpError(500, 'Login template error'));
}
@@ -123,7 +124,7 @@ function auth(req, res, next) {
}
// user is already authenticated, refresh cookie
const token = jwt.sign({ user: req.user }, TOKEN_SECRET, { expiresIn: `${constants.DEFAULT_TOKEN_EXPIRATION_DAYS}d` });
const token = jwt.sign({ user: req.user }, gTokenSecret, { expiresIn: `${constants.DEFAULT_TOKEN_EXPIRATION_DAYS}d` });
res.cookie('authToken', token, {
httpOnly: true,
@@ -171,7 +172,7 @@ async function authorize(req, res, next) {
if (!apps.canAccess(app, req.user)) return next(new HttpError(403, 'Forbidden' ));
const token = jwt.sign({ user: users.removePrivateFields(req.user) }, TOKEN_SECRET, { expiresIn: `${constants.DEFAULT_TOKEN_EXPIRATION_DAYS}d` });
const token = jwt.sign({ user: users.removePrivateFields(req.user) }, gTokenSecret, { expiresIn: `${constants.DEFAULT_TOKEN_EXPIRATION_DAYS}d` });
res.cookie('authToken', token, {
httpOnly: true,
@@ -251,11 +252,11 @@ function initializeAuthwallExpressSync() {
async function start() {
assert.strictEqual(gHttpServer, null, 'Authwall is already up and running.');
if (!fs.existsSync(paths.PROXY_AUTH_TOKEN_SECRET_FILE)) {
TOKEN_SECRET = hat(64);
fs.writeFileSync(paths.PROXY_AUTH_TOKEN_SECRET_FILE, TOKEN_SECRET, 'utf8');
} else {
TOKEN_SECRET = fs.readFileSync(paths.PROXY_AUTH_TOKEN_SECRET_FILE, 'utf8').trim();
gTokenSecret = await blobs.getString(blobs.PROXY_AUTH_TOKEN_SECRET);
if (!gTokenSecret) {
debug('start: generating new token secret');
gTokenSecret = hat(64);
await blobs.setString(blobs.PROXY_AUTH_TOKEN_SECRET, gTokenSecret);
}
gHttpServer = initializeAuthwallExpressSync();