From 8af21c02af4711969c275dbe6417c05793bfe361 Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 21 Apr 2019 02:04:00 -0400 Subject: [PATCH] feat: oauth2 login (wip) --- client/components/login.vue | 2 +- package.json | 1 + server/controllers/auth.js | 22 +++++++++- server/master.js | 6 +++ server/models/users.js | 44 +++++++++++-------- .../authentication/auth0/authentication.js | 14 +++--- .../authentication/auth0/definition.yml | 4 ++ 7 files changed, 67 insertions(+), 26 deletions(-) diff --git a/client/components/login.vue b/client/components/login.vue index 06ee5d48..699fbf64 100644 --- a/client/components/login.vue +++ b/client/components/login.vue @@ -189,7 +189,7 @@ export default { this.screen = 'login' if (!strategy.useForm) { this.isLoading = true - window.location.assign(this.$helpers.resolvePath('login/' + strategy.key)) + window.location.assign('/login/' + strategy.key) } else { this.$nextTick(() => { this.$refs.iptEmail.focus() diff --git a/package.json b/package.json index 81b86799..67d5cdeb 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "emoji-regex": "8.0.0", "express": "4.16.4", "express-brute": "1.0.1", + "express-session": "1.16.1", "file-type": "10.7.1", "filesize": "4.0.0", "fs-extra": "7.0.1", diff --git a/server/controllers/auth.js b/server/controllers/auth.js index b3c9d70b..4f48ba59 100644 --- a/server/controllers/auth.js +++ b/server/controllers/auth.js @@ -8,10 +8,30 @@ const _ = require('lodash') /** * Login form */ -router.get('/login', function (req, res, next) { +router.get('/login', (req, res, next) => { _.set(res.locals, 'pageMeta.title', 'Login') res.render('login') }) +router.get('/login/:strategy', async (req, res, next) => { + try { + const authResult = await WIKI.models.users.login({ + strategy: req.params.strategy + }, { req, res }) + console.info(authResult) + } catch (err) { + next(err) + } +}) +router.get('/login/:strategy/callback', async (req, res, next) => { + try { + const authResult = await WIKI.models.users.login({ + strategy: req.params.strategy + }, { req, res }) + console.info(authResult) + } catch (err) { + next(err) + } +}) /** * Logout diff --git a/server/master.js b/server/master.js index 3bacb483..d657ef37 100644 --- a/server/master.js +++ b/server/master.js @@ -4,6 +4,7 @@ const compression = require('compression') const cookieParser = require('cookie-parser') const cors = require('cors') const express = require('express') +const session = require('express-session') const favicon = require('serve-favicon') const fs = require('fs-extra') const http = require('http') @@ -65,6 +66,11 @@ module.exports = async () => { // ---------------------------------------- app.use(cookieParser()) + app.use(session({ + secret: WIKI.config.sessionSecret, + resave: false, + saveUninitialized: false + })) app.use(WIKI.auth.passport.initialize()) app.use(WIKI.auth.authenticate) diff --git a/server/models/users.js b/server/models/users.js index 914820b7..b29556a1 100644 --- a/server/models/users.js +++ b/server/models/users.js @@ -154,10 +154,11 @@ module.exports = class User extends Model { // Model Methods // ------------------------------------------------ - static async processProfile(profile) { + static async processProfile({ profile, provider }) { + // -> Parse email let primaryEmail = '' if (_.isArray(profile.emails)) { - let e = _.find(profile.emails, ['primary', true]) + const e = _.find(profile.emails, ['primary', true]) primaryEmail = (e) ? e.value : _.first(profile.emails).value } else if (_.isString(profile.email) && profile.email.length > 5) { primaryEmail = profile.email @@ -166,30 +167,29 @@ module.exports = class User extends Model { } else if (profile.user && profile.user.email && profile.user.email.length > 5) { primaryEmail = profile.user.email } else { - return Promise.reject(new Error(WIKI.lang.t('auth:errors.invaliduseremail'))) + return Promise.reject(new Error('Missing or invalid email address from profile.')) } - - profile.provider = _.lowerCase(profile.provider) primaryEmail = _.toLower(primaryEmail) + // -> Find user let user = await WIKI.models.users.query().findOne({ email: primaryEmail, - provider: profile.provider + providerKey: provider }) if (user) { user.$query().patchAdnFetch({ email: primaryEmail, - provider: profile.provider, + providerKey: provider, providerId: profile.id, - name: profile.displayName || _.split(primaryEmail, '@')[0] + name: _.get(profile, 'displayName', primaryEmail.split('@')[0]) }) } else { - user = await WIKI.models.users.query().insertAndFetch({ - email: primaryEmail, - provider: profile.provider, - providerId: profile.id, - name: profile.displayName || _.split(primaryEmail, '@')[0] - }) + // user = await WIKI.models.users.query().insertAndFetch({ + // email: primaryEmail, + // providerKey: provider, + // providerId: profile.id, + // name: profile.displayName || _.split(primaryEmail, '@')[0] + // }) } // Handle unregistered accounts @@ -215,12 +215,20 @@ module.exports = class User extends Model { static async login (opts, context) { if (_.has(WIKI.auth.strategies, opts.strategy)) { - _.set(context.req, 'body.email', opts.username) - _.set(context.req, 'body.password', opts.password) + const strInfo = _.find(WIKI.data.authentication, ['key', opts.strategy]) + + // Inject form user/pass + if (strInfo.useForm) { + _.set(context.req, 'body.email', opts.username) + _.set(context.req, 'body.password', opts.password) + } // Authenticate return new Promise((resolve, reject) => { - WIKI.auth.passport.authenticate(opts.strategy, { session: false }, async (err, user, info) => { + WIKI.auth.passport.authenticate(opts.strategy, { + session: !strInfo.useForm, + scope: strInfo.scopes ? strInfo.scopes.join(' ') : null + }, async (err, user, info) => { if (err) { return reject(err) } if (!user) { return reject(new WIKI.Error.AuthLoginFailed()) } @@ -239,7 +247,7 @@ module.exports = class User extends Model { } } else { // No 2FA, log in user - return context.req.logIn(user, { session: false }, async err => { + return context.req.logIn(user, { session: !strInfo.useForm }, async err => { if (err) { return reject(err) } const jwtToken = await WIKI.models.users.refreshToken(user) resolve({ diff --git a/server/modules/authentication/auth0/authentication.js b/server/modules/authentication/auth0/authentication.js index 2666cceb..13125c2d 100644 --- a/server/modules/authentication/auth0/authentication.js +++ b/server/modules/authentication/auth0/authentication.js @@ -14,12 +14,14 @@ module.exports = { clientID: conf.clientId, clientSecret: conf.clientSecret, callbackURL: conf.callbackURL - }, function (accessToken, refreshToken, profile, cb) { - WIKI.models.users.processProfile(profile).then((user) => { - return cb(null, user) || true - }).catch((err) => { - return cb(err, null) || true - }) + }, async (accessToken, refreshToken, extraParams, profile, cb) => { + console.info(accessToken, refreshToken, extraParams, profile) + try { + const user = WIKI.models.users.processProfile({ profile, provider: 'auth0' }) + cb(null, user) + } catch (err) { + cb(err, null) + } } )) } diff --git a/server/modules/authentication/auth0/definition.yml b/server/modules/authentication/auth0/definition.yml index 1090b459..9f475181 100644 --- a/server/modules/authentication/auth0/definition.yml +++ b/server/modules/authentication/auth0/definition.yml @@ -7,6 +7,10 @@ color: deep-orange website: https://auth0.com/ isAvailable: true useForm: false +scopes: + - openid + - profile + - email props: domain: type: String