Compare commits

..

13 Commits

Author SHA1 Message Date
Jannik Radix
55a1efcb4e Add search bind support, fix group_identifier typo, fix gidNumber query
- Add search_bind_enabled/search_bind_dn/search_bind_password config
- Support both group_indentifier (original typo) and group_identifier
- Skip gidNumber query when attribute is empty
- Use searchLdap for all search/group queries
2026-02-24 22:03:14 +01:00
Andy Miller
403350df9b Merge pull request #35 from Linegod/patch-1
Fix issue #28 - Grav username defaults to the LDAP users full DN
2025-11-23 17:58:09 +00:00
J.P. Pasnak
a3650e1477 Fix issue #28 - Grav username defaults to the LDAP users full DN
Additional fix assignment operator bug in error handling
2025-11-22 21:30:07 -06:00
Andy Miller
a3f0a2cf88 Merge tag '1.1.0' into develop
Release v1.1.0
2024-04-16 11:16:53 -06:00
Andy Miller
6e6c48ddc8 Merge branch 'release/1.1.0' 2024-04-16 11:16:53 -06:00
Andy Miller
26750b931a prepare for release 2024-04-16 11:16:43 -06:00
Andy Miller
100ae5923a updated changelog 2024-04-16 11:15:09 -06:00
Andy Miller
93fe1c0ede Merge pull request #31 from ViliusS/fix-php81-error
Fix plugin installation under PHP 8.1
2024-04-16 11:11:03 -06:00
Vilius Šumskas
f705d41d8c Fix plugin installation under PHP 8.1 2024-04-16 13:21:43 +03:00
Andy Miller
0c214e4ed8 Merge pull request #19 from ViliusS/update-ldap-documentation
Add LDAP configuration example for Active Directory
2023-03-08 15:20:22 -07:00
Vilius Šumskas
f25765e36f Better grammar logic 2023-03-08 23:41:31 +02:00
Vilius Šumskas
bcdd625f13 gramar fix 2020-11-08 17:58:08 +02:00
Vilius Šumskas
1539449b51 Add LDAP configuration example for Active Directory
Also, add missing documentation regarding map_dn parameter and make it clear that referrals should be disabled for all new Windows versions.
2020-11-08 17:51:02 +02:00
6 changed files with 104 additions and 16 deletions

View File

@@ -1,3 +1,11 @@
# v1.1.0
## 04/16/2024
1. [](#improved)
* Stop event propagation on empty username [#27](https://github.com/trilbymedia/grav-plugin-login-ldap/pulls/27)
* Add LDAP configuration example for Active Directory [#19](https://github.com/trilbymedia/grav-plugin-login-ldap/pulls/19)
* Fix plugin installation under PHP 8.1 [#31](https://github.com/trilbymedia/grav-plugin-login-ldap/pulls/31)
# v1.0.2 # v1.0.2
## 11/16/2020 ## 11/16/2020

View File

@@ -50,6 +50,7 @@ group_indentifier: cn
map_username: uid map_username: uid
map_fullname: givenName lastName map_fullname: givenName lastName
map_email: mail map_email: mail
map_dn: distinguishedName
save_grav_user: false save_grav_user: false
store_ldap_data: false store_ldap_data: false
default_access_levels: default_access_levels:
@@ -78,7 +79,7 @@ default_access_levels:
|version|LDAP Version 3 is most popular (only change this if you know what you are doing) | [default: `3`] | |version|LDAP Version 3 is most popular (only change this if you know what you are doing) | [default: `3`] |
|ssl|Enable SSL for the connection (typically for port 636 or 3269) | `true` \| [default: `false`] | |ssl|Enable SSL for the connection (typically for port 636 or 3269) | `true` \| [default: `false`] |
|start_tls|Negotiate TLS encryption with the LDAP server (requires all traffic to be encrypted) | `true` \| [default: `false`] | |start_tls|Negotiate TLS encryption with the LDAP server (requires all traffic to be encrypted) | `true` \| [default: `false`] |
|opt_referrals|Sets the value of LDAP_OPT_REFERRALS (Set to "off" for Windows 2003 servers) | `true` \| [default: `false`] | |opt_referrals|Sets the value of LDAP_OPT_REFERRALS (leave it disabled for Windows 2003 and later servers) | `true` \| [default: `false`] |
### LDAP Configuration ### LDAP Configuration
@@ -92,6 +93,23 @@ default_access_levels:
|map_username|LDAP Attribute(s) that contains the user's username | [default: `uid`] | |map_username|LDAP Attribute(s) that contains the user's username | [default: `uid`] |
|map_fullname|LDAP Attribute(s) that contains the user's full name | [default: `givenName lastName`] | |map_fullname|LDAP Attribute(s) that contains the user's full name | [default: `givenName lastName`] |
|map_email|LDAP Attribute(s) that contains the user's email address | [default: `mail`] | |map_email|LDAP Attribute(s) that contains the user's email address | [default: `mail`] |
|map_dn|LDAP Attribute that contains the user's DN String | [default: `distinguishedName`] |
### Examples
#### Active Directory with pre-Windows 2000 style logins
|Key | Value |
|:---------------------|:-------|
|user_dn| `YOURDOMAIN\[username]` |
|search_dn| `ou=users,dc=yourdomain,dc=local` |
|group_dn| `ou=groups,dc=yourdomain,dc=local` |
|group_query| `(&(cn=*)(member=[dn]))` or `(&(cn=*)(member:1.2.840.113556.1.4.1941:=[dn]))` for nested group support |
|group_indentifier| `cn` |
|map_username| `sAMAccountName` |
|map_fullname| `displayName` |
|map_email| `mail` |
|map_dn| `distinguishedName` |
### Advanced Configuration ### Advanced Configuration

View File

@@ -1,5 +1,5 @@
name: Login LDAP name: Login LDAP
version: 1.0.2 version: 1.2.0
description: Allows for Grav user authentication against an LDAP Server such as OpenLDAP or ActiveDirectory description: Allows for Grav user authentication against an LDAP Server such as OpenLDAP or ActiveDirectory
icon: user-circle-o icon: user-circle-o
author: author:
@@ -108,6 +108,38 @@ form:
validate: validate:
type: bool type: bool
search_bind_section:
type: section
title: PLUGIN_LOGIN_LDAP.SEARCH_BIND_CONFIGURATION
underline: true
fields:
search_bind_enabled:
type: toggle
label: PLUGIN_LOGIN_LDAP.SEARCH_BIND_ENABLE
help: PLUGIN_LOGIN_LDAP.SEARCH_BIND_ENABLE_DESC
default: 0
highlight: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
search_bind_dn:
type: text
label: PLUGIN_LOGIN_LDAP.SEARCH_BIND_DN
size: large
placeholder: cn=readonly,dc=company,dc=com
help: PLUGIN_LOGIN_LDAP.SEARCH_BIND_DN_DESC
search_bind_password:
type: password
label: PLUGIN_LOGIN_LDAP.SEARCH_BIND_PASSWORD
size: large
help: PLUGIN_LOGIN_LDAP.SEARCH_BIND_PASSWORD_DESC
config_section: config_section:
type: section type: section
title: LDAP Configuration title: LDAP Configuration
@@ -219,7 +251,6 @@ form:
type: commalist type: commalist
blacklist_ldap_fields: blacklist_ldap_fields:
type: array
type: array type: array
value_only: true value_only: true
label: PLUGIN_LOGIN_LDAP.BLACKLIST_FIELDS label: PLUGIN_LOGIN_LDAP.BLACKLIST_FIELDS

View File

@@ -43,3 +43,10 @@ PLUGIN_LOGIN_LDAP:
BLACKLIST_FIELDS: 'Blacklist Fields' BLACKLIST_FIELDS: 'Blacklist Fields'
BLACKLIST_FIELDS_HELP: 'A list of LDAP fields to be skipped and ignored' BLACKLIST_FIELDS_HELP: 'A list of LDAP fields to be skipped and ignored'
BLACKLIST_FIELDS_PLACEHOLDER: 'Field (ie, jpegPhoto, homePostalAddress)' BLACKLIST_FIELDS_PLACEHOLDER: 'Field (ie, jpegPhoto, homePostalAddress)'
SEARCH_BIND_CONFIGURATION: 'Search Bind Configuration'
SEARCH_BIND_ENABLE: 'Use Search Bind'
SEARCH_BIND_ENABLE_DESC: 'Use a dedicated LDAP account for user/group searches (useful when regular users lack search permissions)'
SEARCH_BIND_DN: 'Search Bind DN'
SEARCH_BIND_DN_DESC: 'Full DN of the LDAP account used for searches (e.g. cn=readonly,dc=company,dc=com)'
SEARCH_BIND_PASSWORD: 'Search Bind Password'
SEARCH_BIND_PASSWORD_DESC: 'Password for the search bind account'

View File

@@ -83,7 +83,9 @@ class LoginLDAPPlugin extends Plugin
$search_dn = $this->config->get('plugins.login-ldap.search_dn'); $search_dn = $this->config->get('plugins.login-ldap.search_dn');
$group_dn = $this->config->get('plugins.login-ldap.group_dn'); $group_dn = $this->config->get('plugins.login-ldap.group_dn');
$group_query = $this->config->get('plugins.login-ldap.group_query'); $group_query = $this->config->get('plugins.login-ldap.group_query');
$group_indentifier = $this->config->get('plugins.login-ldap.group_indentifier'); // Support both the original typo (group_indentifier) and the correct spelling (group_identifier)
$group_indentifier = $this->config->get('plugins.login-ldap.group_indentifier')
?? $this->config->get('plugins.login-ldap.group_identifier', 'cn');
$username = str_replace('[username]', $credentials['username'], $user_dn); $username = str_replace('[username]', $credentials['username'], $user_dn);
@@ -96,6 +98,11 @@ class LoginLDAPPlugin extends Plugin
$opt_referrals = $this->config->get('plugins.login-ldap.opt_referrals'); $opt_referrals = $this->config->get('plugins.login-ldap.opt_referrals');
$blacklist = $this->config->get('plugins.login-ldap.blacklist_ldap_fields', []); $blacklist = $this->config->get('plugins.login-ldap.blacklist_ldap_fields', []);
// Alternate search user (for when regular users lack search permissions)
$search_bind_enabled = $this->config->get('plugins.login-ldap.search_bind_enabled', false);
$search_bind_dn = $this->config->get('plugins.login-ldap.search_bind_dn');
$search_bind_password = $this->config->get('plugins.login-ldap.search_bind_password');
if (is_null($host)) { if (is_null($host)) {
throw new ConnectionException('FATAL: LDAP host entry missing in plugin configuration...'); throw new ConnectionException('FATAL: LDAP host entry missing in plugin configuration...');
} }
@@ -110,8 +117,7 @@ class LoginLDAPPlugin extends Plugin
} }
try { try {
/** @var Ldap $ldap */ $ldap_config = array(
$ldap = Ldap::create('ext_ldap', array(
'host' => $host, 'host' => $host,
'port' => $port, 'port' => $port,
'encryption' => $encryption, 'encryption' => $encryption,
@@ -119,7 +125,10 @@ class LoginLDAPPlugin extends Plugin
'protocol_version' => $version, 'protocol_version' => $version,
'referrals' => (bool) $opt_referrals, 'referrals' => (bool) $opt_referrals,
), ),
)); );
/** @var Ldap $ldap */
$ldap = Ldap::create('ext_ldap', $ldap_config);
// Map Info // Map Info
$map_username = $this->config->get('plugins.login-ldap.map_username'); $map_username = $this->config->get('plugins.login-ldap.map_username');
@@ -130,8 +139,17 @@ class LoginLDAPPlugin extends Plugin
// Try to login via LDAP // Try to login via LDAP
$ldap->bind($username, $credentials['password']); $ldap->bind($username, $credentials['password']);
// Set up search LDAP connection (use separate bind if configured)
if ($search_bind_enabled && $search_bind_dn) {
/** @var Ldap $searchLdap */
$searchLdap = Ldap::create('ext_ldap', $ldap_config);
$searchLdap->bind($search_bind_dn, $search_bind_password);
} else {
$searchLdap = $ldap;
}
// Create Grav User // Create Grav User
$grav_user = User::load(strtolower($username)); $grav_user = User::load(strtolower($credentials['username']));
// Set defaults with only thing we know... username provided // Set defaults with only thing we know... username provided
$grav_user['login'] = $credentials['username']; $grav_user['login'] = $credentials['username'];
@@ -141,7 +159,7 @@ class LoginLDAPPlugin extends Plugin
// If search_dn is set we can try to get information from LDAP // If search_dn is set we can try to get information from LDAP
if ($search_dn) { if ($search_dn) {
$query_string = $map_username .'='. $credentials['username']; $query_string = $map_username .'='. $credentials['username'];
$query = $ldap->query($search_dn, $query_string); $query = $searchLdap->query($search_dn, $query_string);
$results = $query->execute()->toArray(); $results = $query->execute()->toArray();
// Get LDAP Data // Get LDAP Data
@@ -179,13 +197,16 @@ class LoginLDAPPlugin extends Plugin
if ($group_dn) { if ($group_dn) {
// retrieves all extra groups for user // retrieves all extra groups for user
$group_query = str_replace('[username]', $credentials['username'], $group_query); $group_query = str_replace('[username]', $credentials['username'], $group_query);
$group_query = str_replace('[dn]', $ldap->escape($userdata['dn'], '', LdapInterface::ESCAPE_FILTER), $group_query); $group_query = str_replace('[dn]', $searchLdap->escape($userdata['dn'], '', LdapInterface::ESCAPE_FILTER), $group_query);
$query = $ldap->query($group_dn, $group_query); $query = $searchLdap->query($group_dn, $group_query);
$groups = $query->execute()->toArray(); $groups = $query->execute()->toArray();
// retrieve current primary group for user // retrieve current primary group for user (posixGroup support)
$query = $ldap->query($group_dn, 'gidnumber=' . $this->getLDAPMappedItem('gidNumber', $ldap_data)); $gidNumber = $this->getLDAPMappedItem('gidNumber', $ldap_data);
$groups = array_merge($groups, $query->execute()->toArray()); if (!empty($gidNumber)) {
$query = $searchLdap->query($group_dn, 'gidnumber=' . $gidNumber);
$groups = array_merge($groups, $query->execute()->toArray());
}
foreach ($groups as $group) { foreach ($groups as $group) {
$attributes = $group->getAttributes(); $attributes = $group->getAttributes();
@@ -258,7 +279,7 @@ class LoginLDAPPlugin extends Plugin
$this->grav['log']->error('plugin.login-ldap: ['. $e->getCode() . '] ' . $username . ' - ' . $message); $this->grav['log']->error('plugin.login-ldap: ['. $e->getCode() . '] ' . $username . ' - ' . $message);
// Just return so other authenticators can take a shot... // Just return so other authenticators can take a shot...
if ($message = "Invalid credentials") { if ($message == "Invalid credentials") {
return; return;
} }

View File

@@ -5,6 +5,9 @@ version: 3
ssl: false ssl: false
start_tls: false start_tls: false
opt_referrals: false opt_referrals: false
search_bind_enabled: false
search_bind_dn:
search_bind_password:
user_dn: 'uid=[username],dc=company,dc=com' user_dn: 'uid=[username],dc=company,dc=com'
search_dn: search_dn:
group_dn: group_dn: