From 8793912e7e4a82e8720d8c1c66870de94d7ee8de Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Mon, 18 May 2020 13:54:11 +0200 Subject: [PATCH 01/10] First cut - add subroutes --- .../src/providers/github/router.ts | 22 +++++++++++++++++++ .../src/providers/google/router.ts | 22 +++++++++++++++++++ plugins/auth-backend/src/service/router.ts | 19 ++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 plugins/auth-backend/src/providers/github/router.ts create mode 100644 plugins/auth-backend/src/providers/google/router.ts diff --git a/plugins/auth-backend/src/providers/github/router.ts b/plugins/auth-backend/src/providers/github/router.ts new file mode 100644 index 0000000000..a1c6efa64f --- /dev/null +++ b/plugins/auth-backend/src/providers/github/router.ts @@ -0,0 +1,22 @@ +import express from 'express'; +import Router from 'express-promise-router'; + +export const router = Router(); +router.get('/', async (_req: express.Request, res: express.Response) => { + res.send('initiate auth'); +}); + +router.get('/login', async (_req: express.Request, res: express.Response) => { + res.send('github provider login'); +}); + +router.get('/logout', async (_req: express.Request, res: express.Response) => { + res.send('github provider logout'); +}); + +router.get( + '/handler/frame', + async (req: express.Request, res: express.Response) => { + res.send('github provider frame response handler'); + }, +); diff --git a/plugins/auth-backend/src/providers/google/router.ts b/plugins/auth-backend/src/providers/google/router.ts new file mode 100644 index 0000000000..cb1c635602 --- /dev/null +++ b/plugins/auth-backend/src/providers/google/router.ts @@ -0,0 +1,22 @@ +import express from 'express'; +import Router from 'express-promise-router'; + +export const router = Router(); +router.get('/', async (_req: express.Request, res: express.Response) => { + res.send('initiate auth'); +}); + +router.get('/login', async (_req: express.Request, res: express.Response) => { + res.send('google provider login'); +}); + +router.get('/logout', async (_req: express.Request, res: express.Response) => { + res.send('google provider logout'); +}); + +router.get( + '/handler/frame', + async (req: express.Request, res: express.Response) => { + res.send('google provider frame response handler'); + }, +); diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index f238d973aa..dd9f4d00b9 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -17,6 +17,8 @@ import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; +import { router as googleAuthRouter } from './../providers/google/router'; +import { router as githubAuthRouter } from './../providers/google/router'; export interface RouterOptions { logger: Logger; @@ -32,9 +34,26 @@ export async function createRouter( res.status(200).send('pong'); }); + router.use('/:provider', authProviderSwitcher); + const app = express(); app.set('logger', logger); app.use(router); return app; } + +const authProviderSwitcher = async ( + req: express.Request, + res: express.Response, + next: express.NextFunction, +) => { + const provider = req.params.provider; + if (provider === 'google') { + return googleAuthRouter(req, res, next); + } else if (provider === 'github') { + return githubAuthRouter(req, res, next); + } else { + res.send('No such provider'); + } +}; From 6757352a791920938ba07b74c88867e9fd8ab048 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Mon, 18 May 2020 21:31:08 +0200 Subject: [PATCH 02/10] Add passportJS and add strategy and routing for a provider. --- plugins/auth-backend/package.json | 10 +- plugins/auth-backend/src/providers/config.ts | 20 + .../src/providers/google/router.ts | 26 +- plugins/auth-backend/src/service/router.ts | 163 ++++++-- .../src/service/standaloneApplication.ts | 2 + yarn.lock | 393 ++++++++++++------ 6 files changed, 450 insertions(+), 164 deletions(-) create mode 100644 plugins/auth-backend/src/providers/config.ts diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index c043bb990c..a66ac42006 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -20,16 +20,22 @@ "cors": "^2.8.5", "express": "^4.17.1", "express-promise-router": "^3.0.3", + "express-session": "1.17.1", "fs-extra": "^9.0.0", "helmet": "^3.22.0", "morgan": "^1.10.0", "winston": "^3.2.1", - "yn": "^4.0.0" + "yn": "^4.0.0", + "passport": "0.4.1", + "passport-google-oauth20": "2.0.0" }, "devDependencies": { "@backstage/cli": "^0.1.1-alpha.5", "jest-fetch-mock": "^3.0.3", - "tsc-watch": "^4.2.3" + "tsc-watch": "^4.2.3", + "@types/passport": "1.0.3", + "@types/express-session": "1.17.0", + "@types/passport-google-oauth20": "2.0.3" }, "files": [ "dist" diff --git a/plugins/auth-backend/src/providers/config.ts b/plugins/auth-backend/src/providers/config.ts new file mode 100644 index 0000000000..b899347938 --- /dev/null +++ b/plugins/auth-backend/src/providers/config.ts @@ -0,0 +1,20 @@ +export const providers = [ + { + provider: 'google', + options: { + clientID: process.env.GOOGLE_CLIENT_ID!, + clientSecret: process.env.GOOGLE_CLIENT_SECRET!, + callbackURL: 'http://localhost:7000/auth/google/handler/frame', + passReqToCallback: true, + }, + }, + // { + // provider: 'github', + // options: { + // clientID: process.env.GITHUB_CLIENT_ID!, + // clientSecret: process.env.GITHUB_CLIENT_SECRET!, + // callbackURL: 'http://localhost:7000/auth/github/handler/frame', + // passReqToCallback: true, + // }, + // }, +]; diff --git a/plugins/auth-backend/src/providers/google/router.ts b/plugins/auth-backend/src/providers/google/router.ts index cb1c635602..73f5ee6f9d 100644 --- a/plugins/auth-backend/src/providers/google/router.ts +++ b/plugins/auth-backend/src/providers/google/router.ts @@ -1,13 +1,25 @@ import express from 'express'; import Router from 'express-promise-router'; +import passport from 'passport'; export const router = Router(); -router.get('/', async (_req: express.Request, res: express.Response) => { - res.send('initiate auth'); +router.get('/start', (req, res, next) => { + passport.authenticate('google', { + scope: ['profile', 'email'], + accessType: 'offline', + prompt: 'consent', + state: '8745634875963', + })(req, res, next); }); -router.get('/login', async (_req: express.Request, res: express.Response) => { - res.send('google provider login'); +router.get('/handler/frame', passport.authenticate('google'), function ( + req, + res, +) { + console.log('DEBUG: req.session.passport.user', req.session?.passport.user); + console.log('DEBUG: req.params =', req.params); + console.log('DEBUG: req.url =', req.url); + res.send('yay!'); }); router.get('/logout', async (_req: express.Request, res: express.Response) => { @@ -15,8 +27,8 @@ router.get('/logout', async (_req: express.Request, res: express.Response) => { }); router.get( - '/handler/frame', - async (req: express.Request, res: express.Response) => { - res.send('google provider frame response handler'); + '/refreshToken', + async (_req: express.Request, res: express.Response) => { + res.send('google provider refreshToken'); }, ); diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index dd9f4d00b9..ae0f3d822b 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -16,44 +16,157 @@ import express from 'express'; import Router from 'express-promise-router'; +import passport from 'passport'; +import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; import { Logger } from 'winston'; -import { router as googleAuthRouter } from './../providers/google/router'; -import { router as githubAuthRouter } from './../providers/google/router'; +import { providers } from './../providers/config'; export interface RouterOptions { logger: Logger; } +type AuthProviderHandlers = { + start( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): Promise; + handle( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): express.Response; + refresh?( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): Promise; + logout( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): express.Response; +}; + +type AuthProvider = { + [key: string]: { + makeStrategy(options: any): passport.Strategy; + makeRouter(handlers: AuthProviderHandlers): express.Router; + }; +}; + +type AuthInfo = { + profile: passport.Profile; + accessToken: string; + refreshToken?: string; + expiresAt?: number; +}; + +type AuthResponse = { + type: string; + payload: AuthInfo; +}; + +const postMessageResponse = (res: express.Response, data: AuthResponse) => { + const jsonData = JSON.stringify(data); + const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); + + res.setHeader('X-Frame-Options', 'sameorigin'); + res.end(` + + + + + + `); +}; + +const GoogleAuthProviderHandler: AuthProviderHandlers = { + start(req, res, next) { + return passport.authenticate('google', { + scope: ['profile', 'email'], + accessType: 'offline', + prompt: 'consent', + state: '8745634875963', + })(req, res, next); + }, + handle(req, res, next) { + return passport.authenticate('google', function (_, user) { + postMessageResponse(res, { + type: 'oauth-result', + payload: user, + }); + })(req, res, next); + }, + logout(_req, res, _next) { + return res.send('logout!'); + }, +}; + +const providerFactories: AuthProvider = { + google: { + makeStrategy(options: any): passport.Strategy { + return new GoogleStrategy(options, function ( + _req: any, + accessToken: any, + refreshToken: any, + profile: any, + cb: any, + ) { + cb(undefined, { profile, accessToken, refreshToken }); + }); + }, + makeRouter(handlers: AuthProviderHandlers): express.Router { + const router = Router(); + router.get('/start', handlers.start); + router.get('/handler/frame', handlers.handle); + router.get('/logout', handlers.logout); + if (handlers.refresh) { + router.get('/refreshToken', handlers.refresh); + } + return router; + }, + }, +}; + +function makeProvider(config: any) { + const provider = config.provider; + const providerFactory = providerFactories[provider]; + const strategy: passport.Strategy = providerFactory.makeStrategy( + config.options, + ); + const providerRouter = providerFactory.makeRouter(GoogleAuthProviderHandler); + return { provider, strategy, providerRouter }; +} + export async function createRouter( options: RouterOptions, ): Promise { - const logger = options.logger.child({ plugin: 'auth' }); const router = Router(); + for (const providerConfig of providers) { + const { provider, strategy, providerRouter } = makeProvider(providerConfig); + passport.use(strategy); + + router.use(`/${provider}`, providerRouter); + } + + passport.serializeUser(function (user, done) { + done(null, user); + }); + + passport.deserializeUser(function (user, done) { + done(null, user); + }); + + router.use(passport.initialize()); + router.use(passport.session()); + router.get('/ping', async (_req, res) => { res.status(200).send('pong'); }); - router.use('/:provider', authProviderSwitcher); - - const app = express(); - app.set('logger', logger); - app.use(router); - - return app; + return router; } - -const authProviderSwitcher = async ( - req: express.Request, - res: express.Response, - next: express.NextFunction, -) => { - const provider = req.params.provider; - if (provider === 'google') { - return googleAuthRouter(req, res, next); - } else if (provider === 'github') { - return githubAuthRouter(req, res, next); - } else { - res.send('No such provider'); - } -}; diff --git a/plugins/auth-backend/src/service/standaloneApplication.ts b/plugins/auth-backend/src/service/standaloneApplication.ts index 5eea4fb8f5..d2d817c342 100644 --- a/plugins/auth-backend/src/service/standaloneApplication.ts +++ b/plugins/auth-backend/src/service/standaloneApplication.ts @@ -23,6 +23,8 @@ import compression from 'compression'; import cors from 'cors'; import express from 'express'; import helmet from 'helmet'; +import passport from 'passport'; +import session from 'express-session'; import { Logger } from 'winston'; import { createRouter } from './router'; diff --git a/yarn.lock b/yarn.lock index 52d9ad442c..745978eeb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1715,14 +1715,14 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@lerna/add@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b" - integrity sha512-vhUXXF6SpufBE1EkNEXwz1VLW03f177G9uMOFMQkp6OJ30/PWg4Ekifuz9/3YfgB2/GH8Tu4Lk3O51P2Hskg/A== +"@lerna/add@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/add/-/add-3.20.0.tgz#bea7edf36fc93fb72ec34cb9ba854c48d4abf309" + integrity sha512-AnH1oRIEEg/VDa3SjYq4x1/UglEAvrZuV0WssHUMN81RTZgQk3we+Mv3qZNddrZ/fBcZu2IAdN/EQ3+ie2JxKQ== dependencies: "@evocateur/pacote" "^9.6.3" - "@lerna/bootstrap" "3.21.0" - "@lerna/command" "3.21.0" + "@lerna/bootstrap" "3.20.0" + "@lerna/command" "3.18.5" "@lerna/filter-options" "3.20.0" "@lerna/npm-conf" "3.16.0" "@lerna/validation-error" "3.13.0" @@ -1731,12 +1731,12 @@ p-map "^2.1.0" semver "^6.2.0" -"@lerna/bootstrap@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.21.0.tgz#bcd1b651be5b0970b20d8fae04c864548123aed6" - integrity sha512-mtNHlXpmvJn6JTu0KcuTTPl2jLsDNud0QacV/h++qsaKbhAaJr/FElNZ5s7MwZFUM3XaDmvWzHKaszeBMHIbBw== +"@lerna/bootstrap@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.20.0.tgz#635d71046830f208e851ab429a63da1747589e37" + integrity sha512-Wylullx3uthKE7r4izo09qeRGL20Y5yONlQEjPCfnbxCC2Elu+QcPu4RC6kqKQ7b+g7pdC3OOgcHZjngrwr5XQ== dependencies: - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/filter-options" "3.20.0" "@lerna/has-npm-version" "3.16.5" "@lerna/npm-install" "3.16.5" @@ -1760,13 +1760,13 @@ read-package-tree "^5.1.6" semver "^6.2.0" -"@lerna/changed@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/changed/-/changed-3.21.0.tgz#108e15f679bfe077af500f58248c634f1044ea0b" - integrity sha512-hzqoyf8MSHVjZp0gfJ7G8jaz+++mgXYiNs9iViQGA8JlN/dnWLI5sWDptEH3/B30Izo+fdVz0S0s7ydVE3pWIw== +"@lerna/changed@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/changed/-/changed-3.20.0.tgz#66b97ebd6c8f8d207152ee524a0791846a9097ae" + integrity sha512-+hzMFSldbRPulZ0vbKk6RD9f36gaH3Osjx34wrrZ62VB4pKmjyuS/rxVYkCA3viPLHoiIw2F8zHM5BdYoDSbjw== dependencies: "@lerna/collect-updates" "3.20.0" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/listable" "3.18.5" "@lerna/output" "3.13.0" @@ -1788,12 +1788,12 @@ execa "^1.0.0" strong-log-transformer "^2.0.0" -"@lerna/clean@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/clean/-/clean-3.21.0.tgz#c0b46b5300cc3dae2cda3bec14b803082da3856d" - integrity sha512-b/L9l+MDgE/7oGbrav6rG8RTQvRiZLO1zTcG17zgJAAuhlsPxJExMlh2DFwJEVi2les70vMhHfST3Ue1IMMjpg== +"@lerna/clean@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/clean/-/clean-3.20.0.tgz#ba777e373ddeae63e57860df75d47a9e5264c5b2" + integrity sha512-9ZdYrrjQvR5wNXmHfDsfjWjp0foOkCwKe3hrckTzkAeQA1ibyz5llGwz5e1AeFrV12e2/OLajVqYfe+qdkZUgg== dependencies: - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/filter-options" "3.20.0" "@lerna/prompt" "3.18.5" "@lerna/pulse-till-done" "3.13.0" @@ -1833,14 +1833,14 @@ npmlog "^4.1.2" slash "^2.0.0" -"@lerna/command@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/command/-/command-3.21.0.tgz#9a2383759dc7b700dacfa8a22b2f3a6e190121f7" - integrity sha512-T2bu6R8R3KkH5YoCKdutKv123iUgUbW8efVjdGCDnCMthAQzoentOJfDeodBwn0P2OqCl3ohsiNVtSn9h78fyQ== +"@lerna/command@3.18.5": + version "3.18.5" + resolved "https://registry.npmjs.org/@lerna/command/-/command-3.18.5.tgz#14c6d2454adbfd365f8027201523e6c289cd3cd9" + integrity sha512-36EnqR59yaTU4HrR1C9XDFti2jRx0BgpIUBeWn129LZZB8kAB3ov1/dJNa1KcNRKp91DncoKHLY99FZ6zTNpMQ== dependencies: "@lerna/child-process" "3.16.5" "@lerna/package-graph" "3.18.5" - "@lerna/project" "3.21.0" + "@lerna/project" "3.18.0" "@lerna/validation-error" "3.13.0" "@lerna/write-log-file" "3.13.0" clone-deep "^4.0.1" @@ -1875,14 +1875,14 @@ fs-extra "^8.1.0" npmlog "^4.1.2" -"@lerna/create@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/create/-/create-3.21.0.tgz#e813832adf3488728b139e5a75c8b01b1372e62f" - integrity sha512-cRIopzKzE2vXJPmsiwCDMWo4Ct+KTmX3nvvkQLDoQNrrRK7w+3KQT3iiorbj1koD95RsVQA7mS2haWok9SIv0g== +"@lerna/create@3.18.5": + version "3.18.5" + resolved "https://registry.npmjs.org/@lerna/create/-/create-3.18.5.tgz#11ac539f069248eaf7bc4c42e237784330f4fc47" + integrity sha512-cHpjocbpKmLopCuZFI7cKEM3E/QY8y+yC7VtZ4FQRSaLU8D8i2xXtXmYaP1GOlVNavji0iwoXjuNpnRMInIr2g== dependencies: "@evocateur/pacote" "^9.6.3" "@lerna/child-process" "3.16.5" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/npm-conf" "3.16.0" "@lerna/validation-error" "3.13.0" camelcase "^5.0.0" @@ -1907,23 +1907,23 @@ "@lerna/child-process" "3.16.5" npmlog "^4.1.2" -"@lerna/diff@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/diff/-/diff-3.21.0.tgz#e6df0d8b9916167ff5a49fcb02ac06424280a68d" - integrity sha512-5viTR33QV3S7O+bjruo1SaR40m7F2aUHJaDAC7fL9Ca6xji+aw1KFkpCtVlISS0G8vikUREGMJh+c/VMSc8Usw== +"@lerna/diff@3.18.5": + version "3.18.5" + resolved "https://registry.npmjs.org/@lerna/diff/-/diff-3.18.5.tgz#e9e2cb882f84d5b84f0487c612137305f07accbc" + integrity sha512-u90lGs+B8DRA9Z/2xX4YaS3h9X6GbypmGV6ITzx9+1Ga12UWGTVlKaCXBgONMBjzJDzAQOK8qPTwLA57SeBLgA== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/validation-error" "3.13.0" npmlog "^4.1.2" -"@lerna/exec@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/exec/-/exec-3.21.0.tgz#17f07533893cb918a17b41bcc566dc437016db26" - integrity sha512-iLvDBrIE6rpdd4GIKTY9mkXyhwsJ2RvQdB9ZU+/NhR3okXfqKc6py/24tV111jqpXTtZUW6HNydT4dMao2hi1Q== +"@lerna/exec@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/exec/-/exec-3.20.0.tgz#29f0c01aee2340eb46f90706731fef2062a49639" + integrity sha512-pS1mmC7kzV668rHLWuv31ClngqeXjeHC8kJuM+W2D6IpUVMGQHLcCTYLudFgQsuKGVpl0DGNYG+sjLhAPiiu6A== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/filter-options" "3.20.0" "@lerna/profiler" "3.20.0" "@lerna/run-topologically" "3.18.5" @@ -1999,13 +1999,13 @@ "@lerna/child-process" "3.16.5" semver "^6.2.0" -"@lerna/import@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/import/-/import-3.21.0.tgz#87b08f2a2bfeeff7357c6fd8490e638d3cd5b32d" - integrity sha512-aISkL4XD0Dqf5asDaOZWu65jgj8fWUhuQseZWuQe3UfHxav69fTS2YLIngUfencaOSZVOcVCom28YCzp61YDxw== +"@lerna/import@3.18.5": + version "3.18.5" + resolved "https://registry.npmjs.org/@lerna/import/-/import-3.18.5.tgz#a9c7d8601870729851293c10abd18b3707f7ba5e" + integrity sha512-PH0WVLEgp+ORyNKbGGwUcrueW89K3Iuk/DDCz8mFyG2IG09l/jOF0vzckEyGyz6PO5CMcz4TI1al/qnp3FrahQ== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/prompt" "3.18.5" "@lerna/pulse-till-done" "3.13.0" "@lerna/validation-error" "3.13.0" @@ -2013,43 +2013,43 @@ fs-extra "^8.1.0" p-map-series "^1.0.0" -"@lerna/info@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/info/-/info-3.21.0.tgz#76696b676fdb0f35d48c83c63c1e32bb5e37814f" - integrity sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA== +"@lerna/info@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/info/-/info-3.20.0.tgz#3a5212f3029f2bc6255f9533bdf4bcb120ef329a" + integrity sha512-Rsz+KQF9mczbGUbPTrtOed1N0C+cA08Qz0eX/oI+NNjvsryZIju/o7uedG4I3P55MBiAioNrJI88fHH3eTgYug== dependencies: - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/output" "3.13.0" envinfo "^7.3.1" -"@lerna/init@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/init/-/init-3.21.0.tgz#1e810934dc8bf4e5386c031041881d3b4096aa5c" - integrity sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg== +"@lerna/init@3.18.5": + version "3.18.5" + resolved "https://registry.npmjs.org/@lerna/init/-/init-3.18.5.tgz#86dd0b2b3290755a96975069b5cb007f775df9f5" + integrity sha512-oCwipWrha98EcJAHm8AGd2YFFLNI7AW9AWi0/LbClj1+XY9ah+uifXIgYGfTk63LbgophDd8936ZEpHMxBsbAg== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" fs-extra "^8.1.0" p-map "^2.1.0" write-json-file "^3.2.0" -"@lerna/link@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/link/-/link-3.21.0.tgz#8be68ff0ccee104b174b5bbd606302c2f06e9d9b" - integrity sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ== +"@lerna/link@3.18.5": + version "3.18.5" + resolved "https://registry.npmjs.org/@lerna/link/-/link-3.18.5.tgz#f24347e4f0b71d54575bd37cfa1794bc8ee91b18" + integrity sha512-xTN3vktJpkT7Nqc3QkZRtHO4bT5NvuLMtKNIBDkks0HpGxC9PRyyqwOoCoh1yOGbrWIuDezhfMg3Qow+6I69IQ== dependencies: - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/package-graph" "3.18.5" "@lerna/symlink-dependencies" "3.17.0" p-map "^2.1.0" slash "^2.0.0" -"@lerna/list@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/list/-/list-3.21.0.tgz#42f76fafa56dea13b691ec8cab13832691d61da2" - integrity sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg== +"@lerna/list@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/list/-/list-3.20.0.tgz#7e67cc29c5cf661cfd097e8a7c2d3dcce7a81029" + integrity sha512-fXTicPrfioVnRzknyPawmYIVkzDRBaQqk9spejS1S3O1DOidkihK0xxNkr8HCVC0L22w6f92g83qWDp2BYRUbg== dependencies: - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/filter-options" "3.20.0" "@lerna/listable" "3.18.5" "@lerna/output" "3.13.0" @@ -2195,7 +2195,25 @@ npmlog "^4.1.2" upath "^1.2.0" -"@lerna/project@3.21.0", "@lerna/project@^3.18.0": +"@lerna/project@3.18.0": + version "3.18.0" + resolved "https://registry.npmjs.org/@lerna/project/-/project-3.18.0.tgz#56feee01daeb42c03cbdf0ed8a2a10cbce32f670" + integrity sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA== + dependencies: + "@lerna/package" "3.16.0" + "@lerna/validation-error" "3.13.0" + cosmiconfig "^5.1.0" + dedent "^0.7.0" + dot-prop "^4.2.0" + glob-parent "^5.0.0" + globby "^9.2.0" + load-json-file "^5.3.0" + npmlog "^4.1.2" + p-map "^2.1.0" + resolve-from "^4.0.0" + write-json-file "^3.2.0" + +"@lerna/project@^3.18.0": version "3.21.0" resolved "https://registry.npmjs.org/@lerna/project/-/project-3.21.0.tgz#5d784d2d10c561a00f20320bcdb040997c10502d" integrity sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A== @@ -2221,10 +2239,10 @@ inquirer "^6.2.0" npmlog "^4.1.2" -"@lerna/publish@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/publish/-/publish-3.21.0.tgz#0112393125f000484c3f50caba71a547f91bd7f4" - integrity sha512-JZ+ehZB9UCQ9nqH8Ld/Yqc/If++aK/7XIubkrB9sQ5hf2GeIbmI/BrJpMgLW/e9T5bKrUBZPUvoUN3daVipA5A== +"@lerna/publish@3.20.2": + version "3.20.2" + resolved "https://registry.npmjs.org/@lerna/publish/-/publish-3.20.2.tgz#a45d29813099b3249657ea913d0dc3f8ebc5cc2e" + integrity sha512-N7Y6PdhJ+tYQPdI1tZum8W25cDlTp4D6brvRacKZusweWexxaopbV8RprBaKexkEX/KIbncuADq7qjDBdQHzaA== dependencies: "@evocateur/libnpmaccess" "^3.1.2" "@evocateur/npm-registry-fetch" "^4.0.0" @@ -2232,7 +2250,7 @@ "@lerna/check-working-tree" "3.16.5" "@lerna/child-process" "3.16.5" "@lerna/collect-updates" "3.20.0" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/describe-ref" "3.16.5" "@lerna/log-packed" "3.16.0" "@lerna/npm-conf" "3.16.0" @@ -2247,7 +2265,7 @@ "@lerna/run-lifecycle" "3.16.2" "@lerna/run-topologically" "3.18.5" "@lerna/validation-error" "3.13.0" - "@lerna/version" "3.21.0" + "@lerna/version" "3.20.2" figgy-pudding "^3.5.1" fs-extra "^8.1.0" npm-package-arg "^6.1.0" @@ -2310,12 +2328,12 @@ figgy-pudding "^3.5.1" p-queue "^4.0.0" -"@lerna/run@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/run/-/run-3.21.0.tgz#2a35ec84979e4d6e42474fe148d32e5de1cac891" - integrity sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q== +"@lerna/run@3.20.0": + version "3.20.0" + resolved "https://registry.npmjs.org/@lerna/run/-/run-3.20.0.tgz#a479f7c42bdf9ebabb3a1e5a2bdebb7a8d201151" + integrity sha512-9U3AqeaCeB7KsGS9oyKNp62s9vYoULg/B4cqXTKZkc+OKL6QOEjYHYVSBcMK9lUXrMjCjDIuDSX3PnTCPxQ2Dw== dependencies: - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/filter-options" "3.20.0" "@lerna/npm-run-script" "3.16.5" "@lerna/output" "3.13.0" @@ -2360,15 +2378,15 @@ dependencies: npmlog "^4.1.2" -"@lerna/version@3.21.0": - version "3.21.0" - resolved "https://registry.npmjs.org/@lerna/version/-/version-3.21.0.tgz#5bcc3d2de9eb8f4db18efb0d88973f9a509eccc3" - integrity sha512-nIT3u43fCNj6uSMN1dRxFnF4GhmIiOEqSTkGSjrMU+8kHKwzOqS/6X6TOzklBmCyEZOpF/fLlGqH3BZHnwLDzQ== +"@lerna/version@3.20.2": + version "3.20.2" + resolved "https://registry.npmjs.org/@lerna/version/-/version-3.20.2.tgz#3709141c0f537741d9bc10cb24f56897bcb30428" + integrity sha512-ckBJMaBWc+xJen0cMyCE7W67QXLLrc0ELvigPIn8p609qkfNM0L0CF803MKxjVOldJAjw84b8ucNWZLvJagP/Q== dependencies: "@lerna/check-working-tree" "3.16.5" "@lerna/child-process" "3.16.5" "@lerna/collect-updates" "3.20.0" - "@lerna/command" "3.21.0" + "@lerna/command" "3.18.5" "@lerna/conventional-commits" "3.18.5" "@lerna/github-client" "3.16.5" "@lerna/gitlab-client" "3.15.0" @@ -2698,14 +2716,12 @@ react-lifecycles-compat "^3.0.4" "@rollup/plugin-commonjs@^11.0.2": - version "11.1.0" - resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.1.0.tgz#60636c7a722f54b41e419e1709df05c7234557ef" - integrity sha512-Ycr12N3ZPN96Fw2STurD21jMqzKwL9QuFhms3SD7KKRK7oaXUsBU9Zt0jL/rOPHiPYisI21/rXGO3jr9BnLHUA== + version "11.0.2" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.2.tgz#837cc6950752327cb90177b608f0928a4e60b582" + integrity sha512-MPYGZr0qdbV5zZj8/2AuomVpnRVXRU5XKXb3HVniwRoRCreGlf5kOE081isNWeiLIi6IYkwTX9zE0/c7V8g81g== dependencies: - "@rollup/pluginutils" "^3.0.8" - commondir "^1.0.1" + "@rollup/pluginutils" "^3.0.0" estree-walker "^1.0.1" - glob "^7.1.2" is-reference "^1.1.2" magic-string "^0.25.2" resolve "^1.11.0" @@ -2728,7 +2744,7 @@ is-module "^1.0.0" resolve "^1.14.2" -"@rollup/pluginutils@^3.0.10", "@rollup/pluginutils@^3.0.8": +"@rollup/pluginutils@^3.0.0", "@rollup/pluginutils@^3.0.10", "@rollup/pluginutils@^3.0.8": version "3.0.10" resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.10.tgz#a659b9025920378494cd8f8c59fbf9b3a50d5f12" integrity sha512-d44M7t+PjmMrASHbhgpSbVgtL6EFyX7J4mYxwQ/c5eoaE6N2VgCgEcWVzNnwycIloti+/MpwFr8qfw+nRw00sw== @@ -4039,6 +4055,14 @@ "@types/node" "*" "@types/range-parser" "*" +"@types/express-session@1.17.0": + version "1.17.0" + resolved "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.0.tgz#770daf81368f6278e3e40dd894e1e52abbdca0cd" + integrity sha512-OQEHeBFE1UhChVIBhRh9qElHUvTp4BzKKHxMDkGHT7WuYk5eL93hPG7D8YAIkoBSbhNEY0RjreF15zn+U0eLjA== + dependencies: + "@types/express" "*" + "@types/node" "*" + "@types/express@*", "@types/express@^4.17.6": version "4.17.6" resolved "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz#6bce49e49570507b86ea1b07b806f04697fac45e" @@ -4170,9 +4194,9 @@ pretty-format "^25.2.1" "@types/jest@^25.2.2": - version "25.2.2" - resolved "https://registry.npmjs.org/@types/jest/-/jest-25.2.2.tgz#6a752e7a00f69c3e790ea00c345029d5cefa92bf" - integrity sha512-aRctFbG8Pb7DSLzUt/fEtL3q/GKb9mretFuYhRub2J0q6NhzBYbx9HTQzHrWgBNIxYOlxGNVe6Z54cpbUt+Few== + version "25.2.3" + resolved "https://registry.npmjs.org/@types/jest/-/jest-25.2.3.tgz#33d27e4c4716caae4eced355097a47ad363fdcaf" + integrity sha512-JXc1nK/tXHiDhV55dvfzqtmP4S3sy3T3ouV2tkViZgxY/zeUkcpQcQPGRlgF4KmWzWW5oiWYSZwtCB+2RsE4Fw== dependencies: jest-diff "^25.2.1" pretty-format "^25.2.1" @@ -4262,6 +4286,13 @@ resolved "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.2.tgz#d070fe6a6b78755d1092a3dc492d34c3d8f871c4" integrity sha512-4QQmOF5KlwfxJ5IGXFIudkeLCdMABz03RcUXu+LCb24zmln8QW6aDjuGl4d4XPVLf2j+FnjelHTP7dvceAFbhA== +"@types/oauth@*": + version "0.9.1" + resolved "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.1.tgz#e17221e7f7936b0459ae7d006255dff61adca305" + integrity sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A== + dependencies: + "@types/node" "*" + "@types/ora@^3.2.0": version "3.2.0" resolved "https://registry.npmjs.org/@types/ora/-/ora-3.2.0.tgz#b2f65d1283a8f36d8b0f9ee767e0732a2f429362" @@ -4274,6 +4305,31 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/passport-google-oauth20@2.0.3": + version "2.0.3" + resolved "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.3.tgz#f554ff6d39f395acff3f1d762e54462194dac8da" + integrity sha512-6EUEGzEg4acwowvgR/yVZIj8S2Kkwc6JmlY2/wnM1wJHNz20o7s1TIGrxnah8ymLgJasYDpy95P3TMMqlmetPw== + dependencies: + "@types/express" "*" + "@types/passport" "*" + "@types/passport-oauth2" "*" + +"@types/passport-oauth2@*": + version "1.4.9" + resolved "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.9.tgz#134007c4b505a82548c9cb19094c5baeb2205c92" + integrity sha512-QP0q+NVQOaIu2r0e10QWkiUA0Ya5mOBHRJN0UrI+LolMLOP1/VN4EVIpJ3xVwFo+xqNFRoFvFwJhBvKnk7kpUA== + dependencies: + "@types/express" "*" + "@types/oauth" "*" + "@types/passport" "*" + +"@types/passport@*", "@types/passport@1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@types/passport/-/passport-1.0.3.tgz#e459ed6c262bf0686684d1b05901be0d0b192a9c" + integrity sha512-nyztuxtDPQv9utCzU0qW7Gl8BY2Dn8BKlYAFFyxKipFxjaVd96celbkLCV/tRqqBUZ+JB8If3UfgV8347DTo3Q== + dependencies: + "@types/express" "*" + "@types/prettier@^2.0.0": version "2.0.0" resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4" @@ -4554,9 +4610,9 @@ "@types/jest" "*" "@types/testing-library__jest-dom@^5.0.4": - version "5.6.0" - resolved "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.6.0.tgz#325e97aacb7e4a66693e7face8a2c04f936f4a4b" - integrity sha512-VRl4kIzvtySjscCpMul3mz0UgEd40nG/jWluaXIYi5UG8cOOLD56u8IIgHZk+gSKmccRCsVv7AAg1HBmE7OQ2w== + version "5.0.4" + resolved "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.0.4.tgz#c7bfbafb920cd1ce40506474e70ee73637f33701" + integrity sha512-Ns69aaNvlxvXkPxIwsqeaWH5vJpwa/pdBIlf8LGkRnbV3tiqUgifs13moLXg1NQ2AM23qRR5CtHarNshvRyEdA== dependencies: "@types/jest" "*" @@ -4614,9 +4670,9 @@ source-map "^0.6.1" "@types/webpack@*", "@types/webpack@^4.41.7": - version "4.41.13" - resolved "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.13.tgz#988d114c8913d039b8a0e0502a7fe4f1f84f3d5e" - integrity sha512-RYmIHOWSxnTTa765N6jJBVE45pd2SYNblEYshVDduLw6RhocazNmRzE5/ytvBD8IkDMH6DI+bcrqxh8NILimBA== + version "4.41.12" + resolved "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.12.tgz#0386ee2a2814368e2f2397abb036c0bf173ff6c3" + integrity sha512-BpCtM4NnBen6W+KEhrL9jKuZCXVtiH6+0b6cxdvNt2EwU949Al334PjQSl2BeAyvAX9mgoNNG21wvjP3xZJJ5w== dependencies: "@types/anymatch" "*" "@types/node" "*" @@ -5866,6 +5922,11 @@ base64-js@^1.0.2: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + base@^0.11.1: version "0.11.2" resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -9313,6 +9374,20 @@ express-promise-router@^3.0.3: lodash.flattendeep "^4.0.0" methods "^1.0.0" +express-session@1.17.1: + version "1.17.1" + resolved "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357" + integrity sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q== + dependencies: + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~2.0.0" + on-headers "~1.0.2" + parseurl "~1.3.3" + safe-buffer "5.2.0" + uid-safe "~2.1.5" + express@^4.17.0, express@^4.17.1: version "4.17.1" resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -13422,26 +13497,26 @@ left-pad@^1.3.0: integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== lerna@^3.20.2: - version "3.21.0" - resolved "https://registry.npmjs.org/lerna/-/lerna-3.21.0.tgz#c81a0f8df45c6b7c9d3fc9fdcd0f846aca2375c6" - integrity sha512-ux8yOwQEgIXOZVUfq+T8nVzPymL19vlIoPbysOP3YA4hcjKlqQIlsjI/1ugBe6b4MF7W4iV5vS3gH9cGqBBc1A== + version "3.20.2" + resolved "https://registry.npmjs.org/lerna/-/lerna-3.20.2.tgz#abf84e73055fe84ee21b46e64baf37b496c24864" + integrity sha512-bjdL7hPLpU3Y8CBnw/1ys3ynQMUjiK6l9iDWnEGwFtDy48Xh5JboR9ZJwmKGCz9A/sarVVIGwf1tlRNKUG9etA== dependencies: - "@lerna/add" "3.21.0" - "@lerna/bootstrap" "3.21.0" - "@lerna/changed" "3.21.0" - "@lerna/clean" "3.21.0" + "@lerna/add" "3.20.0" + "@lerna/bootstrap" "3.20.0" + "@lerna/changed" "3.20.0" + "@lerna/clean" "3.20.0" "@lerna/cli" "3.18.5" - "@lerna/create" "3.21.0" - "@lerna/diff" "3.21.0" - "@lerna/exec" "3.21.0" - "@lerna/import" "3.21.0" - "@lerna/info" "3.21.0" - "@lerna/init" "3.21.0" - "@lerna/link" "3.21.0" - "@lerna/list" "3.21.0" - "@lerna/publish" "3.21.0" - "@lerna/run" "3.21.0" - "@lerna/version" "3.21.0" + "@lerna/create" "3.18.5" + "@lerna/diff" "3.18.5" + "@lerna/exec" "3.20.0" + "@lerna/import" "3.18.5" + "@lerna/info" "3.20.0" + "@lerna/init" "3.18.5" + "@lerna/link" "3.18.5" + "@lerna/list" "3.20.0" + "@lerna/publish" "3.20.2" + "@lerna/run" "3.20.0" + "@lerna/version" "3.20.2" import-local "^2.0.0" npmlog "^4.1.2" @@ -15405,6 +15480,11 @@ oauth-sign@~0.9.0: resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +oauth@0.9.x: + version "0.9.15" + resolved "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE= + object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -16075,6 +16155,37 @@ pascalcase@^0.1.1: resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= +passport-google-oauth20@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" + integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== + dependencies: + passport-oauth2 "1.x.x" + +passport-oauth2@1.x.x: + version "1.5.0" + resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108" + integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ== + dependencies: + base64url "3.x.x" + oauth "0.9.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x: + version "1.0.0" + resolved "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= + +passport@0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + patch-package@^6.2.2: version "6.2.2" resolved "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" @@ -16204,6 +16315,11 @@ pause-stream@0.0.11: dependencies: through "~2.3" +pause@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -17148,6 +17264,11 @@ ramda@^0.21.0: resolved "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs= + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -18473,7 +18594,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.0, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -19056,10 +19177,10 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.12: - version "0.5.19" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== +source-map-support@^0.5.6, source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -20377,14 +20498,14 @@ ts-loader@^7.0.4: semver "^6.0.0" ts-node@^8.6.2: - version "8.10.1" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-8.10.1.tgz#77da0366ff8afbe733596361d2df9a60fc9c9bd3" - integrity sha512-bdNz1L4ekHiJul6SHtZWs1ujEKERJnHs4HxN7rjTyyVOFf3HaJ6sLqe6aPG62XTzAB/63pKRh5jTSWL0D7bsvw== + version "8.8.1" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-8.8.1.tgz#7c4d3e9ed33aa703b64b28d7f9d194768be5064d" + integrity sha512-10DE9ONho06QORKAaCBpPiFCdW+tZJuY/84tyypGtl6r+/C7Asq0dhqbRZURuUlLQtZxxDvT8eoj8cGW0ha6Bg== dependencies: arg "^4.1.0" diff "^4.0.1" make-error "^1.1.1" - source-map-support "^0.5.17" + source-map-support "^0.5.6" yn "3.1.1" ts-pnp@^1.1.2: @@ -20393,9 +20514,9 @@ ts-pnp@^1.1.2: integrity sha512-CrG5GqAAzMT7144Cl+UIFP7mz/iIhiy+xQ6GGcnjTezhALT02uPMRw7tgDSESgB5MsfKt55+GPWw4ir1kVtMIQ== tsc-watch@^4.2.3: - version "4.2.6" - resolved "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.2.6.tgz#c0903e9f15a882b78481d80cba170731b7fe2779" - integrity sha512-YLWyWFrL6mmA13yveULg1bJYrizlkTjqJ4d6Fi3dCgxbfK6jE8HcqoFHKLAsP5mWn0PKhOEf3hhqE7Egjpflfg== + version "4.2.5" + resolved "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.2.5.tgz#3ee680cfd02087bb76cbecd2d5f290a0d6302454" + integrity sha512-scXpL5SFJevvtKOtQIRxJvyEwCKSIZS9bDrO/cy/dWlETTVwSlfRm2WmakdRPM0Rg90DbYyJjkUr2z74HXcxzQ== dependencies: cross-spawn "^5.1.0" node-cleanup "^2.1.2" @@ -20535,6 +20656,18 @@ uid-number@0.0.6: resolved "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= +uid-safe@~2.1.5: + version "2.1.5" + resolved "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" + integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== + dependencies: + random-bytes "~1.0.0" + +uid2@0.0.x: + version "0.0.3" + resolved "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= + umask@^1.1.0, umask@~1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" @@ -20923,7 +21056,7 @@ utila@^0.4.0, utila@~0.4: resolved "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= -utils-merge@1.0.1: +utils-merge@1.0.1, utils-merge@1.x.x: version "1.0.1" resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= From 422d85b67da28eb844faa78c8fae1257463112de Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Mon, 18 May 2020 22:24:39 +0200 Subject: [PATCH 03/10] move provider factories from router to src/providers --- plugins/auth-backend/src/providers/config.ts | 9 -- .../src/providers/google/provider.ts | 67 ++++++++++ .../src/providers/google/router.ts | 34 ----- plugins/auth-backend/src/providers/index.ts | 17 +++ plugins/auth-backend/src/providers/types.ts | 44 +++++++ plugins/auth-backend/src/service/router.ts | 124 +----------------- 6 files changed, 130 insertions(+), 165 deletions(-) create mode 100644 plugins/auth-backend/src/providers/google/provider.ts delete mode 100644 plugins/auth-backend/src/providers/google/router.ts create mode 100644 plugins/auth-backend/src/providers/index.ts create mode 100644 plugins/auth-backend/src/providers/types.ts diff --git a/plugins/auth-backend/src/providers/config.ts b/plugins/auth-backend/src/providers/config.ts index b899347938..92d50ee208 100644 --- a/plugins/auth-backend/src/providers/config.ts +++ b/plugins/auth-backend/src/providers/config.ts @@ -8,13 +8,4 @@ export const providers = [ passReqToCallback: true, }, }, - // { - // provider: 'github', - // options: { - // clientID: process.env.GITHUB_CLIENT_ID!, - // clientSecret: process.env.GITHUB_CLIENT_SECRET!, - // callbackURL: 'http://localhost:7000/auth/github/handler/frame', - // passReqToCallback: true, - // }, - // }, ]; diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts new file mode 100644 index 0000000000..ddbb42c98b --- /dev/null +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -0,0 +1,67 @@ +import passport from 'passport'; +import express from 'express'; +import Router from 'express-promise-router'; +import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; +import { AuthProviderHandlers, AuthResponse } from './../types'; + +export const provider = { + makeStrategy(options: any): passport.Strategy { + return new GoogleStrategy(options, function ( + _req: any, + accessToken: any, + refreshToken: any, + profile: any, + cb: any, + ) { + cb(undefined, { profile, accessToken, refreshToken }); + }); + }, + makeRouter(handlers: AuthProviderHandlers): express.Router { + const router = Router(); + router.get('/start', handlers.start); + router.get('/handler/frame', handlers.handle); + router.get('/logout', handlers.logout); + if (handlers.refresh) { + router.get('/refreshToken', handlers.refresh); + } + return router; + }, +}; + +export const GoogleAuthProviderHandler: AuthProviderHandlers = { + start(req, res, next) { + return passport.authenticate('google', { + scope: ['profile', 'email'], + accessType: 'offline', + prompt: 'consent', + state: '8745634875963', + })(req, res, next); + }, + handle(req, res, next) { + return passport.authenticate('google', function (_, user) { + postMessageResponse(res, { + type: 'oauth-result', + payload: user, + }); + })(req, res, next); + }, + logout(_req, res, _next) { + return res.send('logout!'); + }, +}; + +const postMessageResponse = (res: express.Response, data: AuthResponse) => { + const jsonData = JSON.stringify(data); + const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); + + res.setHeader('X-Frame-Options', 'sameorigin'); + res.end(` + + + + + + `); +}; diff --git a/plugins/auth-backend/src/providers/google/router.ts b/plugins/auth-backend/src/providers/google/router.ts deleted file mode 100644 index 73f5ee6f9d..0000000000 --- a/plugins/auth-backend/src/providers/google/router.ts +++ /dev/null @@ -1,34 +0,0 @@ -import express from 'express'; -import Router from 'express-promise-router'; -import passport from 'passport'; - -export const router = Router(); -router.get('/start', (req, res, next) => { - passport.authenticate('google', { - scope: ['profile', 'email'], - accessType: 'offline', - prompt: 'consent', - state: '8745634875963', - })(req, res, next); -}); - -router.get('/handler/frame', passport.authenticate('google'), function ( - req, - res, -) { - console.log('DEBUG: req.session.passport.user', req.session?.passport.user); - console.log('DEBUG: req.params =', req.params); - console.log('DEBUG: req.url =', req.url); - res.send('yay!'); -}); - -router.get('/logout', async (_req: express.Request, res: express.Response) => { - res.send('google provider logout'); -}); - -router.get( - '/refreshToken', - async (_req: express.Request, res: express.Response) => { - res.send('google provider refreshToken'); - }, -); diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts new file mode 100644 index 0000000000..3cb2b6a018 --- /dev/null +++ b/plugins/auth-backend/src/providers/index.ts @@ -0,0 +1,17 @@ +import { AuthProvider } from './types'; +import { + provider as GoogleAuthProvider, + GoogleAuthProviderHandler, +} from './google/provider'; + +const providerFactories: AuthProvider = { + google: GoogleAuthProvider, +}; + +export const makeProvider = (config: any) => { + const provider = config.provider; + const providerFactory = providerFactories[provider]; + const strategy = providerFactory.makeStrategy(config.options); + const providerRouter = providerFactory.makeRouter(GoogleAuthProviderHandler); + return { provider, strategy, providerRouter }; +}; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts new file mode 100644 index 0000000000..442ab405e2 --- /dev/null +++ b/plugins/auth-backend/src/providers/types.ts @@ -0,0 +1,44 @@ +import express from 'express'; +import passport from 'passport'; + +export type AuthProviderHandlers = { + start( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): Promise; + handle( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): express.Response; + refresh?( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): Promise; + logout( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ): express.Response; +}; + +export type AuthProvider = { + [key: string]: { + makeStrategy(options: any): passport.Strategy; + makeRouter(handlers: AuthProviderHandlers): express.Router; + }; +}; + +export type AuthInfo = { + profile: passport.Profile; + accessToken: string; + refreshToken?: string; + expiresAt?: number; +}; + +export type AuthResponse = { + type: string; + payload: AuthInfo; +}; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index ae0f3d822b..b22dbe310c 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -17,139 +17,23 @@ import express from 'express'; import Router from 'express-promise-router'; import passport from 'passport'; -import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; import { Logger } from 'winston'; import { providers } from './../providers/config'; +import { makeProvider } from '../providers'; export interface RouterOptions { logger: Logger; } -type AuthProviderHandlers = { - start( - req: express.Request, - res: express.Response, - next: express.NextFunction, - ): Promise; - handle( - req: express.Request, - res: express.Response, - next: express.NextFunction, - ): express.Response; - refresh?( - req: express.Request, - res: express.Response, - next: express.NextFunction, - ): Promise; - logout( - req: express.Request, - res: express.Response, - next: express.NextFunction, - ): express.Response; -}; - -type AuthProvider = { - [key: string]: { - makeStrategy(options: any): passport.Strategy; - makeRouter(handlers: AuthProviderHandlers): express.Router; - }; -}; - -type AuthInfo = { - profile: passport.Profile; - accessToken: string; - refreshToken?: string; - expiresAt?: number; -}; - -type AuthResponse = { - type: string; - payload: AuthInfo; -}; - -const postMessageResponse = (res: express.Response, data: AuthResponse) => { - const jsonData = JSON.stringify(data); - const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); - - res.setHeader('X-Frame-Options', 'sameorigin'); - res.end(` - - - - - - `); -}; - -const GoogleAuthProviderHandler: AuthProviderHandlers = { - start(req, res, next) { - return passport.authenticate('google', { - scope: ['profile', 'email'], - accessType: 'offline', - prompt: 'consent', - state: '8745634875963', - })(req, res, next); - }, - handle(req, res, next) { - return passport.authenticate('google', function (_, user) { - postMessageResponse(res, { - type: 'oauth-result', - payload: user, - }); - })(req, res, next); - }, - logout(_req, res, _next) { - return res.send('logout!'); - }, -}; - -const providerFactories: AuthProvider = { - google: { - makeStrategy(options: any): passport.Strategy { - return new GoogleStrategy(options, function ( - _req: any, - accessToken: any, - refreshToken: any, - profile: any, - cb: any, - ) { - cb(undefined, { profile, accessToken, refreshToken }); - }); - }, - makeRouter(handlers: AuthProviderHandlers): express.Router { - const router = Router(); - router.get('/start', handlers.start); - router.get('/handler/frame', handlers.handle); - router.get('/logout', handlers.logout); - if (handlers.refresh) { - router.get('/refreshToken', handlers.refresh); - } - return router; - }, - }, -}; - -function makeProvider(config: any) { - const provider = config.provider; - const providerFactory = providerFactories[provider]; - const strategy: passport.Strategy = providerFactory.makeStrategy( - config.options, - ); - const providerRouter = providerFactory.makeRouter(GoogleAuthProviderHandler); - return { provider, strategy, providerRouter }; -} - export async function createRouter( options: RouterOptions, ): Promise { const router = Router(); + // configure all the providers for (const providerConfig of providers) { const { provider, strategy, providerRouter } = makeProvider(providerConfig); passport.use(strategy); - router.use(`/${provider}`, providerRouter); } @@ -164,9 +48,5 @@ export async function createRouter( router.use(passport.initialize()); router.use(passport.session()); - router.get('/ping', async (_req, res) => { - res.status(200).send('pong'); - }); - return router; } From 79ace9081113bd3c620b6fadca0288b5bd57e271 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Tue, 19 May 2020 12:45:35 +0200 Subject: [PATCH 04/10] Intermediary step before moving to class --- plugins/auth-backend/src/providers/config.ts | 1 - .../src/providers/google/provider.ts | 59 ++++++++++++------- plugins/auth-backend/src/providers/index.ts | 7 +-- plugins/auth-backend/src/providers/types.ts | 2 +- 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/plugins/auth-backend/src/providers/config.ts b/plugins/auth-backend/src/providers/config.ts index 92d50ee208..b8df8b7e99 100644 --- a/plugins/auth-backend/src/providers/config.ts +++ b/plugins/auth-backend/src/providers/config.ts @@ -5,7 +5,6 @@ export const providers = [ clientID: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, callbackURL: 'http://localhost:7000/auth/google/handler/frame', - passReqToCallback: true, }, }, ]; diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index ddbb42c98b..0754e0abc0 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -6,35 +6,54 @@ import { AuthProviderHandlers, AuthResponse } from './../types'; export const provider = { makeStrategy(options: any): passport.Strategy { - return new GoogleStrategy(options, function ( - _req: any, - accessToken: any, - refreshToken: any, - profile: any, - cb: any, - ) { - cb(undefined, { profile, accessToken, refreshToken }); - }); + return new GoogleStrategy( + { ...options, passReqToCallback: true }, + function ( + _req: any, + accessToken: any, + refreshToken: any, + profile: any, + cb: any, + ) { + cb(undefined, { profile, accessToken, refreshToken }); + }, + ); }, - makeRouter(handlers: AuthProviderHandlers): express.Router { - const router = Router(); - router.get('/start', handlers.start); - router.get('/handler/frame', handlers.handle); - router.get('/logout', handlers.logout); - if (handlers.refresh) { - router.get('/refreshToken', handlers.refresh); - } - return router; + makeRouter(): express.Router { + return defaultRouter(GoogleAuthProviderHandler); }, }; +const defaultRouter = (handlers: AuthProviderHandlers) => { + const router = Router(); + router.get('/start', handlers.start); + router.get('/handler/frame', handlers.handle); + router.get('/logout', handlers.logout); + if (handlers.refresh) { + router.get('/refreshToken', handlers.refresh); + } + return router; +}; + +// Make this a class +// add a getStrategy method +// pass the config as a new constructor + +// class GoogleAuthProvider implements AuthProviderHandlers { +// config: any; +// constructor(config: any) { +// this.config = config; +// } + +// } + export const GoogleAuthProviderHandler: AuthProviderHandlers = { start(req, res, next) { + const scopes = req.query.scopes?.toString().split(','); return passport.authenticate('google', { - scope: ['profile', 'email'], + scope: scopes, accessType: 'offline', prompt: 'consent', - state: '8745634875963', })(req, res, next); }, handle(req, res, next) { diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 3cb2b6a018..7bfd10224e 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -1,8 +1,5 @@ import { AuthProvider } from './types'; -import { - provider as GoogleAuthProvider, - GoogleAuthProviderHandler, -} from './google/provider'; +import { provider as GoogleAuthProvider } from './google/provider'; const providerFactories: AuthProvider = { google: GoogleAuthProvider, @@ -12,6 +9,6 @@ export const makeProvider = (config: any) => { const provider = config.provider; const providerFactory = providerFactories[provider]; const strategy = providerFactory.makeStrategy(config.options); - const providerRouter = providerFactory.makeRouter(GoogleAuthProviderHandler); + const providerRouter = providerFactory.makeRouter(); return { provider, strategy, providerRouter }; }; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 442ab405e2..d76b1c74fe 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -27,7 +27,7 @@ export type AuthProviderHandlers = { export type AuthProvider = { [key: string]: { makeStrategy(options: any): passport.Strategy; - makeRouter(handlers: AuthProviderHandlers): express.Router; + makeRouter(): express.Router; }; }; From 50658a166b99565157684e9d0e0d9c30a54f7849 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Tue, 19 May 2020 14:20:46 +0200 Subject: [PATCH 05/10] Remove github provider. Refactored Google provider to be a class --- .../src/providers/github/router.ts | 22 ---- .../src/providers/google/provider.ts | 102 +++++++++--------- plugins/auth-backend/src/providers/index.ts | 29 +++-- plugins/auth-backend/src/providers/types.ts | 28 +++-- 4 files changed, 89 insertions(+), 92 deletions(-) delete mode 100644 plugins/auth-backend/src/providers/github/router.ts diff --git a/plugins/auth-backend/src/providers/github/router.ts b/plugins/auth-backend/src/providers/github/router.ts deleted file mode 100644 index a1c6efa64f..0000000000 --- a/plugins/auth-backend/src/providers/github/router.ts +++ /dev/null @@ -1,22 +0,0 @@ -import express from 'express'; -import Router from 'express-promise-router'; - -export const router = Router(); -router.get('/', async (_req: express.Request, res: express.Response) => { - res.send('initiate auth'); -}); - -router.get('/login', async (_req: express.Request, res: express.Response) => { - res.send('github provider login'); -}); - -router.get('/logout', async (_req: express.Request, res: express.Response) => { - res.send('github provider logout'); -}); - -router.get( - '/handler/frame', - async (req: express.Request, res: express.Response) => { - res.send('github provider frame response handler'); - }, -); diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 0754e0abc0..94f6ca7fcc 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -1,13 +1,55 @@ import passport from 'passport'; import express from 'express'; -import Router from 'express-promise-router'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; -import { AuthProviderHandlers, AuthResponse } from './../types'; +import { + AuthProvider, + AuthProviderRouteHandlers, + AuthResponse, +} from './../types'; -export const provider = { - makeStrategy(options: any): passport.Strategy { +export class GoogleAuthProvider + implements AuthProvider, AuthProviderRouteHandlers { + providerConfig: any; + constructor(providerConfig: any) { + this.providerConfig = providerConfig; + } + + start( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ) { + const scopes = req.query.scopes?.toString().split(','); + return passport.authenticate('google', { + scope: scopes, + accessType: 'offline', + prompt: 'consent', + })(req, res, next); + } + frameHandler( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ) { + return passport.authenticate('google', function (_, user) { + postMessageResponse(res, { + type: 'auth-result', + payload: user, + }); + })(req, res, next); + } + + logout( + req: express.Request, + res: express.Response, + next: express.NextFunction, + ) { + return res.send('logout!'); + } + + strategy(): passport.Strategy { return new GoogleStrategy( - { ...options, passReqToCallback: true }, + { ...this.providerConfig.options, passReqToCallback: true }, function ( _req: any, accessToken: any, @@ -18,56 +60,8 @@ export const provider = { cb(undefined, { profile, accessToken, refreshToken }); }, ); - }, - makeRouter(): express.Router { - return defaultRouter(GoogleAuthProviderHandler); - }, -}; - -const defaultRouter = (handlers: AuthProviderHandlers) => { - const router = Router(); - router.get('/start', handlers.start); - router.get('/handler/frame', handlers.handle); - router.get('/logout', handlers.logout); - if (handlers.refresh) { - router.get('/refreshToken', handlers.refresh); } - return router; -}; - -// Make this a class -// add a getStrategy method -// pass the config as a new constructor - -// class GoogleAuthProvider implements AuthProviderHandlers { -// config: any; -// constructor(config: any) { -// this.config = config; -// } - -// } - -export const GoogleAuthProviderHandler: AuthProviderHandlers = { - start(req, res, next) { - const scopes = req.query.scopes?.toString().split(','); - return passport.authenticate('google', { - scope: scopes, - accessType: 'offline', - prompt: 'consent', - })(req, res, next); - }, - handle(req, res, next) { - return passport.authenticate('google', function (_, user) { - postMessageResponse(res, { - type: 'oauth-result', - payload: user, - }); - })(req, res, next); - }, - logout(_req, res, _next) { - return res.send('logout!'); - }, -}; +} const postMessageResponse = (res: express.Response, data: AuthResponse) => { const jsonData = JSON.stringify(data); diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 7bfd10224e..ea58df2fad 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -1,14 +1,31 @@ -import { AuthProvider } from './types'; -import { provider as GoogleAuthProvider } from './google/provider'; +import Router from 'express-promise-router'; +import { AuthProviderRouteHandlers, AuthProviderFactories } from './types'; -const providerFactories: AuthProvider = { +import { GoogleAuthProvider } from './google/provider'; + +const providerFactories: AuthProviderFactories = { google: GoogleAuthProvider, }; export const makeProvider = (config: any) => { const provider = config.provider; - const providerFactory = providerFactories[provider]; - const strategy = providerFactory.makeStrategy(config.options); - const providerRouter = providerFactory.makeRouter(); + const providerImpl = providerFactories[provider]; + if (!providerImpl) { + throw Error(`Provider Implementation missing for provider: ${provider}`); + } + const providerInstance = new providerImpl(config); + const strategy = providerInstance.strategy(); + const providerRouter = defaultRouter(providerInstance); return { provider, strategy, providerRouter }; }; + +export const defaultRouter = (provider: AuthProviderRouteHandlers) => { + const router = Router(); + router.get('/start', provider.start); + router.get('/handler/frame', provider.frameHandler); + router.get('/logout', provider.logout); + if (provider.refresh) { + router.get('/refreshToken', provider.refresh); + } + return router; +}; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index d76b1c74fe..1a9c609724 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -1,13 +1,13 @@ import express from 'express'; import passport from 'passport'; -export type AuthProviderHandlers = { +export interface AuthProviderRouteHandlers { start( req: express.Request, res: express.Response, next: express.NextFunction, ): Promise; - handle( + frameHandler( req: express.Request, res: express.Response, next: express.NextFunction, @@ -22,12 +22,15 @@ export type AuthProviderHandlers = { res: express.Response, next: express.NextFunction, ): express.Response; -}; +} +export interface AuthProvider { + strategy(): passport.Strategy; + router?(): express.Router; +} -export type AuthProvider = { +export type AuthProviderFactories = { [key: string]: { - makeStrategy(options: any): passport.Strategy; - makeRouter(): express.Router; + new (providerConfig: any): AuthProvider & AuthProviderRouteHandlers; }; }; @@ -38,7 +41,12 @@ export type AuthInfo = { expiresAt?: number; }; -export type AuthResponse = { - type: string; - payload: AuthInfo; -}; +export type AuthResponse = + | { + type: 'auth-result'; + payload: AuthInfo; + } + | { + type: 'auth-result'; + error: Error | undefined; + }; From 2dcdfd848030280ebc5a687e8fb29c67ea3c660a Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Tue, 19 May 2020 14:44:32 +0200 Subject: [PATCH 06/10] remove unused imports. remove express-session module --- plugins/auth-backend/package.json | 2 -- .../src/service/standaloneApplication.ts | 2 -- yarn.lock | 36 +------------------ 3 files changed, 1 insertion(+), 39 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a66ac42006..02c3122dd3 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -20,7 +20,6 @@ "cors": "^2.8.5", "express": "^4.17.1", "express-promise-router": "^3.0.3", - "express-session": "1.17.1", "fs-extra": "^9.0.0", "helmet": "^3.22.0", "morgan": "^1.10.0", @@ -34,7 +33,6 @@ "jest-fetch-mock": "^3.0.3", "tsc-watch": "^4.2.3", "@types/passport": "1.0.3", - "@types/express-session": "1.17.0", "@types/passport-google-oauth20": "2.0.3" }, "files": [ diff --git a/plugins/auth-backend/src/service/standaloneApplication.ts b/plugins/auth-backend/src/service/standaloneApplication.ts index d2d817c342..5eea4fb8f5 100644 --- a/plugins/auth-backend/src/service/standaloneApplication.ts +++ b/plugins/auth-backend/src/service/standaloneApplication.ts @@ -23,8 +23,6 @@ import compression from 'compression'; import cors from 'cors'; import express from 'express'; import helmet from 'helmet'; -import passport from 'passport'; -import session from 'express-session'; import { Logger } from 'winston'; import { createRouter } from './router'; diff --git a/yarn.lock b/yarn.lock index 745978eeb6..a880f92a9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4055,14 +4055,6 @@ "@types/node" "*" "@types/range-parser" "*" -"@types/express-session@1.17.0": - version "1.17.0" - resolved "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.0.tgz#770daf81368f6278e3e40dd894e1e52abbdca0cd" - integrity sha512-OQEHeBFE1UhChVIBhRh9qElHUvTp4BzKKHxMDkGHT7WuYk5eL93hPG7D8YAIkoBSbhNEY0RjreF15zn+U0eLjA== - dependencies: - "@types/express" "*" - "@types/node" "*" - "@types/express@*", "@types/express@^4.17.6": version "4.17.6" resolved "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz#6bce49e49570507b86ea1b07b806f04697fac45e" @@ -9374,20 +9366,6 @@ express-promise-router@^3.0.3: lodash.flattendeep "^4.0.0" methods "^1.0.0" -express-session@1.17.1: - version "1.17.1" - resolved "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357" - integrity sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q== - dependencies: - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~2.0.0" - on-headers "~1.0.2" - parseurl "~1.3.3" - safe-buffer "5.2.0" - uid-safe "~2.1.5" - express@^4.17.0, express@^4.17.1: version "4.17.1" resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -17264,11 +17242,6 @@ ramda@^0.21.0: resolved "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= -random-bytes@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" - integrity sha1-T2ih3Arli9P7lYSMMDJNt11kNgs= - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -18594,7 +18567,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.0, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -20656,13 +20629,6 @@ uid-number@0.0.6: resolved "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= -uid-safe@~2.1.5: - version "2.1.5" - resolved "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" - integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== - dependencies: - random-bytes "~1.0.0" - uid2@0.0.x: version "0.0.3" resolved "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" From 15396a7202db10812f6d14bc97bd5ab4cef99d8a Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Tue, 19 May 2020 14:58:27 +0200 Subject: [PATCH 07/10] Fix lint issues --- plugins/auth-backend/src/providers/config.ts | 16 +++++ .../src/providers/google/provider.ts | 60 +++++++++++-------- plugins/auth-backend/src/providers/index.ts | 40 +++++++++---- plugins/auth-backend/src/providers/types.ts | 16 +++++ plugins/auth-backend/src/service/router.ts | 6 +- 5 files changed, 100 insertions(+), 38 deletions(-) diff --git a/plugins/auth-backend/src/providers/config.ts b/plugins/auth-backend/src/providers/config.ts index b8df8b7e99..96b4a8bca5 100644 --- a/plugins/auth-backend/src/providers/config.ts +++ b/plugins/auth-backend/src/providers/config.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export const providers = [ { provider: 'google', diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 94f6ca7fcc..089be9ad3d 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import passport from 'passport'; import express from 'express'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; @@ -7,6 +23,22 @@ import { AuthResponse, } from './../types'; +const postMessageResponse = (res: express.Response, data: AuthResponse) => { + const jsonData = JSON.stringify(data); + const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); + + res.setHeader('X-Frame-Options', 'sameorigin'); + res.end(` + + + + + + `); +}; + export class GoogleAuthProvider implements AuthProvider, AuthProviderRouteHandlers { providerConfig: any; @@ -31,7 +63,7 @@ export class GoogleAuthProvider res: express.Response, next: express.NextFunction, ) { - return passport.authenticate('google', function (_, user) { + return passport.authenticate('google', (_, user) => { postMessageResponse(res, { type: 'auth-result', payload: user, @@ -39,42 +71,22 @@ export class GoogleAuthProvider })(req, res, next); } - logout( - req: express.Request, - res: express.Response, - next: express.NextFunction, - ) { + logout(_req: express.Request, res: express.Response) { return res.send('logout!'); } strategy(): passport.Strategy { return new GoogleStrategy( { ...this.providerConfig.options, passReqToCallback: true }, - function ( + ( _req: any, accessToken: any, refreshToken: any, profile: any, cb: any, - ) { + ) => { cb(undefined, { profile, accessToken, refreshToken }); }, ); } } - -const postMessageResponse = (res: express.Response, data: AuthResponse) => { - const jsonData = JSON.stringify(data); - const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); - - res.setHeader('X-Frame-Options', 'sameorigin'); - res.end(` - - - - - - `); -}; diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index ea58df2fad..61b3ecdda7 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import Router from 'express-promise-router'; import { AuthProviderRouteHandlers, AuthProviderFactories } from './types'; @@ -7,18 +23,6 @@ const providerFactories: AuthProviderFactories = { google: GoogleAuthProvider, }; -export const makeProvider = (config: any) => { - const provider = config.provider; - const providerImpl = providerFactories[provider]; - if (!providerImpl) { - throw Error(`Provider Implementation missing for provider: ${provider}`); - } - const providerInstance = new providerImpl(config); - const strategy = providerInstance.strategy(); - const providerRouter = defaultRouter(providerInstance); - return { provider, strategy, providerRouter }; -}; - export const defaultRouter = (provider: AuthProviderRouteHandlers) => { const router = Router(); router.get('/start', provider.start); @@ -29,3 +33,15 @@ export const defaultRouter = (provider: AuthProviderRouteHandlers) => { } return router; }; + +export const makeProvider = (config: any) => { + const provider = config.provider; + const ProviderImpl = providerFactories[provider]; + if (!ProviderImpl) { + throw Error(`Provider Implementation missing for provider: ${provider}`); + } + const providerInstance = new ProviderImpl(config); + const strategy = providerInstance.strategy(); + const providerRouter = defaultRouter(providerInstance); + return { provider, strategy, providerRouter }; +}; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 1a9c609724..3b200d906a 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import express from 'express'; import passport from 'passport'; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index b22dbe310c..f6b476b8dd 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -29,19 +29,21 @@ export async function createRouter( options: RouterOptions, ): Promise { const router = Router(); + const logger = options.logger.child({ plugin: 'auth' }); // configure all the providers for (const providerConfig of providers) { + logger.info('Configuring providers'); const { provider, strategy, providerRouter } = makeProvider(providerConfig); passport.use(strategy); router.use(`/${provider}`, providerRouter); } - passport.serializeUser(function (user, done) { + passport.serializeUser((user, done) => { done(null, user); }); - passport.deserializeUser(function (user, done) { + passport.deserializeUser((user, done) => { done(null, user); }); From 357700e573d948995c1be4ab3ce7422402c2b852 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Tue, 19 May 2020 20:16:04 +0200 Subject: [PATCH 08/10] Fix PR comments --- .../src/providers/google/provider.ts | 26 ++----------- plugins/auth-backend/src/providers/index.ts | 8 ++-- plugins/auth-backend/src/providers/types.ts | 3 +- plugins/auth-backend/src/providers/utils.ts | 37 +++++++++++++++++++ plugins/auth-backend/src/service/router.ts | 8 ++-- 5 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 plugins/auth-backend/src/providers/utils.ts diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 089be9ad3d..b79c6bf362 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -17,31 +17,12 @@ import passport from 'passport'; import express from 'express'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; -import { - AuthProvider, - AuthProviderRouteHandlers, - AuthResponse, -} from './../types'; - -const postMessageResponse = (res: express.Response, data: AuthResponse) => { - const jsonData = JSON.stringify(data); - const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); - - res.setHeader('X-Frame-Options', 'sameorigin'); - res.end(` - - - - - - `); -}; +import { AuthProvider, AuthProviderRouteHandlers } from './../types'; +import { postMessageResponse } from './../utils'; export class GoogleAuthProvider implements AuthProvider, AuthProviderRouteHandlers { - providerConfig: any; + private readonly providerConfig: any; constructor(providerConfig: any) { this.providerConfig = providerConfig; } @@ -58,6 +39,7 @@ export class GoogleAuthProvider prompt: 'consent', })(req, res, next); } + frameHandler( req: express.Request, res: express.Response, diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 61b3ecdda7..1ed13cdc33 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -35,13 +35,13 @@ export const defaultRouter = (provider: AuthProviderRouteHandlers) => { }; export const makeProvider = (config: any) => { - const provider = config.provider; - const ProviderImpl = providerFactories[provider]; + const providerId = config.provider; + const ProviderImpl = providerFactories[providerId]; if (!ProviderImpl) { - throw Error(`Provider Implementation missing for provider: ${provider}`); + throw Error(`Provider Implementation missing for provider: ${providerId}`); } const providerInstance = new ProviderImpl(config); const strategy = providerInstance.strategy(); const providerRouter = defaultRouter(providerInstance); - return { provider, strategy, providerRouter }; + return { providerId, strategy, providerRouter }; }; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 3b200d906a..fcdfc2bbad 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -53,7 +53,6 @@ export type AuthProviderFactories = { export type AuthInfo = { profile: passport.Profile; accessToken: string; - refreshToken?: string; expiresAt?: number; }; @@ -64,5 +63,5 @@ export type AuthResponse = } | { type: 'auth-result'; - error: Error | undefined; + error: Error; }; diff --git a/plugins/auth-backend/src/providers/utils.ts b/plugins/auth-backend/src/providers/utils.ts new file mode 100644 index 0000000000..4fbe66361a --- /dev/null +++ b/plugins/auth-backend/src/providers/utils.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import express from 'express'; +import { AuthResponse } from './types'; + +export const postMessageResponse = ( + res: express.Response, + data: AuthResponse, +) => { + const jsonData = JSON.stringify(data); + const base64Data = Buffer.from(jsonData, 'utf8').toString('base64'); + + res.setHeader('X-Frame-Options', 'sameorigin'); + res.end(` + + + + + + `); +}; diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index f6b476b8dd..dff03e8139 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -33,10 +33,12 @@ export async function createRouter( // configure all the providers for (const providerConfig of providers) { - logger.info('Configuring providers'); - const { provider, strategy, providerRouter } = makeProvider(providerConfig); + const { providerId, strategy, providerRouter } = makeProvider( + providerConfig, + ); + logger.info(`Configuring provider: ${providerId}`); passport.use(strategy); - router.use(`/${provider}`, providerRouter); + router.use(`/${providerId}`, providerRouter); } passport.serializeUser((user, done) => { From 9113045c504227a482d1fa7851711cf8ba7326dd Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Tue, 19 May 2020 22:19:30 +0200 Subject: [PATCH 09/10] Namespace auth secrets --- plugins/auth-backend/src/providers/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/auth-backend/src/providers/config.ts b/plugins/auth-backend/src/providers/config.ts index 96b4a8bca5..45098afb89 100644 --- a/plugins/auth-backend/src/providers/config.ts +++ b/plugins/auth-backend/src/providers/config.ts @@ -18,8 +18,8 @@ export const providers = [ { provider: 'google', options: { - clientID: process.env.GOOGLE_CLIENT_ID!, - clientSecret: process.env.GOOGLE_CLIENT_SECRET!, + clientID: process.env.AUTH_GOOGLE_CLIENT_ID!, + clientSecret: process.env.AUTH_GOOGLE_CLIENT_SECRET!, callbackURL: 'http://localhost:7000/auth/google/handler/frame', }, }, From 9749d07be5812fa98a5984746b4c3bf1ea10ad50 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Wed, 20 May 2020 12:49:30 +0200 Subject: [PATCH 10/10] more fixes --- plugins/auth-backend/package.json | 8 ++++---- .../src/providers/google/provider.ts | 15 ++++++++++---- plugins/auth-backend/src/providers/index.ts | 8 ++++++-- plugins/auth-backend/src/providers/types.ts | 20 ++++++++++++------- plugins/auth-backend/src/service/router.ts | 10 +++++++++- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 02c3122dd3..e285d33ef1 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -26,14 +26,14 @@ "winston": "^3.2.1", "yn": "^4.0.0", "passport": "0.4.1", - "passport-google-oauth20": "2.0.0" + "passport-google-oauth20": "2.0.0", + "@types/passport": "1.0.3", + "@types/passport-google-oauth20": "2.0.3" }, "devDependencies": { "@backstage/cli": "^0.1.1-alpha.5", "jest-fetch-mock": "^3.0.3", - "tsc-watch": "^4.2.3", - "@types/passport": "1.0.3", - "@types/passport-google-oauth20": "2.0.3" + "tsc-watch": "^4.2.3" }, "files": [ "dist" diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index b79c6bf362..2c559a2dc9 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -17,13 +17,17 @@ import passport from 'passport'; import express from 'express'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; -import { AuthProvider, AuthProviderRouteHandlers } from './../types'; +import { + AuthProvider, + AuthProviderRouteHandlers, + AuthProviderConfig, +} from './../types'; import { postMessageResponse } from './../utils'; export class GoogleAuthProvider implements AuthProvider, AuthProviderRouteHandlers { - private readonly providerConfig: any; - constructor(providerConfig: any) { + private readonly providerConfig: AuthProviderConfig; + constructor(providerConfig: AuthProviderConfig) { this.providerConfig = providerConfig; } @@ -54,7 +58,10 @@ export class GoogleAuthProvider } logout(_req: express.Request, res: express.Response) { - return res.send('logout!'); + return new Promise((resolve) => { + res.send('logout!'); + resolve(); + }); } strategy(): passport.Strategy { diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 1ed13cdc33..a26176381a 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -15,7 +15,11 @@ */ import Router from 'express-promise-router'; -import { AuthProviderRouteHandlers, AuthProviderFactories } from './types'; +import { + AuthProviderRouteHandlers, + AuthProviderFactories, + AuthProviderConfig, +} from './types'; import { GoogleAuthProvider } from './google/provider'; @@ -34,7 +38,7 @@ export const defaultRouter = (provider: AuthProviderRouteHandlers) => { return router; }; -export const makeProvider = (config: any) => { +export const makeProvider = (config: AuthProviderConfig) => { const providerId = config.provider; const ProviderImpl = providerFactories[providerId]; if (!ProviderImpl) { diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index fcdfc2bbad..eaff539c04 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -17,6 +17,16 @@ import express from 'express'; import passport from 'passport'; +export type AuthProviderConfig = { + provider: string; + options: any; +}; + +export interface AuthProvider { + strategy(): passport.Strategy; + router?(): express.Router; +} + export interface AuthProviderRouteHandlers { start( req: express.Request, @@ -27,7 +37,7 @@ export interface AuthProviderRouteHandlers { req: express.Request, res: express.Response, next: express.NextFunction, - ): express.Response; + ): Promise; refresh?( req: express.Request, res: express.Response, @@ -37,11 +47,7 @@ export interface AuthProviderRouteHandlers { req: express.Request, res: express.Response, next: express.NextFunction, - ): express.Response; -} -export interface AuthProvider { - strategy(): passport.Strategy; - router?(): express.Router; + ): Promise; } export type AuthProviderFactories = { @@ -53,7 +59,7 @@ export type AuthProviderFactories = { export type AuthInfo = { profile: passport.Profile; accessToken: string; - expiresAt?: number; + expiresInSeconds?: number; }; export type AuthResponse = diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index dff03e8139..cdde95d9d0 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -30,6 +30,7 @@ export async function createRouter( ): Promise { const router = Router(); const logger = options.logger.child({ plugin: 'auth' }); + const providerRouters: { [key: string]: express.Router } = {}; // configure all the providers for (const providerConfig of providers) { @@ -38,7 +39,7 @@ export async function createRouter( ); logger.info(`Configuring provider: ${providerId}`); passport.use(strategy); - router.use(`/${providerId}`, providerRouter); + providerRouters[providerId] = providerRouter; } passport.serializeUser((user, done) => { @@ -52,5 +53,12 @@ export async function createRouter( router.use(passport.initialize()); router.use(passport.session()); + for (const providerId in providerRouters) { + if (providerRouters.hasOwnProperty(providerId)) { + const providerRouter = providerRouters[providerId]; + router.use(`/${providerId}`, providerRouter); + } + } + return router; }