Ошибка PassportJS: никакие другие операции не могут быть выполнены над соединением, пока привязка прерывается периодически - PullRequest
1 голос
/ 07 марта 2019

TLDR: Есть ли проблема состояния гонки с passportjs или passport-ldapauth ?

Я использую библиотеку koa-passport со стратегией passport-ldapauth в приложении nodejs, предназначенном для аутентификации пользователя в AD (Active Directory). Вау, это был полный рот.

Вот ошибка, которую я получаю от passport.authenticate, которая, я предполагаю, возвращается из LDAP:

BusyError: 00002024: LdapErr: DSID-0C060810, comment: No other operations may be performed on the connection while a bind is outstanding.

Проблема здесь очевидна, существует невыполненная привязка, и она должна быть закрыта, прежде чем я смогу сделать другую привязку для аутентификации следующего пользователя. Решение, однако, не так, оно может лежать либо с LDAP или это может лежать с паспортами. Я здесь в надежде найти решение для последнего. (Собираемся изучить параметры конфигурации для LDAP, ожидая ответа на этом # multiprocessing )

Вот мой код:

import passport from 'koa-passport';
import LdapStrategy from 'passport-ldapauth';
import { readFileSync } from 'fs';
const ldapCert = readFileSync(process.env.LDAP_CERT, 'utf8');

const ldapConfig = {
  server: {
    url: process.env.LDAP_URL,
    bindDN: process.env.LDAP_BINDDN,
    bindCredentials: process.env.LDAP_PASSWORD,
    searchBase: process.env.LDAP_SEARCH_BASE,
    searchFilter: process.env.LDAP_SEARCH_FILTER,
    searchAttributes: ['sAMAccountName'],
    tlsOptions: {
      ca: [ldapCert]
    }
  }
};

module.exports = async (ctx, next) => {
  passport.initialize();
  passport.use(new LdapStrategy(ldapConfig));
  await passport.authenticate('ldapauth', { session: false }, async (err, user, info) => {
    if (err) {
      console.log('Invalid Authentication Error');
      ctx.throw('INVALID_AUTHENTICATION');
    } else if (!user) {
      console.log('Invalid username or password Error');
      ctx.throw('INVALID_USERNAME_PASSWORD');
    } else {
      await next(); // continue to authorization flow
    }
  })(ctx, next);

Прежде чем мы начнем, знайте, что все ldapConfigs остаются неизменными на протяжении всего жизненного цикла приложения, что означает, что я использую одно и то же BINDDN и ПАРОЛЬ для каждого поиска.

Так, как указано в заголовке, эта ошибка происходит с перебоями. Таким образом, сам код работает в целом, и я могу аутентифицировать пользователей примерно в 95% случаев, и если он когда-либо выдает ошибку INVALID_AUTHENTICATION, когда пароль был верным, то есть, когда я получаю BusyError в логах.

Эта проблема более заметна и ее легче воспроизвести, когда я ввожу поддельное имя пользователя / пароль, в идеале мне следует выдать сообщение об ошибке INVALID_USERNAME_PASSWORD, что составляет около 75% времени. Остальные 25% я получаю INVALID_AUTHENTICATION.

Я даже пытался воспроизвести его, используя ldapsearch инструмент командной строки, в паре с tmux. Я выполнил вызов в ~ 20 панелях одновременно, используя один и тот же binddn, и они все вернулись просто отлично (я должен попытаться запустить его с большим количеством? 100? 1000?). Именно это заставило меня поверить, что проблемы были не с LDAP или AD, а с passportjs.

Я пришел к выводу, что, возможно, есть проблема с расой в паспорте JS, но я не смог найти никакой литературы по сетям. Кто-нибудь сталкивался с чем-то подобным? Я полагаю, что, возможно, привязка не закрывается, потому что иногда passport.authenticate может возвращаться до вызова обратного вызова? Это вообще возможно? Это как-то связано с тем, как я его кодировал с помощью async / await?

Мой запасной вариант может состоять в том, чтобы полностью отказаться от passportjs и просто попробовать с ldapjs. Любые мысли, комментарии, предложения, обсуждения будут оценены

Вот полная трассировка стека, если необходимо:

BusyError: 00002024: LdapErr: DSID-0C060810, comment: No other operations may be performed on the connection while a bind is outstanding., data 0, v3839
    at messageCallback (/app/node_modules/ldapjs/lib/client/client.js:1419:45)
    at Parser.onMessage (/app/node_modules/ldapjs/lib/client/client.js:1089:14)
    at emitOne (events.js:116:13)
    at Parser.emit (events.js:211:7)
    at Parser.write (/app/node_modules/ldapjs/lib/messages/parser.js:111:8)
    at TLSSocket.onData (/app/node_modules/ldapjs/lib/client/client.js:1076:22)
    at emitOne (events.js:116:13)
    at TLSSocket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at TLSSocket.Readable.push (_stream_readable.js:208:10)
    at TLSWrap.onread (net.js:597:20)
InternalServerError: INVALID_AUTHENTICATION
    at Object.throw (/app/node_modules/koa/lib/context.js:97:11)
...