google login reading from couch

This commit is contained in:
Martin McKeaveney 2021-04-21 21:08:04 +01:00
parent d8db863faa
commit 8fab374c1f
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. * Generates a new global user ID.
* @returns {string} The new user ID which the user doc can be stored under. * @returns {string} The new user ID which the user doc can be stored under.
*/ */
exports.generateGlobalUserID = () => { exports.generateGlobalUserID = id => {
return `${DocumentTypes.USER}${SEPARATOR}${newid()}` return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}`
} }
/** /**

View File

@ -1,7 +1,7 @@
const passport = require("koa-passport") const passport = require("koa-passport")
const LocalStrategy = require("passport-local").Strategy const LocalStrategy = require("passport-local").Strategy
const JwtStrategy = require("passport-jwt").Strategy const JwtStrategy = require("passport-jwt").Strategy
const database = require("./db") const constants = require("./constants")
const { StaticDatabases, DocumentTypes } = require("./db/utils") const { StaticDatabases, DocumentTypes } = require("./db/utils")
const { jwt, local, google, authenticated } = require("./middleware") const { jwt, local, google, authenticated } = require("./middleware")
const { Cookies, UserStatus } = require("./constants") const { Cookies, UserStatus } = require("./constants")
@ -55,7 +55,11 @@ module.exports = {
auth: { auth: {
buildAuthMiddleware: authenticated, buildAuthMiddleware: authenticated,
passport, passport,
middlewares: {
google,
},
}, },
constants,
passport, passport,
Cookies, Cookies,
UserStatus, UserStatus,

View File

@ -2,7 +2,11 @@ const env = require("../../environment")
const jwt = require("jsonwebtoken") const jwt = require("jsonwebtoken")
const database = require("../../db") const database = require("../../db")
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy
const { StaticDatabases, generateUserID } = require("../../db/utils") const {
StaticDatabases,
generateUserID,
generateGlobalUserID,
} = require("../../db/utils")
exports.options = { exports.options = {
clientID: env.GOOGLE_CLIENT_ID, clientID: env.GOOGLE_CLIENT_ID,
@ -11,13 +15,11 @@ exports.options = {
} }
async function authenticate(token, tokenSecret, profile, done) { 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 // 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 let dbUser
const userId = generateUserID(profile._json.email) const userId = generateGlobalUserID(profile.id)
try { try {
// use the google profile id // use the google profile id
@ -54,13 +56,37 @@ async function authenticate(token, tokenSecret, profile, done) {
return done(null, dbUser) return done(null, dbUser)
} }
exports.CustomGoogleStrategy = function(config) { /**
return new GoogleStrategy( * 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.
clientID: config.clientID, * @returns Passport Google Strategy
clientSecret: config.clientSecret, */
callbackURL: config.callbackURL, exports.strategyFactory = async function() {
}, try {
authenticate 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)
}
} }

View File

@ -39,7 +39,7 @@
<Input outline type="password" on:change bind:value={password} /> <Input outline type="password" on:change bind:value={password} />
<Spacer large /> <Spacer large />
<Button primary on:click={login}>Login</Button> <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> <Button secondary on:click={createTestUser}>Create Test User</Button>
</form> </form>

View File

@ -1,6 +1,7 @@
const authPkg = require("@budibase/auth") const authPkg = require("@budibase/auth")
const { google } = require("@budibase/auth/src/middleware")
const { clearCookie } = authPkg.utils const { clearCookie } = authPkg.utils
const { Cookies } = authPkg.constants const { Cookies } = authPkg
const { passport } = authPkg.auth const { passport } = authPkg.auth
exports.authenticate = async (ctx, next) => { exports.authenticate = async (ctx, next) => {
@ -34,18 +35,20 @@ exports.logout = async ctx => {
ctx.body = { message: "User logged out" } ctx.body = { message: "User logged out" }
} }
// exports.googleAuth = async (ctx, next) => exports.googlePreAuth = async (ctx, next) => {
// passport.authenticate( const strategy = await google.strategyFactory()
// "google",
// { successRedirect: "/", failureRedirect: "/" }, return passport.authenticate(strategy, {
// (ctx scope: ["profile", "email"],
// setToken(ctx, next) })(ctx, next)
// ) }
exports.googleAuth = async (ctx, next) => { exports.googleAuth = async (ctx, next) => {
const strategy = await google.strategyFactory()
return passport.authenticate( return passport.authenticate(
"google", strategy,
{ successRedirect: "/", failureRedirect: "/" }, { successRedirect: "/", failureRedirect: "/error" },
async (err, user) => { async (err, user) => {
if (err) { if (err) {
return ctx.throw(403, "Unauthorized") return ctx.throw(403, "Unauthorized")

View File

@ -15,15 +15,10 @@ function buildConfigSaveValidation() {
} }
router router
.post( .post("/api/admin/configs", buildConfigSaveValidation(), controller.save)
"/api/admin/configs", .post("/api/admin/configs/status", controller.configStatus)
buildConfigSaveValidation(), .delete("/api/admin/configs/:id", controller.destroy)
authenticated, .get("/api/admin/configs", controller.fetch)
controller.save .get("/api/admin/configs/:id", controller.find)
)
.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)
module.exports = router module.exports = router

View File

@ -21,11 +21,7 @@ function buildTemplateSaveValidation() {
router router
.get("/api/admin/template/definitions", controller.definitions) .get("/api/admin/template/definitions", controller.definitions)
.post( .post("/api/admin/template", buildTemplateSaveValidation(), controller.save)
"/api/admin/template",
buildTemplateSaveValidation(),
controller.save
)
.get("/api/admin/template", controller.fetch) .get("/api/admin/template", controller.fetch)
.get("/api/admin/template/:type", controller.fetchByType) .get("/api/admin/template/:type", controller.fetchByType)
.get("/api/admin/template/:ownerId", controller.fetchByOwner) .get("/api/admin/template/:ownerId", controller.fetchByOwner)

View File

@ -1,16 +1,11 @@
const Router = require("@koa/router") const Router = require("@koa/router")
const { passport } = require("@budibase/auth").auth
const authController = require("../controllers/auth") const authController = require("../controllers/auth")
const context = require("koa/lib/context")
const router = Router() const router = Router()
router router
.post("/api/admin/auth", authController.authenticate) .post("/api/admin/auth", authController.authenticate)
.get( .get("/api/admin/auth/google", authController.googlePreAuth)
"/api/admin/auth/google",
passport.authenticate("google", { scope: ["profile", "email"] })
)
.get("/api/admin/auth/google/callback", authController.googleAuth) .get("/api/admin/auth/google/callback", authController.googleAuth)
.post("/api/admin/auth/logout", authController.logout) .post("/api/admin/auth/logout", authController.logout)

View File

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