Explorar el Código

LDAP authentication

NGPixel hace 8 años
padre
commit
80aa30009b

+ 2 - 0
app/data.yml

@@ -33,6 +33,8 @@ defaults:
         enabled: false
       slack:
         enabled: false
+      ldap:
+        enabled: false
     db: mongodb://localhost/wiki
     sessionSecret: null
     admin: null

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
assets/js/app.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
assets/js/libs.js


+ 0 - 1
config.sample.yml

@@ -82,7 +82,6 @@ auth:
     bindDn: cn='root'
     bindCredentials: BIND_PASSWORD
     searchBase: o=users,o=example.com
-    # searchFilter: {{username}} to use the provided username in search
     searchFilter: (uid={{username}})
     tlsEnabled: false
     tlsCertPath: C:\example\root_ca_cert.crt

+ 39 - 11
controllers/auth.js

@@ -1,5 +1,6 @@
 'use strict'
 
+const Promise = require('bluebird')
 const express = require('express')
 const router = express.Router()
 const passport = require('passport')
@@ -37,24 +38,51 @@ router.get('/login', function (req, res, next) {
 })
 
 router.post('/login', bruteforce.prevent, function (req, res, next) {
-  passport.authenticate('local', function (err, user, info) {
-    if (err) { return next(err) }
-
-    if (!user) {
-      req.flash('alert', {
-        title: 'Invalid login',
-        message: 'The email or password is invalid.'
+  new Promise((resolve, reject) => {
+    // [1] LOCAL AUTHENTICATION
+    passport.authenticate('local', function (err, user, info) {
+      if (err) { return reject(err) }
+      if (!user) { return reject(new Error('INVALID_LOGIN')) }
+      resolve(user)
+    })(req, res, next)
+  }).catch({ message: 'INVALID_LOGIN' }, err => {
+    if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
+      // [2] LDAP AUTHENTICATION
+      return new Promise((resolve, reject) => {
+        passport.authenticate('ldapauth', function (err, user, info) {
+          if (err) { return reject(err) }
+          if (info && info.message) { return reject(new Error(info.message)) }
+          if (!user) { return reject(new Error('INVALID_LOGIN')) }
+          resolve(user)
+        })(req, res, next)
       })
-      return res.redirect('/login')
+    } else {
+      throw err
     }
-
-    req.logIn(user, function (err) {
+  }).then((user) => {
+    // LOGIN SUCCESS
+    return req.logIn(user, function (err) {
       if (err) { return next(err) }
       req.brute.reset(function () {
         return res.redirect('/')
       })
     })
-  })(req, res, next)
+  }).catch(err => {
+    // LOGIN FAIL
+    if (err.message === 'INVALID_LOGIN') {
+      req.flash('alert', {
+        title: 'Invalid login',
+        message: 'The email or password is invalid.'
+      })
+      return res.redirect('/login')
+    } else {
+      req.flash('alert', {
+        title: 'Login error',
+        message: err.message
+      })
+      return res.redirect('/login')
+    }
+  })
 })
 
 /**

+ 2 - 1
locales/en/auth.json

@@ -5,6 +5,7 @@
 		"google": "Google ID",
 		"facebook": "Facebook",
     "github": "GitHub",
-    "slack": "Slack"
+    "slack": "Slack",
+    "ldap": "LDAP / Active Directory"
 	}
 }

+ 5 - 2
locales/fr/auth.json

@@ -3,6 +3,9 @@
 		"local": "Local",
 		"windowslive": "Compte Microsoft",
 		"google": "Google ID",
-		"facebook": "Facebook"
+		"facebook": "Facebook",
+    "github": "GitHub",
+    "slack": "Slack",
+    "ldap": "LDAP / Active Directory"
 	}
-}
+}

+ 18 - 0
models/user.js

@@ -71,6 +71,24 @@ userSchema.statics.processProfile = (profile) => {
   }, {
     new: true
   }).then((user) => {
+    // LDAP - Handle unregistered accounts
+    // Todo: Allow this behavior for any provider...
+    if (!user && profile.provider === 'ldap') {
+      let nUsr = {
+        email: primaryEmail,
+        provider: profile.provider,
+        providerId: profile.id,
+        password: '',
+        name: profile.displayName || profile.name || profile.cn,
+        rights: [{
+          role: 'read',
+          path: '/',
+          exact: false,
+          deny: false
+        }]
+      }
+      return db.User.create(nUsr)
+    }
     return user || Promise.reject(new Error('You have not been authorized to login to this site yet.'))
   })
 }

+ 1 - 1
npm/install.js

@@ -56,7 +56,7 @@ pm2.connectAsync().then(() => {
 }).then(() => {
   return new Promise((resolve, reject) => {
     ora.text = 'Installing Wiki.js npm dependencies...'
-    let npmInstallProc = exec('npm install --only=production', {
+    let npmInstallProc = exec('npm install --only=production --no-optional', {
       cwd: installDir
     })
     npmInstallProc.stdout.pipe(process.stdout)

+ 2 - 2
views/auth/login.pug

@@ -34,12 +34,12 @@ html
       h2 Login required
       if appflash.length > 0
         h3
-          i.fa.fa-warning
+          i.icon-warning-outline
           = appflash[0].title
         h4= appflash[0].message
       if appconfig.auth.local.enabled
         form(method='post', action='/login')
-          input#login-user(type='text', name='email', placeholder='Email address')
+          input#login-user(type='text', name='email', placeholder='Email / Username')
           input#login-pass(type='password', name='password', placeholder='Password')
           button(type='submit') Log In
       if appconfig.authStrategies.socialEnabled

+ 1 - 0
views/pages/admin/profile.pug

@@ -40,6 +40,7 @@ block adminContent
                 when 'facebook': i.icon-facebook.is-indigo
                 when 'github': i.icon-github.is-grey
                 when 'slack': i.icon-slack.is-purple
+                when 'ldap': i.icon-arrow-repeat-outline
                 default: i.icon-warning
               = t('auth:providers.' + user.provider)
             label.label Member since

+ 3 - 0
views/pages/admin/users-edit.pug

@@ -42,6 +42,9 @@ block adminContent
               when 'slack'
                 i.icon-slack.is-purple
                 | Slack
+              when 'ldap'
+                i.icon-arrow-repeat-outline
+                | LDAP / Active Directory
               default: i.icon-warning
           td.is-centered= userMoment(usr.createdAt).format('lll')
           td.is-centered= userMoment(usr.updatedAt).format('lll')

+ 3 - 0
views/pages/admin/users.pug

@@ -49,6 +49,9 @@ block adminContent
                 when 'slack'
                   i.icon-slack.is-purple
                   | Slack
+                when 'ldap'
+                  i.icon-arrow-repeat-outline
+                  | LDAP / Active Directory
                 default: i.icon-warning
             td.is-centered= userMoment(usr.createdAt).format('lll')
             td.is-centered= userMoment(usr.updatedAt).format('lll')

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio