Compare commits
13 Commits
a921973929
...
55a1efcb4e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55a1efcb4e | ||
|
|
403350df9b | ||
|
|
a3650e1477 | ||
|
|
a3f0a2cf88 | ||
|
|
6e6c48ddc8 | ||
|
|
26750b931a | ||
|
|
100ae5923a | ||
|
|
93fe1c0ede | ||
|
|
f705d41d8c | ||
|
|
0c214e4ed8 | ||
|
|
f25765e36f | ||
|
|
bcdd625f13 | ||
|
|
1539449b51 |
@@ -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
|
||||||
|
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -42,4 +42,11 @@ PLUGIN_LOGIN_LDAP:
|
|||||||
VERSION_DESC: 'LDAP Version 3 is most popular, only change this if you know what you are doing'
|
VERSION_DESC: 'LDAP Version 3 is most popular, only change this if you know what you are doing'
|
||||||
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'
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user