mirror of
https://git.unistra.fr/aius/root/ldap-overleaf-sl.git
synced 2025-05-04 19:55:26 +02:00
305 lines
9.3 KiB
Diff
305 lines
9.3 KiB
Diff
19a20,25
|
|
> // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
> const fs = require("fs")
|
|
> const { Client } = require("ldapts")
|
|
> const ldapEscape = require("ldap-escape")
|
|
> // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
>
|
|
120a127,136
|
|
> // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
> _checkUserPassword2(query, password, callback) {
|
|
> // leave original _checkUserPassword untouched, because it will be called by
|
|
> // setUserPasswordInV2 (e.g. UserRegistrationHandler.js )
|
|
> User.findOne(query, (error, user) => {
|
|
> AuthenticationManager.authUserObj(error, user, query, password, callback)
|
|
> })
|
|
> },
|
|
> // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
>
|
|
126c142,144
|
|
< AuthenticationManager._checkUserPassword(
|
|
---
|
|
> // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
> AuthenticationManager._checkUserPassword2(
|
|
> // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
190a209,488
|
|
>
|
|
> // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
> /**
|
|
> * login with any password
|
|
> */
|
|
> login(user, password, callback) {
|
|
> callback(null, user, true)
|
|
> },
|
|
>
|
|
> createIfNotFoundAndLogin(
|
|
> query,
|
|
> callback,
|
|
> uid,
|
|
> firstname,
|
|
> lastname,
|
|
> mail,
|
|
> isAdmin
|
|
> ) {
|
|
> User.findOne(query, (error, user) => {
|
|
> if (error) {
|
|
> console.log(error)
|
|
> }
|
|
>
|
|
> AuthenticationManager.createIfNotExistAndLogin(
|
|
> query,
|
|
> user,
|
|
> callback,
|
|
> uid,
|
|
> firstname,
|
|
> lastname,
|
|
> mail,
|
|
> isAdmin
|
|
> )
|
|
> })
|
|
> },
|
|
>
|
|
> createIfNotExistAndLogin(
|
|
> query,
|
|
> user,
|
|
> callback,
|
|
> uid,
|
|
> firstname,
|
|
> lastname,
|
|
> mail,
|
|
> isAdmin
|
|
> ) {
|
|
> if (!user) {
|
|
> //create random pass for local userdb, does not get checked for ldap users during login
|
|
> const pass = require("crypto").randomBytes(32).toString("hex")
|
|
> console.log('Creating User', { mail, uid, firstname, lastname, isAdmin, pass })
|
|
>
|
|
> const userRegHand = require("../User/UserRegistrationHandler.js")
|
|
> userRegHand.registerNewUser(
|
|
> {
|
|
> email: mail,
|
|
> first_name: firstname,
|
|
> last_name: lastname,
|
|
> password: pass,
|
|
> },
|
|
> function (error, user, setNewPasswordUrl) {
|
|
> if (error) {
|
|
> console.log(error)
|
|
> }
|
|
> user.email = mail
|
|
> user.isAdmin = isAdmin
|
|
> user.emails[0].confirmedAt = Date.now()
|
|
> user.save()
|
|
> //console.log('user %s added to local library: ', mail)
|
|
> User.findOne(query, (error, user) => {
|
|
> if (error) {
|
|
> console.log(error)
|
|
> }
|
|
> if (user && user.hashedPassword) {
|
|
> AuthenticationManager.login(user, "randomPass", callback)
|
|
> }
|
|
> })
|
|
> }
|
|
> ) // end register user
|
|
> } else {
|
|
> console.log('User exists', { mail })
|
|
> AuthenticationManager.login(user, "randomPass", callback)
|
|
> }
|
|
> },
|
|
>
|
|
> authUserObj(error, user, query, password, callback) {
|
|
> if (process.env.ALLOW_EMAIL_LOGIN && user && user.hashedPassword) {
|
|
> console.log("email login for existing user " + query.email)
|
|
> // check passwd against local db
|
|
> bcrypt.compare(password, user.hashedPassword, function (error, match) {
|
|
> if (match) {
|
|
> console.log("Local user password match")
|
|
> _metricsForSuccessfulPasswordMatch(password)
|
|
> //callback(null, user, match)
|
|
> AuthenticationManager.login(user, "randomPass", callback)
|
|
> } else {
|
|
> console.log("Local user password mismatch, trying LDAP")
|
|
> // check passwd against ldap
|
|
> AuthenticationManager.ldapAuth(
|
|
> query,
|
|
> password,
|
|
> AuthenticationManager.createIfNotExistAndLogin,
|
|
> callback,
|
|
> user
|
|
> )
|
|
> }
|
|
> })
|
|
> } else {
|
|
> // No local passwd check user has to be in ldap and use ldap credentials
|
|
> AuthenticationManager.ldapAuth(
|
|
> query,
|
|
> password,
|
|
> AuthenticationManager.createIfNotExistAndLogin,
|
|
> callback,
|
|
> user
|
|
> )
|
|
> }
|
|
> return null
|
|
> },
|
|
>
|
|
> async ldapAuth(
|
|
> query,
|
|
> password,
|
|
> onSuccessCreateUserIfNotExistent,
|
|
> callback,
|
|
> user
|
|
> ) {
|
|
> const client = fs.existsSync(process.env.LDAP_SERVER_CACERT)
|
|
> ? new Client({
|
|
> url: process.env.LDAP_SERVER,
|
|
> tlsOptions: {
|
|
> ca: [fs.readFileSync(process.env.LDAP_SERVER_CACERT)],
|
|
> },
|
|
> })
|
|
> : new Client({
|
|
> url: process.env.LDAP_SERVER,
|
|
> })
|
|
>
|
|
> const ldap_reader = process.env.LDAP_BIND_USER
|
|
> const ldap_reader_pass = process.env.LDAP_BIND_PW
|
|
> const ldap_base = process.env.LDAP_BASE
|
|
>
|
|
> var mail = query.email
|
|
> var uid = query.email.split("@")[0]
|
|
> var firstname = ""
|
|
> var lastname = ""
|
|
> var isAdmin = false
|
|
> var userDn = ""
|
|
>
|
|
> //replace all appearences of %u with uid and all %m with mail:
|
|
> const replacerUid = new RegExp("%u", "g")
|
|
> const replacerMail = new RegExp("%m", "g")
|
|
> const filterstr = process.env.LDAP_USER_FILTER.replace(
|
|
> replacerUid,
|
|
> ldapEscape.filter`${uid}`
|
|
> ).replace(replacerMail, ldapEscape.filter`${mail}`) //replace all appearances
|
|
> // check bind
|
|
> try {
|
|
> if (process.env.LDAP_BINDDN) {
|
|
> //try to bind directly with the user trying to log in
|
|
> userDn = process.env.LDAP_BINDDN.replace(
|
|
> replacerUid,
|
|
> ldapEscape.filter`${uid}`
|
|
> ).replace(replacerMail, ldapEscape.filter`${mail}`)
|
|
> await client.bind(userDn, password)
|
|
> } else {
|
|
> // use fixed bind user
|
|
> await client.bind(ldap_reader, ldap_reader_pass)
|
|
> }
|
|
> } catch (ex) {
|
|
> if (process.env.LDAP_BINDDN) {
|
|
> console.log("Could not bind user: " + userDn)
|
|
> } else {
|
|
> console.log(
|
|
> "Could not bind LDAP reader: " + ldap_reader + " err: " + String(ex)
|
|
> )
|
|
> }
|
|
> return callback(null, null)
|
|
> }
|
|
>
|
|
> // get user data
|
|
> try {
|
|
> const { searchEntries, searchRef } = await client.search(ldap_base, {
|
|
> scope: "sub",
|
|
> filter: filterstr,
|
|
> })
|
|
> await searchEntries
|
|
> console.log(JSON.stringify(searchEntries))
|
|
> if (searchEntries[0]) {
|
|
> mail = searchEntries[0].mail
|
|
> uid = searchEntries[0].uid
|
|
> firstname = searchEntries[0].givenName
|
|
> lastname = searchEntries[0].sn
|
|
> if (!process.env.LDAP_BINDDN) {
|
|
> //dn is already correctly assembled
|
|
> userDn = searchEntries[0].dn
|
|
> }
|
|
> console.log(
|
|
> `Found user: ${mail} Name: ${firstname} ${lastname} DN: ${userDn}`
|
|
> )
|
|
> }
|
|
> } catch (ex) {
|
|
> console.log(
|
|
> "An Error occured while getting user data during ldapsearch: " +
|
|
> String(ex)
|
|
> )
|
|
> await client.unbind()
|
|
> return callback(null, null)
|
|
> }
|
|
>
|
|
> try {
|
|
> // if admin filter is set - only set admin for user in ldap group
|
|
> // does not matter - admin is deactivated: managed through ldap
|
|
> if (process.env.LDAP_ADMIN_GROUP_FILTER) {
|
|
> const adminfilter = process.env.LDAP_ADMIN_GROUP_FILTER.replace(
|
|
> replacerUid,
|
|
> ldapEscape.filter`${uid}`
|
|
> ).replace(replacerMail, ldapEscape.filter`${mail}`)
|
|
> adminEntry = await client.search(ldap_base, {
|
|
> scope: "sub",
|
|
> filter: adminfilter,
|
|
> })
|
|
> await adminEntry
|
|
> //console.log('Admin Search response:' + JSON.stringify(adminEntry.searchEntries))
|
|
> if (adminEntry.searchEntries[0]) {
|
|
> console.log("is Admin")
|
|
> isAdmin = true
|
|
> }
|
|
> }
|
|
> } catch (ex) {
|
|
> console.log(
|
|
> "An Error occured while checking for admin rights - setting admin rights to false: " +
|
|
> String(ex)
|
|
> )
|
|
> isAdmin = false
|
|
> } finally {
|
|
> await client.unbind()
|
|
> }
|
|
> if (mail == "" || userDn == "") {
|
|
> console.log(
|
|
> "Mail / userDn not set - exit. This should not happen - please set mail-entry in ldap."
|
|
> )
|
|
> return callback(null, null)
|
|
> }
|
|
>
|
|
> if (!process.env.BINDDN) {
|
|
> //since we used a fixed bind user to obtain the correct userDn we need to bind again to authenticate
|
|
> try {
|
|
> await client.bind(userDn, password)
|
|
> } catch (ex) {
|
|
> console.log("Could not bind User: " + userDn + " err: " + String(ex))
|
|
> return callback(null, null)
|
|
> } finally {
|
|
> await client.unbind()
|
|
> }
|
|
> }
|
|
> //console.log('Logging in user: ' + mail + ' Name: ' + firstname + ' ' + lastname + ' isAdmin: ' + String(isAdmin))
|
|
> // we are authenticated now let's set the query to the correct mail from ldap
|
|
> query.email = mail
|
|
> User.findOne(query, (error, user) => {
|
|
> if (error) {
|
|
> console.log(error)
|
|
> }
|
|
> if (user && user.hashedPassword) {
|
|
> //console.log('******************** LOGIN ******************')
|
|
> AuthenticationManager.login(user, "randomPass", callback)
|
|
> } else {
|
|
> onSuccessCreateUserIfNotExistent(
|
|
> query,
|
|
> user,
|
|
> callback,
|
|
> uid,
|
|
> firstname,
|
|
> lastname,
|
|
> mail,
|
|
> isAdmin
|
|
> )
|
|
> }
|
|
> })
|
|
> },
|
|
> // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|