From e8813a8b33dbd10bc559923448aee437d5e7d174 Mon Sep 17 00:00:00 2001 From: Ifedapo Olarewaju Date: Sun, 17 Feb 2019 21:09:20 +0100 Subject: [PATCH] send authtoken via query param --- .../src/server/controllers/callback.js | 44 +--------------- .../companion/src/server/controllers/index.js | 1 + .../src/server/controllers/send-token.js | 51 +++++++++++++++++++ packages/@uppy/companion/src/uppy.js | 3 +- .../companion/test/__tests__/companion.js | 35 ++++++++----- packages/@uppy/companion/test/mockserver.js | 2 +- packages/@uppy/provider-views/src/index.js | 2 +- 7 files changed, 79 insertions(+), 59 deletions(-) create mode 100644 packages/@uppy/companion/src/server/controllers/send-token.js diff --git a/packages/@uppy/companion/src/server/controllers/callback.js b/packages/@uppy/companion/src/server/controllers/callback.js index 29bfab6b2..17bd99f7a 100644 --- a/packages/@uppy/companion/src/server/controllers/callback.js +++ b/packages/@uppy/companion/src/server/controllers/callback.js @@ -1,11 +1,7 @@ /** * oAuth callback. Encrypts the access token and sends the new token with the response, - * and redirects to redirect url. */ const tokenService = require('../helpers/jwt') -const parseUrl = require('url').parse -const { hasMatch, sanitizeHtml } = require('../helpers/utils') -const oAuthState = require('../helpers/oauth-state') const logger = require('../logger') /** @@ -25,43 +21,5 @@ module.exports = function callback (req, res, next) { req.uppy.providerTokens[providerName] = req.query.access_token logger.debug(`Generating auth token for provider ${providerName}.`) const uppyAuthToken = tokenService.generateToken(req.uppy.providerTokens, req.uppy.options.secret) - // add the token to cookies for thumbnail/image requests - tokenService.addToCookies(res, uppyAuthToken, req.uppy.options) - - const state = (req.session.grant || {}).state - if (state) { - const origin = oAuthState.getFromState(state, 'origin', req.uppy.options.secret) - const allowedClients = req.uppy.options.clients - // if no preset clients then allow any client - if (!allowedClients || hasMatch(origin, allowedClients) || hasMatch(parseUrl(origin).host, allowedClients)) { - const redirect = oAuthState.getFromState(state, 'redirect', req.uppy.options.secret) - if (redirect) { - // if a redirect value is specified from the client, then redirect there instead - const query = (parseUrl(redirect).query ? `&` : `?`) + `uppyAuthToken=${uppyAuthToken}` - return res.redirect(`${redirect}${query}`) - } - return res.send(htmlContent(uppyAuthToken, origin)) - } - } - next() -} - -/** - * - * @param {string} token uppy auth token - * @param {string} origin url string - */ -const htmlContent = (token, origin) => { - return ` - - - - - - - - ` + return res.redirect(req.uppy.buildURL(`/${providerName}/send-token?uppyAuthToken=${uppyAuthToken}`, true)) } diff --git a/packages/@uppy/companion/src/server/controllers/index.js b/packages/@uppy/companion/src/server/controllers/index.js index 9e6b4810c..fde48e803 100644 --- a/packages/@uppy/companion/src/server/controllers/index.js +++ b/packages/@uppy/companion/src/server/controllers/index.js @@ -1,6 +1,7 @@ module.exports = { authorized: require('./authorized'), callback: require('./callback'), + sendToken: require('./send-token'), get: require('./get'), thumbnail: require('./thumbnail'), list: require('./list'), diff --git a/packages/@uppy/companion/src/server/controllers/send-token.js b/packages/@uppy/companion/src/server/controllers/send-token.js new file mode 100644 index 000000000..335d0987c --- /dev/null +++ b/packages/@uppy/companion/src/server/controllers/send-token.js @@ -0,0 +1,51 @@ +/** + * + * sends auth token to uppy client + */ +const tokenService = require('../helpers/jwt') +const parseUrl = require('url').parse +const { hasMatch, sanitizeHtml } = require('../helpers/utils') +const oAuthState = require('../helpers/oauth-state') + +/** + * + * @param {object} req + * @param {object} res + * @param {function} next + */ +module.exports = function sendToken (req, res, next) { + const uppyAuthToken = req.uppy.authToken + // add the token to cookies for thumbnail/image requests + tokenService.addToCookies(res, uppyAuthToken, req.uppy.options) + + const state = (req.session.grant || {}).state + if (state) { + const origin = oAuthState.getFromState(state, 'origin', req.uppy.options.secret) + const allowedClients = req.uppy.options.clients + // if no preset clients then allow any client + if (!allowedClients || hasMatch(origin, allowedClients) || hasMatch(parseUrl(origin).host, allowedClients)) { + return res.send(htmlContent(uppyAuthToken, origin)) + } + } + next() +} + +/** + * + * @param {string} token uppy auth token + * @param {string} origin url string + */ +const htmlContent = (token, origin) => { + return ` + + + + + + + + ` +} diff --git a/packages/@uppy/companion/src/uppy.js b/packages/@uppy/companion/src/uppy.js index af394d3cb..3367228c0 100644 --- a/packages/@uppy/companion/src/uppy.js +++ b/packages/@uppy/companion/src/uppy.js @@ -87,6 +87,7 @@ module.exports.app = (options = {}) => { app.get('/:providerName/redirect', middlewares.hasSessionAndProvider, controllers.redirect) app.get('/:providerName/logout', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.logout) app.get('/:providerName/authorized', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.authorized) + app.get('/:providerName/send-token', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.sendToken) app.get('/:providerName/list/:id?', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.list) app.post('/:providerName/get/:id', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.get) app.get('/:providerName/thumbnail/:id', middlewares.hasSessionAndProvider, middlewares.cookieAuthToken, middlewares.verifyToken, controllers.thumbnail) @@ -217,7 +218,7 @@ const getOptionsMiddleware = (options) => { req.uppy = { options, s3Client, - authToken: req.header('uppy-auth-token'), + authToken: req.header('uppy-auth-token') || req.query.uppyAuthToken, buildURL: getURLBuilder(options) } next() diff --git a/packages/@uppy/companion/test/__tests__/companion.js b/packages/@uppy/companion/test/__tests__/companion.js index d198983d5..064d48cbb 100644 --- a/packages/@uppy/companion/test/__tests__/companion.js +++ b/packages/@uppy/companion/test/__tests__/companion.js @@ -66,26 +66,35 @@ describe('download provdier file', () => { }) describe('test authentication', () => { - test('authentication callback redirects to specified url', () => { + test('authentication callback redirects to send-token url', () => { return request(authServer) .get('/drive/callback') - .set('uppy-auth-token', token) + .expect(302) + .expect((res) => { + expect(res.header['location']).toContain('http://localhost:3020/drive/send-token?uppyAuthToken=') + }) + }) + + test('the token gets sent via cookie and html', () => { + return request(authServer) + .get(`/drive/send-token?uppyAuthToken=${token}`) .expect(200) .expect((res) => { const authToken = res.header['set-cookie'][0].split(';')[0].split('uppyAuthToken=')[1] + expect(authToken).toEqual(token) // see mock ../../src/server/helpers/oauth-state above for http://localhost:3020 const body = ` - - - - - - - - ` + + + + + + + + ` expect(res.text).toBe(body) }) }) diff --git a/packages/@uppy/companion/test/mockserver.js b/packages/@uppy/companion/test/mockserver.js index 580f2357d..db74a99b1 100644 --- a/packages/@uppy/companion/test/mockserver.js +++ b/packages/@uppy/companion/test/mockserver.js @@ -5,7 +5,7 @@ const session = require('express-session') var authServer = express() authServer.use(session({ secret: 'grant', resave: true, saveUninitialized: true })) -authServer.all('/drive/callback', (req, res, next) => { +authServer.all('/drive/send-token', (req, res, next) => { req.session.grant = { state: 'non-empty-value' } next() diff --git a/packages/@uppy/provider-views/src/index.js b/packages/@uppy/provider-views/src/index.js index 45cfef8f8..11c09e86f 100644 --- a/packages/@uppy/provider-views/src/index.js +++ b/packages/@uppy/provider-views/src/index.js @@ -422,7 +422,7 @@ module.exports = class ProviderView { } handleAuth () { - const authState = btoa(JSON.stringify({ origin: location.origin })) + const authState = btoa(JSON.stringify({ origin: location.origin, redirect: 'http://localhost:3' })) const link = `${this.provider.authUrl()}?state=${authState}` const authWindow = window.open(link, '_blank')