Issues (23)

src/Adapter/Basic/Ldap.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Micro
7
 *
8
 * @copyright   Copryright (c) 2015-2018 gyselroth GmbH (https://gyselroth.com)
9
 * @license     MIT https://opensource.org/licenses/MIT
10
 */
11
12
namespace Micro\Auth\Adapter\Basic;
13
14
use Micro\Auth\Adapter\AdapterInterface;
15
use Micro\Auth\Exception;
16
use Micro\Auth\Ldap as LdapServer;
17
use Psr\Log\LoggerInterface;
18
19
class Ldap extends AbstractBasic
20
{
21
    /**
22
     * Ldap.
23
     *
24
     * @var LdapServer
25
     */
26
    protected $ldap;
27
28
    /**
29
     * LDAP DN.
30
     *
31
     * @var string
32
     */
33
    protected $ldap_dn;
34
35
    /**
36
     * Account filter.
37
     *
38
     * @var string
39
     */
40
    protected $account_filter = '(uid=%s)';
41
42
    /**
43
     * Logger.
44
     *
45
     * @var LoggerInterface
46
     */
47
    protected $logger;
48
49
    /**
50
     * Init.
51
     *
52
     * @param LdapServer      $ldap
53
     * @param LoggerInterface $logger
54
     * @param iterable        $config
55
     */
56
    public function __construct(LdapServer $ldap, LoggerInterface $logger, ?Iterable $config = null)
57
    {
58
        parent::__construct($logger);
59
        $this->ldap = $ldap;
60
        $this->setOptions($config);
61
    }
62
63
    /**
64
     * Setup.
65
     */
66
    public function setup(): bool
67
    {
68
        $this->ldap->connect();
69
70
        return true;
71
    }
72
73
    /**
74
     * Set options.
75
     *
76
     * @param iterable $config
77
     *
78
     * @return AdapterInterface
79
     */
80
    public function setOptions(? Iterable $config = null): AdapterInterface
81
    {
82
        if (null === $config) {
83
            return $this;
84
        }
85
86
        foreach ($config as $option => $value) {
87
            switch ($option) {
88
                case 'account_filter':
89
                    $this->account_filter = $value;
90
                    unset($config[$option]);
91
92
                break;
93
            }
94
        }
95
96
        parent::setOptions($config);
97
98
        return $this;
99
    }
100
101
    /**
102
     * LDAP Auth.
103
     *
104
     * @param string $username
105
     * @param string $password
106
     *
107
     * @return bool
108
     */
109
    public function plainAuth(string $username, string $password): bool
110
    {
111
        $resource = $this->ldap->getResource();
112
113
        $esc_username = ldap_escape($username);
114
        $filter = htmlspecialchars_decode(sprintf($this->account_filter, $esc_username));
115
        $result = ldap_search($resource, $this->ldap->getBase(), $filter, ['dn', $this->identity_attribute]);
116
        $entries = ldap_get_entries($resource, $result);
117
118
        if (0 === $entries['count']) {
119
            $this->logger->warning("user not found with ldap filter [{$filter}]", [
120
                'category' => get_class($this),
121
            ]);
122
123
            return false;
124
        }
125
        if ($entries['count'] > 1) {
126
            $this->logger->warning("more than one user found with ldap filter [{$filter}]", [
127
                'category' => get_class($this),
128
            ]);
129
130
            return false;
131
        }
132
133
        $dn = $entries[0]['dn'];
134
        $this->logger->info("found ldap user [{$dn}] with filter [{$filter}]", [
135
            'category' => get_class($this),
136
        ]);
137
138
        $result = ldap_bind($resource, $dn, $password);
139
        $this->logger->info("bind ldap user [{$dn}]", [
140
            'category' => get_class($this),
141
            'result' => $result,
142
        ]);
143
144
        if (false === $result) {
145
            return false;
146
        }
147
148
        if (!isset($entries[0][$this->identity_attribute])) {
149
            throw new Exception\IdentityAttributeNotFound('identity attribute not found');
150
        }
151
152
        $this->identifier = $entries[0][$this->identity_attribute][0];
153
        $this->ldap_dn = $dn;
154
155
        return true;
156
    }
157
158
    /**
159
     * Get attributes.
160
     *
161
     * @return array
162
     */
163
    public function getAttributes(): array
164
    {
165
        $search = array_column($this->map, 'attr');
0 ignored issues
show
$this->map of type iterable is incompatible with the type array expected by parameter $input of array_column(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

165
        $search = array_column(/** @scrutinizer ignore-type */ $this->map, 'attr');
Loading history...
166
        $result = ldap_read($this->ldap->getResource(), $this->ldap_dn, '(objectClass=*)', $search);
167
        $entries = ldap_get_entries($this->ldap->getResource(), $result);
168
        $attributes = $entries[0];
169
170
        $this->logger->info("get ldap user [{$this->ldap_dn}] attributes", [
171
            'category' => get_class($this),
172
            'params' => $attributes,
173
        ]);
174
175
        return $attributes;
176
    }
177
}
178