diff --git a/package.json b/package.json index 194ada9fb..d5038cc46 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@sindresorhus/df": "git+https://github.com/cloudron-io/df.git#type", "async": "^2.6.3", "aws-sdk": "^2.759.0", + "basic-auth": "^2.0.1", "body-parser": "^1.19.0", "cloudron-manifestformat": "^5.8.1", "connect": "^3.7.0", diff --git a/src/nginxconfig.ejs b/src/nginxconfig.ejs index 702efb2c5..216ed16af 100644 --- a/src/nginxconfig.ejs +++ b/src/nginxconfig.ejs @@ -166,6 +166,8 @@ server { internal; proxy_pass http://127.0.0.1:3001/auth; proxy_pass_request_body off; + # repeat proxy headers since we addded proxy_set_header at this location level + proxy_set_header X-App-ID "<%= proxyAuth.id %>"; proxy_set_header Content-Length ""; } diff --git a/src/proxyauth.js b/src/proxyauth.js index ad7c32744..04c6f6c84 100644 --- a/src/proxyauth.js +++ b/src/proxyauth.js @@ -9,6 +9,7 @@ exports = module.exports = { const apps = require('./apps.js'), assert = require('assert'), + basicAuth = require('basic-auth'), constants = require('./constants.js'), debug = require('debug')('box:proxyAuth'), express = require('express'), @@ -28,7 +29,6 @@ let gHttpServer = null; let TOKEN_SECRET = null; const EXPIRY_DAYS = 7; -// middleware to check auth status function jwtVerify(req, res, next) { const token = req.cookies.authToken; @@ -46,6 +46,21 @@ function jwtVerify(req, res, next) { }); } +function basicAuthVerify(req, res, next) { + const appId = req.headers['x-app-id'] || ''; + const credentials = basicAuth(req); + if (!appId || !credentials) return next(); + + const api = credentials.name.indexOf('@') !== -1 ? users.verifyWithEmail : users.verifyWithUsername; + + api(credentials.name, credentials.pass, appId, function (error, user) { + if (error) return next(new HttpError(403, 'Invalid username or password' )); + + req.user = user; + next(); + }); +} + function loginPage(req, res, next) { const appId = req.headers['x-app-id'] || ''; if (!appId) return next(new HttpError(503, 'Nginx misconfiguration')); @@ -126,8 +141,7 @@ function initializeAuthwallExpressSync() { let QUERY_LIMIT = '1mb'; // max size for json and urlencoded queries let REQUEST_TIMEOUT = 10000; // timeout for all requests - let json = middleware.json({ strict: true, limit: QUERY_LIMIT }), // application/json - urlencoded = middleware.urlencoded({ extended: false, limit: QUERY_LIMIT }); // application/x-www-form-urlencoded + let json = middleware.json({ strict: true, limit: QUERY_LIMIT }); // application/json if (process.env.BOX_ENV !== 'test') app.use(middleware.morgan('proxyauth :method :url :status :response-time ms - :res[content-length]', { immediate: false })); @@ -139,18 +153,15 @@ function initializeAuthwallExpressSync() { app .use(middleware.timeout(REQUEST_TIMEOUT)) .use(middleware.cookieParser()) - .use(json) - .use(urlencoded) - .use(jwtVerify) .use(router) .use(middleware.lastMile()); router.get ('/', (req, res) => { res.redirect('/login'); }); // this can never happen router.get ('/login', loginPage); - router.get ('/auth', auth); - router.post('/login', login); + router.get ('/auth', jwtVerify, basicAuthVerify, auth); + router.post('/login', json, login); router.get ('/logout', logoutPage); - router.post('/logout', logout); + router.post('/logout', json, logout); return httpServer; }