diff --git a/.gitignore b/.gitignore
index ef624d1..afd34bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,4 @@ config_ldap.php
config_db.php
data
certs
-
+.vscode
diff --git a/Demo/docker-compose.yaml b/Demo/docker-compose.yaml
index ae44233..9425cd5 100644
--- a/Demo/docker-compose.yaml
+++ b/Demo/docker-compose.yaml
@@ -45,6 +45,9 @@ services:
ldap_filter: "(objectClass=*)"
ldap_bind_dn: "cn=butler,dc=example,dc=com"
ldap_bind_pass: "readonly"
+ ldap_secure: 0
+ ldap_cert_path: "/var/www/html/oauth/certs/cert.crt"
+ ldap_key_path: "/var/www/html/oauth/certs/private.key"
db_host: "database"
db_port: "5432"
db_type: "pgsql"
diff --git a/Docker/php-ldap-pgsql/Dockerfile b/Docker/php-ldap-pgsql/Dockerfile
index f901b35..073add2 100644
--- a/Docker/php-ldap-pgsql/Dockerfile
+++ b/Docker/php-ldap-pgsql/Dockerfile
@@ -1,13 +1,17 @@
-FROM php:fpm
+FROM php:8.3.4-fpm-alpine
RUN set -x \
- && apt-get update \
- && apt-get install -y libpq-dev libldap2-dev git\
- && rm -rf /var/lib/apt/lists/* \
+ && apk update \
+ && apk add --no-cache libpq-dev git \
&& docker-php-ext-configure pgsql --with-pgsql=/usr/local/pgsql \
- && docker-php-ext-install pdo pdo_pgsql pgsql \
- && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \
- && docker-php-ext-install ldap
+ && docker-php-ext-install pdo pdo_pgsql pgsql
+
+RUN set -x \
+ && apk add --no-cache --virtual .build-dependencies-in-virtual-world openldap-dev \
+ && apk add --no-cache libldap \
+ && docker-php-ext-install ldap \
+ && docker-php-ext-enable ldap \
+ && apk del .build-dependencies-in-virtual-world
# Enable development php.ini config (Solve empty answer from token.php)
RUN ln -s /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
diff --git a/README.md b/README.md
index 0f7e14e..2e2142b 100755
--- a/README.md
+++ b/README.md
@@ -160,6 +160,9 @@ Edit `oauth/LDAP/config_ldap.php` and adapt prameters with your LDAP configurati
| ldap_base_dn | The base directory name of your LDAP server | `ou=People,o=Company` |
| ldap_bind_dn | The LDAP Directory Name of an service account to allow LDAP search | |
| ldap_bind_pass | The password associated to the service account to allow LDAP search | |
+| ldap_secure | LDAP over ldaps (ex:ldaps://ldap.google.com) | `false` |
+| ldap_cert_path | LDAP certificate file for secure LDAP | `/var/www/html/oauth/certs/certificate.crt`|
+| ldap_key_path | LDAP private key file for secure LDAP | `/var/www/html/oauth/certs/key.key`|
For openLDAP server, the 'ldap_search_attribute' should be `uid`, and for AD server this must be `sAMAccountName`. Nevertheless, 'email' or 'cn' could be used, this depends on your LDAP configuration.
diff --git a/oauth/LDAP/LDAP.php b/oauth/LDAP/LDAP.php
index 3d13cfe..406a8ae 100755
--- a/oauth/LDAP/LDAP.php
+++ b/oauth/LDAP/LDAP.php
@@ -14,20 +14,26 @@ class LDAP implements LDAPInterface
protected $ldap_server;
/**
- * LDAP Resource
- *
- * @param string @ldap_host
- * Either a hostname or, with OpenLDAP 2.x.x and later, a full LDAP URI
- * @param int @ldap_port
- * An optional int to specify ldap server port, by default : 389
- * @param int @ldap_version
- * An optional int to specify ldap version, by default LDAP V3 protocol is used
- * @param boolean @ldap_start_tls
- * An optional boolean to use ldap over STARTTLS, by default LDAP STARTTLS is not used
- *
- * Initiate LDAP connection by creating an associated resource
- */
- public function __construct($ldap_host, $ldap_port = 389, $ldap_version = 3, $ldap_start_tls = false)
+ * LDAP Resource
+ *
+ * @param string @ldap_host
+ * Either a hostname or, with OpenLDAP 2.x.x and later, a full LDAP URI
+ * @param int @ldap_port
+ * An optional int to specify ldap server port, by default : 389
+ * @param int @ldap_version
+ * An optional int to specify ldap version, by default LDAP V3 protocol is used
+ * @param boolean @ldap_start_tls
+ * An optional boolean to use ldap over STARTTLS, by default LDAP STARTTLS is not used
+ * @param string @ldap_cert_path
+ * An optional string to specify the path to the certificate file
+ * @param string @ldap_key_path
+ * An optional string to specify the path to the key file
+ * @param boolean @ldap_secure
+ * An optional boolean to use ldap over secure connection, by default LDAP secure connection is not used
+ *
+ * Initiate LDAP connection by creating an associated resource
+ */
+ public function __construct($ldap_host, $ldap_port = 389, $ldap_version = 3, $ldap_start_tls = false, $ldap_cert_path, $ldap_key_path, $ldap_secure = false)
{
if (!is_string($ldap_host)) {
throw new InvalidArgumentException('First argument to LDAP must be the hostname of a ldap server (string). Ex: ldap//example.com/ ');
@@ -37,12 +43,23 @@ public function __construct($ldap_host, $ldap_port = 389, $ldap_version = 3, $ld
throw new InvalidArgumentException('Second argument to LDAP must be the ldap server port (int). Ex : 389');
}
+ // Connect to LDAP server using secure connection with certificate and key
+ if ($ldap_secure === true) {
+ if (!is_string($ldap_cert_path)) {
+ throw new InvalidArgumentException('Fifth argument to LDAP must be the path to the certificate file (string).');
+ }
+ if (!is_string($ldap_key_path)) {
+ throw new InvalidArgumentException('Sixth argument to LDAP must be the path to the key file (string).');
+ }
+ }
+
$ldap = ldap_connect($ldap_host, $ldap_port)
- or die("Unable to connect to the ldap server : $ldaphost ! Please check your configuration.");
+ or die("Unable to connect to the ldap server : $ldap_host ! Please check your configuration.");
// Support LDAP V3 since many users have encountered difficulties with LDAP V3.
if (is_int($ldap_version) && $ldap_version <= 3 && $ldap_version > 0) {
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, $ldap_version);
+ ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
} else {
throw new InvalidArgumentException('Third argument to LDAP must be the ldap version (int). Ex : 3');
}
diff --git a/oauth/LDAP/config_ldap.php.example b/oauth/LDAP/config_ldap.php.example
index 4a1c4c1..89ce028 100755
--- a/oauth/LDAP/config_ldap.php.example
+++ b/oauth/LDAP/config_ldap.php.example
@@ -4,6 +4,11 @@ $ldap_host = getenv('ldap_host') ?: "ldap://ldap.company.com/";
$ldap_port = intval(getenv('ldap_port')) ?: 389;
$ldap_version = intval(getenv('ldap_version')) ?: 3;
$ldap_start_tls = boolval(getenv('ldap_start_tls')) ?: false;
+$ldap_secure = boolval(getenv('ldap_secure')) ?: false;
+
+// Certificates
+$ldap_cert_path = getenv('ldap_cert_path') ?: "/var/www/html/oauth/certs/certificate.crt";
+$ldap_key_path = getenv('ldap_key_path') ?: "/var/www/html/oauth/certs/key.key";
// Attribute use to identify user on LDAP - ex : uid, mail, sAMAccountName
$ldap_search_attribute = getenv('ldap_search_attribute') ?: "uid";
@@ -15,3 +20,4 @@ $ldap_filter = getenv('ldap_filter') ?: "(objectClass=*)";
// ldap service user to allow search in ldap
$ldap_bind_dn = getenv('ldap_bind_dn') ?: "";
$ldap_bind_pass = getenv('ldap_bind_pass') ?: "";
+
diff --git a/oauth/index.php b/oauth/index.php
index 9a7e804..a14accd 100644
--- a/oauth/index.php
+++ b/oauth/index.php
@@ -7,14 +7,15 @@
// include our LDAP object
-require_once __DIR__.'/LDAP/LDAP.php';
-require_once __DIR__.'/LDAP/config_ldap.php';
+require_once __DIR__ . '/LDAP/LDAP.php';
+require_once __DIR__ . '/LDAP/config_ldap.php';
$prompt_template = new DOMDocument();
$prompt_template->loadHTMLFile('form_prompt.html');
-function messageShow($html_template, $message = 'No Msg') {
+function messageShow($html_template, $message = 'No Msg')
+{
$modification_node = $html_template->getElementsByTagName('div')->item(5);
$page_fragment = $html_template->createDocumentFragment();
$page_fragment->appendXML($message);
@@ -24,66 +25,55 @@ function messageShow($html_template, $message = 'No Msg') {
echo $html_template->saveHTML();
}
-
-// Verify all fields have been filled
-if (empty($_POST['user']) || empty($_POST['password']))
-{
- if (empty($_POST['user'])) {
- messageShow($prompt_template, 'Username field can\'t be empty.');
+if ($_SERVER['REQUEST_METHOD'] === 'GET') {
+ // If user is already authenticated, redirect him to the authorize page
+ messageShow($prompt_template, "");
+} elseif ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ // Verify all fields have been filled
+ if (empty($_POST['user']) || empty($_POST['password'])) {
+ if (empty($_POST['user'])) {
+ messageShow($prompt_template, 'Username field can\'t be empty.');
+ } else {
+ messageShow($prompt_template, 'Password field can\'t be empty.');
+ }
} else {
- messageShow($prompt_template, 'Password field can\'t be empty.');
- }
-}
-else
-{
- // Check received data length (to prevent code injection)
- if (strlen($_POST['user']) > 64)
- {
- messageShow($prompt_template, 'Username has incorrect format ... Please try again');
- }
- elseif (strlen($_POST['password']) > 64)
- {
- messageShow($prompt_template, 'Password has incorrect format ... Please try again');
- }
- else
- {
- // Remove every html tag and useless space on username (to prevent XSS)
- $user=strtolower(strip_tags(htmlspecialchars(trim($_POST['user']))));
- $password=$_POST['password'];
+ // Check received data length (to prevent code injection)
+ if (strlen($_POST['user']) > 64) {
+ messageShow($prompt_template, 'Username has incorrect format ... Please try again');
+ } elseif (strlen($_POST['password']) > 64) {
+ messageShow($prompt_template, 'Password has incorrect format ... Please try again');
+ } else {
+ // Remove every html tag and useless space on username (to prevent XSS)
+ $user = strtolower(strip_tags(htmlspecialchars(trim($_POST['user']))));
+ $password = $_POST['password'];
- // Open a LDAP connection
- $ldap = new LDAP($ldap_host,$ldap_port,$ldap_version,$ldap_start_tls);
+ // Open a LDAP connection
+ $ldap = new LDAP($ldap_host, $ldap_port, $ldap_version, $ldap_start_tls, $ldap_cert_path, $ldap_key_path, $ldap_secure);
- // Check user credential on LDAP
- try{
- $authenticated = $ldap->checkLogin($user,$password,$ldap_search_attribute,$ldap_filter,$ldap_base_dn,$ldap_bind_dn,$ldap_bind_pass);
- }
- catch (Exception $e)
- {
- $authenticated = false;
- }
+ // Check user credential on LDAP
+ try {
+ $authenticated = $ldap->checkLogin($user, $password, $ldap_search_attribute, $ldap_filter, $ldap_base_dn, $ldap_bind_dn, $ldap_bind_pass);
+ } catch (Exception $e) {
+ $authenticated = false;
+ }
- // If user is authenticated
- if ($authenticated)
- {
- $_SESSION['uid']=$user;
+ // If user is authenticated
+ if ($authenticated) {
+ $_SESSION['uid'] = $user;
- // If user came here with an autorize request, redirect him to the authorize page. Else prompt a simple message.
- if (isset($_SESSION['auth_page']))
- {
- $auth_page=$_SESSION['auth_page'];
- header('Location: ' . $auth_page);
- exit();
+ // If user came here with an autorize request, redirect him to the authorize page. Else prompt a simple message.
+ if (isset($_SESSION['auth_page'])) {
+ $auth_page = $_SESSION['auth_page'];
+ header('Location: ' . $auth_page);
+ exit();
+ } else {
+ messageShow($prompt_template, 'Congratulation you are authenticated !
However there is nothing to do here ...');
+ }
}
- else
- {
- messageShow($prompt_template, 'Congratulation you are authenticated !
However there is nothing to do here ...');
+ // check login on LDAP has failed. Login and password were invalid or LDAP is unreachable
+ else {
+ messageShow($prompt_template, 'Authentication failed ... Check your username and password.
If the error persists contact your administrator.
');
}
}
- // check login on LDAP has failed. Login and password were invalid or LDAP is unreachable
- else
- {
- messageShow($prompt_template, 'Authentication failed ... Check your username and password.
If the error persists contact your administrator.
');
- }
}
}
diff --git a/oauth/resource.php b/oauth/resource.php
index f2739b4..c25e34c 100755
--- a/oauth/resource.php
+++ b/oauth/resource.php
@@ -27,7 +27,7 @@
$assoc_id = intval($info_oauth["assoc_id"]);
// Open a LDAP connection
-$ldap = new LDAP($ldap_host, $ldap_port, $ldap_version, $ldap_start_tls);
+$ldap = new LDAP($ldap_host, $ldap_port, $ldap_version, $ldap_start_tls, $ldap_cert_path, $ldap_key_path, $ldap_secure);
// Try to get user data on the LDAP
try {