diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 9d366c30a6..ab9142eaee 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -48,8 +48,8 @@ exports.getGroupParams = (id = "", otherProps = {}) => { * Generates a new global user ID. * @returns {string} The new user ID which the user doc can be stored under. */ -exports.generateGlobalUserID = () => { - return `${DocumentTypes.USER}${SEPARATOR}${newid()}` +exports.generateGlobalUserID = id => { + return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}` } /** diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 3dcf26d346..1906e20be2 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -1,7 +1,7 @@ const passport = require("koa-passport") const LocalStrategy = require("passport-local").Strategy const JwtStrategy = require("passport-jwt").Strategy -const database = require("./db") +const constants = require("./constants") const { StaticDatabases, DocumentTypes } = require("./db/utils") const { jwt, local, google, authenticated } = require("./middleware") const { Cookies, UserStatus } = require("./constants") @@ -55,7 +55,11 @@ module.exports = { auth: { buildAuthMiddleware: authenticated, passport, + middlewares: { + google, + }, }, + constants, passport, Cookies, UserStatus, diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 69c038638f..ad7c83d189 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -2,7 +2,11 @@ const env = require("../../environment") const jwt = require("jsonwebtoken") const database = require("../../db") const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy -const { StaticDatabases, generateUserID } = require("../../db/utils") +const { + StaticDatabases, + generateUserID, + generateGlobalUserID, +} = require("../../db/utils") exports.options = { clientID: env.GOOGLE_CLIENT_ID, @@ -11,13 +15,11 @@ exports.options = { } async function authenticate(token, tokenSecret, profile, done) { - if (!profile._json.email) return done(null, false, "Email Required.") - // Check the user exists in the instance DB by email - const db = new database.CouchDB(StaticDatabases.GLOBAL.name) + const db = database.getDB(StaticDatabases.GLOBAL.name) let dbUser - const userId = generateUserID(profile._json.email) + const userId = generateGlobalUserID(profile.id) try { // use the google profile id @@ -54,13 +56,37 @@ async function authenticate(token, tokenSecret, profile, done) { return done(null, dbUser) } -exports.CustomGoogleStrategy = function(config) { - return new GoogleStrategy( - { - clientID: config.clientID, - clientSecret: config.clientSecret, - callbackURL: config.callbackURL, - }, - authenticate - ) +/** + * Create an instance of the google passport strategy. This wrapper fetches the configuration + * from couchDB rather than environment variables, and is necessary for dynamically configuring passport. + * @returns Passport Google Strategy + */ +exports.strategyFactory = async function() { + try { + const db = database.getDB(StaticDatabases.GLOBAL.name) + + const config = await db.get( + "config_google__767bd8f363854dfa8752f593a637b3fd" + ) + + const { clientID, clientSecret, callbackURL } = config + + if (!clientID || !clientSecret || !callbackURL) { + throw new Error( + "Configuration invalid. Must contain google clientID, clientSecret and callbackURL" + ) + } + + return new GoogleStrategy( + { + clientID: config.clientID, + clientSecret: config.clientSecret, + callbackURL: config.callbackURL, + }, + authenticate + ) + } catch (err) { + console.error(err) + throw new Error("Error constructing google authentication strategy", err) + } } diff --git a/packages/builder/src/components/login/LoginForm.svelte b/packages/builder/src/components/login/LoginForm.svelte index 30d903a9d4..888054df1b 100644 --- a/packages/builder/src/components/login/LoginForm.svelte +++ b/packages/builder/src/components/login/LoginForm.svelte @@ -39,7 +39,7 @@ - Sign In with Google + Sign In With Google diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index 05e3256e34..bfc331042e 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,6 +1,7 @@ const authPkg = require("@budibase/auth") +const { google } = require("@budibase/auth/src/middleware") const { clearCookie } = authPkg.utils -const { Cookies } = authPkg.constants +const { Cookies } = authPkg const { passport } = authPkg.auth exports.authenticate = async (ctx, next) => { @@ -34,18 +35,20 @@ exports.logout = async ctx => { ctx.body = { message: "User logged out" } } -// exports.googleAuth = async (ctx, next) => -// passport.authenticate( -// "google", -// { successRedirect: "/", failureRedirect: "/" }, -// (ctx -// setToken(ctx, next) -// ) +exports.googlePreAuth = async (ctx, next) => { + const strategy = await google.strategyFactory() + + return passport.authenticate(strategy, { + scope: ["profile", "email"], + })(ctx, next) +} exports.googleAuth = async (ctx, next) => { + const strategy = await google.strategyFactory() + return passport.authenticate( - "google", - { successRedirect: "/", failureRedirect: "/" }, + strategy, + { successRedirect: "/", failureRedirect: "/error" }, async (err, user) => { if (err) { return ctx.throw(403, "Unauthorized") diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 0399026cf2..0411a9ffa0 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -15,15 +15,10 @@ function buildConfigSaveValidation() { } router - .post( - "/api/admin/configs", - buildConfigSaveValidation(), - authenticated, - controller.save - ) - .post("/api/admin/config/status", controller.configStatus) - .delete("/api/admin/configs/:id", authenticated, controller.destroy) - .get("/api/admin/configs", authenticated, controller.fetch) - .get("/api/admin/configs/:id", authenticated, controller.find) + .post("/api/admin/configs", buildConfigSaveValidation(), controller.save) + .post("/api/admin/configs/status", controller.configStatus) + .delete("/api/admin/configs/:id", controller.destroy) + .get("/api/admin/configs", controller.fetch) + .get("/api/admin/configs/:id", controller.find) module.exports = router diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js index 756b3e7cf0..2207b72458 100644 --- a/packages/worker/src/api/routes/admin/templates.js +++ b/packages/worker/src/api/routes/admin/templates.js @@ -21,11 +21,7 @@ function buildTemplateSaveValidation() { router .get("/api/admin/template/definitions", controller.definitions) - .post( - "/api/admin/template", - buildTemplateSaveValidation(), - controller.save - ) + .post("/api/admin/template", buildTemplateSaveValidation(), controller.save) .get("/api/admin/template", controller.fetch) .get("/api/admin/template/:type", controller.fetchByType) .get("/api/admin/template/:ownerId", controller.fetchByOwner) diff --git a/packages/worker/src/api/routes/auth.js b/packages/worker/src/api/routes/auth.js index ac7c7c0737..72fddec399 100644 --- a/packages/worker/src/api/routes/auth.js +++ b/packages/worker/src/api/routes/auth.js @@ -1,16 +1,11 @@ const Router = require("@koa/router") -const { passport } = require("@budibase/auth").auth const authController = require("../controllers/auth") -const context = require("koa/lib/context") const router = Router() router .post("/api/admin/auth", authController.authenticate) - .get( - "/api/admin/auth/google", - passport.authenticate("google", { scope: ["profile", "email"] }) - ) + .get("/api/admin/auth/google", authController.googlePreAuth) .get("/api/admin/auth/google/callback", authController.googleAuth) .post("/api/admin/auth/logout", authController.logout) diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 345094206b..5d52ce798f 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -11,6 +11,7 @@ exports.Configs = { SETTINGS: "settings", ACCOUNT: "account", SMTP: "smtp", + GOOGLE: "google", } exports.TemplateTypes = {