소스 검색

feat: oauth2 login (wip)

Nick 6 년 전
부모
커밋
8af21c02af

+ 1 - 1
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()

+ 1 - 0
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",

+ 21 - 1
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

+ 6 - 0
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)
 

+ 26 - 18
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({

+ 8 - 6
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)
+        }
       }
       ))
   }

+ 4 - 0
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