From b0a48fd69357528b16bca9a045f89f2b64cee3c1 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sat, 21 Sep 2024 10:44:27 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A7=20feat:=20LDAP=20Authentication=20?= =?UTF-8?q?Enhancement=20for=20Email=20Handling=20(#4177)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * allow other ldap field besides "mail", or fallback to made up email * chore(ldap): add detailed logging for email fallback scenarios --------- Co-authored-by: Maxim Bonnaerens --- .env.example | 1 + api/strategies/ldapStrategy.js | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.env.example b/.env.example index 5571fe46cf..0b56317ff3 100644 --- a/.env.example +++ b/.env.example @@ -412,6 +412,7 @@ LDAP_CA_CERT_PATH= # LDAP_LOGIN_USES_USERNAME=true # LDAP_ID= # LDAP_USERNAME= +# LDAP_EMAIL= # LDAP_FULL_NAME= #========================# diff --git a/api/strategies/ldapStrategy.js b/api/strategies/ldapStrategy.js index 756e1da422..4d9124bb6a 100644 --- a/api/strategies/ldapStrategy.js +++ b/api/strategies/ldapStrategy.js @@ -14,6 +14,7 @@ const { LDAP_FULL_NAME, LDAP_ID, LDAP_USERNAME, + LDAP_EMAIL, LDAP_TLS_REJECT_UNAUTHORIZED, } = process.env; @@ -43,6 +44,9 @@ if (LDAP_ID) { if (LDAP_USERNAME) { searchAttributes.push(LDAP_USERNAME); } +if (LDAP_EMAIL) { + searchAttributes.push(LDAP_EMAIL); +} const rejectUnauthorized = isEnabled(LDAP_TLS_REJECT_UNAUTHORIZED); const ldapOptions = { @@ -76,15 +80,6 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => { return done(null, false, { message: 'Invalid credentials' }); } - if (!userinfo.mail) { - logger.warn( - '[ldapStrategy]', - 'No email attributes found in userinfo', - JSON.stringify(userinfo, null, 2), - ); - return done(null, false, { message: 'Invalid credentials' }); - } - try { const ldapId = (LDAP_ID && userinfo[LDAP_ID]) || userinfo.uid || userinfo.sAMAccountName || userinfo.mail; @@ -100,12 +95,25 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => { const username = (LDAP_USERNAME && userinfo[LDAP_USERNAME]) || userinfo.givenName || userinfo.mail; + const mail = (LDAP_EMAIL && userinfo[LDAP_EMAIL]) || userinfo.mail || username + '@ldap.local'; + + if (!userinfo.mail && !(LDAP_EMAIL && userinfo[LDAP_EMAIL])) { + logger.warn( + '[ldapStrategy]', + `No valid email attribute found in LDAP userinfo. Using fallback email: ${username}@ldap.local`, + `LDAP_EMAIL env var: ${LDAP_EMAIL || 'not set'}`, + `Available userinfo attributes: ${Object.keys(userinfo).join(', ')}`, + 'Full userinfo:', + JSON.stringify(userinfo, null, 2), + ); + } + if (!user) { user = { provider: 'ldap', ldapId, username, - email: userinfo.mail, + email: mail, emailVerified: true, // The ldap server administrator should verify the email name: fullName, }; @@ -116,7 +124,7 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => { // so update the user information with the values registered in LDAP user.provider = 'ldap'; user.ldapId = ldapId; - user.email = userinfo.mail; + user.email = mail; user.username = username; user.name = fullName; }