google login reading from couch

This commit is contained in:
Martin McKeaveney 2021-04-21 21:08:04 +01:00
parent 1da29900c7
commit 1c7689e694
9 changed files with 69 additions and 49 deletions

View File

@ -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()}`
}
/**

View File

@ -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,

View File

@ -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,7 +56,27 @@ async function authenticate(token, tokenSecret, profile, done) {
return done(null, dbUser)
}
exports.CustomGoogleStrategy = function(config) {
/**
* 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,
@ -63,4 +85,8 @@ exports.CustomGoogleStrategy = function(config) {
},
authenticate
)
} catch (err) {
console.error(err)
throw new Error("Error constructing google authentication strategy", err)
}
}

View File

@ -39,7 +39,7 @@
<Input outline type="password" on:change bind:value={password} />
<Spacer large />
<Button primary on:click={login}>Login</Button>
<a target="_blank" href="/api/admin/auth/google">Sign In with Google</a>
<a target="_blank" href="/api/admin/auth/google">Sign In With Google</a>
<Button secondary on:click={createTestUser}>Create Test User</Button>
</form>

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -11,6 +11,7 @@ exports.Configs = {
SETTINGS: "settings",
ACCOUNT: "account",
SMTP: "smtp",
GOOGLE: "google",
}
exports.TemplateTypes = {