2020-11-27 12:20:10 +01:00
|
|
|
commit c7a763a0fae7e1933f280b29bd2a1911b01f7170
|
|
|
|
Author: Simon Mellerin <simon.mellerin@makina-corpus.com>
|
|
|
|
Date: Fri Nov 27 12:19:02 2020 +0100
|
|
|
|
|
2020-11-26 18:47:34 +01:00
|
|
|
diff --git a/config/packages/security.yaml b/config/packages/security.yaml
|
2020-11-27 12:20:10 +01:00
|
|
|
index 15ef608..8516775 100644
|
2020-11-26 18:47:34 +01:00
|
|
|
--- a/config/packages/security.yaml
|
|
|
|
+++ b/config/packages/security.yaml
|
2020-11-27 12:20:10 +01:00
|
|
|
@@ -10,6 +10,8 @@ security:
|
|
|
|
entity:
|
|
|
|
class: App\Entity\User
|
|
|
|
property: username
|
|
|
|
+ user_provider_yunohost:
|
|
|
|
+ id: yunohost.provider.ldap
|
|
|
|
firewalls:
|
|
|
|
dev:
|
|
|
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
|
|
|
@@ -20,6 +22,10 @@ security:
|
2020-11-26 18:47:34 +01:00
|
|
|
provider: app_user_provider
|
|
|
|
authenticators:
|
|
|
|
- App\Security\LoginFormAuthenticator
|
|
|
|
+ http_basic_ldap:
|
2020-11-27 12:20:10 +01:00
|
|
|
+ provider: user_provider_yunohost
|
2020-11-26 18:47:34 +01:00
|
|
|
+ service: yunohost.ldap
|
2020-11-27 12:20:10 +01:00
|
|
|
+ dn_string: "uid={username},ou=users,dc=yunohost,dc=org"
|
2020-11-26 18:47:34 +01:00
|
|
|
logout:
|
2020-11-26 19:15:40 +01:00
|
|
|
path: security.logout
|
|
|
|
target: security.login
|
2020-11-26 18:47:34 +01:00
|
|
|
diff --git a/config/services.yaml b/config/services.yaml
|
2020-11-27 12:20:10 +01:00
|
|
|
index 533c244..9362ef5 100644
|
2020-11-26 18:47:34 +01:00
|
|
|
--- a/config/services.yaml
|
|
|
|
+++ b/config/services.yaml
|
2020-11-27 12:20:10 +01:00
|
|
|
@@ -70,3 +70,16 @@ services:
|
2020-11-26 18:47:34 +01:00
|
|
|
|
2020-11-26 19:15:40 +01:00
|
|
|
Aeneria\EnedisDataConnectApi\Service\DataConnectServiceInterface:
|
|
|
|
alias: Aeneria\EnedisDataConnectApi\Service\DataConnectService
|
2020-11-26 18:47:34 +01:00
|
|
|
+
|
2020-11-27 12:20:10 +01:00
|
|
|
+ yunohost.provider.ldap:
|
|
|
|
+ class: App\Security\YunohostLdapUserProvider
|
|
|
|
+ arguments: ["@yunohost.ldap", "ou=users,dc=yunohost,dc=org"]
|
|
|
|
+
|
2020-11-26 18:47:34 +01:00
|
|
|
+ yunohost.ldap:
|
|
|
|
+ class: Symfony\Component\Ldap\Ldap
|
|
|
|
+ arguments: ['@yunohost.ldap.adapter']
|
|
|
|
+
|
|
|
|
+ yunohost.ldap.adapter:
|
|
|
|
+ class: Symfony\Component\Ldap\Adapter\ExtLdap\Adapter
|
|
|
|
+ arguments:
|
|
|
|
+ - host: "localhost"
|
2020-11-27 12:20:10 +01:00
|
|
|
diff --git a/src/Security/YunohostLdapUserProvider.php b/src/Security/YunohostLdapUserProvider.php
|
|
|
|
new file mode 100644
|
|
|
|
index 0000000..39ba1e8
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/src/Security/YunohostLdapUserProvider.php
|
|
|
|
@@ -0,0 +1,123 @@
|
|
|
|
+<?php
|
|
|
|
+
|
|
|
|
+namespace App\Security;
|
|
|
|
+
|
|
|
|
+use App\Entity\User;
|
|
|
|
+use App\Repository\UserRepository;
|
|
|
|
+use Symfony\Component\Ldap\Entry;
|
|
|
|
+use Symfony\Component\Ldap\Exception\ConnectionException;
|
|
|
|
+use Symfony\Component\Ldap\LdapInterface;
|
|
|
|
+use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
|
|
|
|
+use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
|
|
|
+use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
|
|
|
+use Symfony\Component\Security\Core\User\UserInterface;
|
|
|
|
+use Symfony\Component\Security\Core\User\UserProviderInterface;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Adapted from LdapUserProvider.
|
|
|
|
+ *
|
|
|
|
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
|
|
|
|
+ * @author Charles Sarrazin <charles@sarraz.in>
|
|
|
|
+ * @author Robin Chalas <robin.chalas@gmail.com>
|
|
|
|
+ */
|
|
|
|
+class YunohostLdapUserProvider implements UserProviderInterface
|
|
|
|
+{
|
|
|
|
+ /** @var LdapInterface */
|
|
|
|
+ private $ldap;
|
|
|
|
+ /** @var string */
|
|
|
|
+ private $baseDn;
|
|
|
|
+ /** @var string */
|
|
|
|
+ private $searchDn;
|
|
|
|
+ /** @var string */
|
|
|
|
+ private $searchPassword;
|
|
|
|
+ /** @var string[] */
|
|
|
|
+ private $defaultRoles;
|
|
|
|
+ /** @var string */
|
|
|
|
+ private $uidKey;
|
|
|
|
+ /** @var string */
|
|
|
|
+ private $defaultSearch;
|
|
|
|
+ /** @var UserRepository */
|
|
|
|
+ private $userRepository;
|
|
|
|
+
|
|
|
|
+ public function __construct(
|
|
|
|
+ LdapInterface $ldap,
|
|
|
|
+ string $baseDn,
|
|
|
|
+ string $searchDn = null,
|
|
|
|
+ string $searchPassword = null,
|
|
|
|
+ array $defaultRoles = [],
|
|
|
|
+ UserRepository $userRepository
|
|
|
|
+ ) {
|
|
|
|
+ $this->ldap = $ldap;
|
|
|
|
+ $this->baseDn = $baseDn;
|
|
|
|
+ $this->searchDn = $searchDn;
|
|
|
|
+ $this->searchPassword = $searchPassword;
|
|
|
|
+ $this->defaultRoles = $defaultRoles;
|
|
|
|
+ $this->defaultSearch = '(uid={username})';
|
|
|
|
+
|
|
|
|
+ $this->userRepository = $userRepository;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * {@inheritdoc}
|
|
|
|
+ */
|
|
|
|
+ public function loadUserByUsername(string $username)
|
|
|
|
+ {
|
|
|
|
+ try {
|
|
|
|
+ $this->ldap->bind($this->searchDn, $this->searchPassword);
|
|
|
|
+ $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
|
|
|
|
+ $query = str_replace('{username}', $username, $this->defaultSearch);
|
|
|
|
+ $search = $this->ldap->query($this->baseDn, $query);
|
|
|
|
+ } catch (ConnectionException $e) {
|
|
|
|
+ throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $entries = $search->execute();
|
|
|
|
+ $count = \count($entries);
|
|
|
|
+
|
|
|
|
+ if (!$count) {
|
|
|
|
+ die($username . 'ldap pas trouvé');
|
|
|
|
+ throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ($count > 1) {
|
|
|
|
+ throw new UsernameNotFoundException('More than one user found.');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $entry = $entries[0];
|
|
|
|
+
|
|
|
|
+ $username = $this->getAttributeValue($entry, 'mail');
|
|
|
|
+
|
|
|
|
+ return $this->userRepository->findOneBy(['username' => $username]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * {@inheritdoc}
|
|
|
|
+ */
|
|
|
|
+ public function refreshUser(UserInterface $user)
|
|
|
|
+ {
|
|
|
|
+ if (!$user instanceof User) {
|
|
|
|
+ throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user)));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return $this->userRepository->findOneBy(['username' => $user->getUsername()]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * {@inheritdoc}
|
|
|
|
+ */
|
|
|
|
+ public function supportsClass(string $class)
|
|
|
|
+ {
|
|
|
|
+ return User::class === $class;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private function getAttributeValue(Entry $entry, string $attribute)
|
|
|
|
+ {
|
|
|
|
+ if (!$entry->hasAttribute($attribute)) {
|
|
|
|
+ throw new InvalidArgumentException(sprintf('Missing attribute "%s" for user "%s".', $attribute, $entry->getDn()));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $values = $entry->getAttribute($attribute);
|
|
|
|
+
|
|
|
|
+ return $values[0];
|
|
|
|
+ }
|
|
|
|
+}
|