LDAP authentication

This commit is contained in:
NGPixel 2017-03-11 23:38:47 -05:00
parent 3f1d946b3d
commit 80aa30009b
13 changed files with 112 additions and 53 deletions

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

View File

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

View File

@ -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.'))
})
}

View File

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

View File

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

View File

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

View File

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

View File

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