Invalid grant: user credentials are invalid when using LDAP

I installed Peertube 3.1.0 with peertube-auth-ldap-plugin. Settings of the LDAP plugin:

  • URL: ldaps://ldap.example.com
  • Bind DN: cn=bind,dc=example,dc=com
  • Bind password: $pass
  • Search base: ou=People,dc=example,dc=com
  • Search filter: (uid={{username}})
  • Mail property: mail
  • Username property: uid

Login fails with « invalid username or password » and the logs contain the following:

[peertube.example.com:443] 2021-04-19 14:34:44.464 info: Login success with auth method ldap of plugin peertube-plugin-auth-ldap for testuser.
[peertube.example.com:443] 2021-04-19 14:34:44.468 info: Bypassing oauth login by plugin peertube-plugin-auth-ldap.
[peertube.example.com:443] 2021-04-19 14:34:44.488 warn: Login error. {
  "err": {
    "statusCode": 400,
    "status": 400,
    "code": 400,
    "message": "Invalid grant: user credentials are invalid",
    "name": "invalid_grant",
    "stack": "invalid_grant: Invalid grant: user credentials are invalid\n    at new InvalidGrantError (/var/www/peertube/versions/peertube-v3.1.0/node_modules/oauth2-server/lib/errors/invalid-grant-error.js:27:14)\n    at /var/www/peertube/versions/peertube-v3.1.0/node_modules/oauth2-server/lib/grant-types/password-grant-type.js:94:15\n    at tryCatcher (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/util.js:16:23)\n    at Promise._settlePromiseFromHandler (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/promise.js:547:31)\n    at Promise._settlePromise (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/promise.js:604:18)\n    at Promise._settlePromise0 (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/promise.js:649:10)\n    at Promise._settlePromises (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/promise.js:729:18)\n    at _drainQueueStep (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/async.js:93:12)\n    at _drainQueue (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/async.js:86:9)\n    at Async._drainQueues (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/async.js:102:5)\n    at Immediate.Async.drainQueues [as _onImmediate] (/var/www/peertube/versions/peertube-v3.1.0/node_modules/bluebird/js/release/async.js:15:14)\n    at processImmediate (internal/timers.js:461:21)"

The error messages in the log differ when an invalid username or invalid password is supplied, so I think LDAP is working as expected. Username and mail attributes are properly extracted and returned by the LDAP plugin. Do I miss something obvious here? Thx!

Found the culprit. The mail attribute returned by LDAP was already taken by a non-LDAP user.