From 3bbacabd2e711a204c143e8fbc045eeb32928c14 Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Tue, 14 Oct 2014 10:59:11 -0700 Subject: [PATCH] Add app proxy route This will add a proxy route for apps which are set to run in private mode. At the moment there is no UI to make apps private. --- src/routes/oauth2.js | 60 ++++++++++++++++++++++++++++++++++++++------ src/server.js | 1 + 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/routes/oauth2.js b/src/routes/oauth2.js index 21b8898f5..6cb652e96 100644 --- a/src/routes/oauth2.js +++ b/src/routes/oauth2.js @@ -8,6 +8,7 @@ var oauth2orize = require('oauth2orize'), url = require('url'), + http = require('http'), passport = require('passport'), assert = require('assert'), session = require('connect-ensure-login'), @@ -120,7 +121,7 @@ server.exchange(oauth2orize.exchange.code(function (client, code, redirectURI, c // Main login form username and password function loginForm(req, res) { - res.render('login', { csrf: req.csrfToken() }); + res.render('login', { adminOrigin: config.adminOrigin, csrf: req.csrfToken() }); } // In memory password reset token store @@ -128,7 +129,7 @@ var resetTokens = {}; // Form to enter email address to send a password reset request mail function passwordResetRequestSite(req, res) { - res.render('password_reset_request', { csrf: req.csrfToken() }); + res.render('password_reset_request', { adminOrigin: config.adminOrigin, csrf: req.csrfToken() }); } // This route is used for above form submission @@ -151,7 +152,7 @@ function passwordResetRequest(req, res, next) { function passwordSentSite(req, res) { debug('passwordSentSite'); - res.render('password_reset_sent', {}); + res.render('password_reset_sent', { adminOrigin: config.adminOrigin }); } function passwordResetSite(req, res, next) { @@ -163,7 +164,7 @@ function passwordResetSite(req, res, next) { userdb.get(key, function (error, result) { if (error) return next(new HttpError(400, 'Unknown reset token')); - res.render('password_reset', { user: result, csrf: req.csrfToken(), resetToken: req.query.reset_token }); + res.render('password_reset', { adminOrigin: config.adminOrigin, user: result, csrf: req.csrfToken(), resetToken: req.query.reset_token }); }); } @@ -222,7 +223,7 @@ var callback = [ session.ensureLoggedIn('/api/v1/session/login'), function (req, res) { debug('callback: with callback server ' + req.query.redirectURI); - res.render('callback', { callbackServer: req.query.redirectURI }); + res.render('callback', { adminOrigin: config.adminOrigin, callbackServer: req.query.redirectURI }); } ]; @@ -235,7 +236,7 @@ var callback = [ var error = [ session.ensureLoggedIn('/api/v1/session/login'), function (req, res) { - res.render('error', {}); + res.render('error', { adminOrigin: config.adminOrigin }); } ]; @@ -406,6 +407,50 @@ function delClientTokens(req, res, next) { }); } +var proxy = [ + function (req, res, next) { + if (req.path === '/api/v1/oauth/proxy/api/v1/session/login') { + if (req.method === 'GET') { + + // in case we login, the returnTo needs to be rewritten, to get rid of the proxy prefix + var proxyPrefix = '/api/v1/oauth/proxy'; + req.session.returnTo = req.session.returnTo.indexOf(proxyPrefix) === 0 ? req.session.returnTo.slice(proxyPrefix.length) : req.session.returnTo; + + return loginForm(req, res); + } else if (req.method === 'POST') { + return passport.authenticate('local', { + successReturnToOrRedirect: '/api/v1/session/error', + failureRedirect: '/api/v1/session/login' + })(req, res, next); + } + } + next(); + }, + session.ensureLoggedIn('/api/v1/session/login'), + function (req, res, next) { + var options = { + host: '127.0.0.1', + port: req.headers['x-forwarded-port'], + method: req.method, + path: req.params[0], + headers: req.headers + }; + + var appRequest = http.request(options, function (appResponse) { + res.writeHead(appResponse.statusCode, appResponse.headers); + appResponse.on('error', console.error); + appResponse.pipe(res, { end: true }); + }); + + req.on('error', console.error); + if (!req.readable) { + appRequest.end(); + } else { + req.pipe(appRequest, { end: true }); + } + } +]; + exports = module.exports = { loginForm: loginForm, login: login, @@ -424,5 +469,6 @@ exports = module.exports = { scope: scope, getClients: getClients, getClientTokens: getClientTokens, - delClientTokens: delClientTokens + delClientTokens: delClientTokens, + proxy: proxy }; \ No newline at end of file diff --git a/src/server.js b/src/server.js index eaaa8dc84..0a1ffd58f 100644 --- a/src/server.js +++ b/src/server.js @@ -235,6 +235,7 @@ Server.prototype._initializeExpressSync = function () { router.get ('/api/v1/oauth/clients', settingsScope, routes.oauth2.getClients); router.get ('/api/v1/oauth/clients/:clientId/tokens', settingsScope, routes.oauth2.getClientTokens); router.del ('/api/v1/oauth/clients/:clientId/tokens', settingsScope, routes.oauth2.delClientTokens); + router.all ('/api/v1/oauth/proxy*', csurf, routes.oauth2.proxy); // app routes router.get ('/api/v1/apps', appsScope, routes.apps.getApps);