Completed
Push — master ( d2c9b2...2cde9b )
by
unknown
08:05 queued 04:31
created

BaseAuthenticate::getUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright 2016 - 2017, Cake Development Corporation (http://cakedc.com)
4
 *
5
 * Licensed under The MIT License
6
 * Redistributions of files must retain the above copyright notice.
7
 *
8
 * @copyright Copyright 2016 - 2017, Cake Development Corporation (http://cakedc.com)
9
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
10
 */
11
12
/**
13
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
14
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
15
 *
16
 * Licensed under The MIT License
17
 * For full copyright and license information, please see the LICENSE.txt
18
 * Redistributions of files must retain the above copyright notice.
19
 *
20
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
21
 * @link          http://cakephp.org CakePHP(tm) Project
22
 * @since         0.10.0
23
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
24
 */
25
26
namespace CakeDC\Api\Service\Auth\Authenticate;
27
28
use CakeDC\Api\Service\Action\Action;
29
30
use Cake\Auth\PasswordHasherFactory;
31
use Cake\Core\InstanceConfigTrait;
32
use Cake\Event\EventListenerInterface;
33
use Cake\Http\Response;
34
use Cake\Http\ServerRequest;
35
36
use Cake\ORM\TableRegistry;
37
38
/**
39
 * Base Authentication class with common methods and properties.
40
 *
41
 */
42
abstract class BaseAuthenticate implements EventListenerInterface
43
{
44
45
    use InstanceConfigTrait;
46
47
    /**
48
     * Default config for this object.
49
     *
50
     * - `fields` The fields to use to identify a user by.
51
     * - `userModel` The alias for users table, defaults to Users.
52
     * - `finder` The finder method to use to fetch user record. Defaults to 'all'.
53
     *   You can set finder name as string or an array where key is finder name and value
54
     *   is an array passed to `Table::find()` options.
55
     *   E.g. ['finderName' => ['some_finder_option' => 'some_value']]
56
     * - `passwordHasher` Password hasher class. Can be a string specifying class name
57
     *    or an array containing `className` key, any other keys will be passed as
58
     *    config to the class. Defaults to 'Default'.
59
     * - Options `scope` and `contain` have been deprecated since 3.1. Use custom
60
     *   finder instead to modify the query to fetch user record.
61
     *
62
     * @var array
63
     */
64
    protected $_defaultConfig = [
65
        'fields' => [
66
            'username' => 'username',
67
            'password' => 'password'
68
        ],
69
        'userModel' => 'Users',
70
        'scope' => [],
71
        'finder' => 'all',
72
        'contain' => null,
73
        'passwordHasher' => 'Default'
74
    ];
75
76
    /**
77
     * An Action
78
     *
79
     * @var \CakeDC\Api\Service\Action\Action
80
     */
81
    protected $_action;
82
83
    /**
84
     * Password hasher instance.
85
     *
86
     * @var \Cake\Auth\AbstractPasswordHasher
87
     */
88
    protected $_passwordHasher;
89
90
    /**
91
     * Whether or not the user authenticated by this class
92
     * requires their password to be rehashed with another algorithm.
93
     *
94
     * @var bool
95
     */
96
    protected $_needsPasswordRehash = false;
97
98
    /**
99
     * Constructor
100
     *
101
     * @param \CakeDC\Api\Service\Action\Action $action An Action instance.
102
     * @param array $config Array of config to use.
103
     */
104 66
    public function __construct(Action $action, array $config = [])
105
    {
106 66
        $this->_action = $action;
107 66
        $this->setConfig($config);
108 66
    }
109
110
    /**
111
     * Find a user record using the username and password provided.
112
     *
113
     * Input passwords will be hashed even when a user doesn't exist. This
114
     * helps mitigate timing attacks that are attempting to find valid usernames.
115
     *
116
     * @param string $username The username/identifier.
117
     * @param string|null $password The password, if not provided password checking is skipped
118
     *   and result of find is returned.
119
     * @return bool|array Either false on failure, or an array of user data.
120
     */
121 4
    protected function _findUser($username, $password = null)
122
    {
123 4
        $result = $this->_query($username)->first();
124
125 4
        if (empty($result)) {
126 1
            return false;
127
        }
128
129 4
        if ($password !== null) {
130 4
            $hasher = $this->passwordHasher();
131 4
            $hashedPassword = $result->get($this->_config['fields']['password']);
132 4
            if (!$hasher->check($password, $hashedPassword)) {
133 1
                return false;
134
            }
135
136 3
            $this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
137 3
            $result->unsetProperty($this->_config['fields']['password']);
138 3
        }
139
140 3
        return $result->toArray();
141
    }
142
143
    /**
144
     * Get query object for fetching user from database.
145
     *
146
     * @param string $username The username/identifier.
147
     * @return \Cake\ORM\Query
148
     */
149 57
    protected function _query($username)
150
    {
151 57
        $config = $this->_config;
152 57
        $table = TableRegistry::get($config['userModel']);
153
154
        $options = [
155
            'conditions' => [
156 57
                $table->aliasField($config['fields']['username']) => $username
157 57
            ]
158 57
        ];
159
160 57
        if (!empty($config['scope'])) {
161
            $options['conditions'] = array_merge($options['conditions'], $config['scope']);
162
        }
163 57
        if (!empty($config['contain'])) {
164
            $options['contain'] = $config['contain'];
165
        }
166
167 57
        $finder = $config['finder'];
168 57
        if (is_array($finder)) {
169
            $options += current($finder);
170
            $finder = key($finder);
171
        }
172
173 57
        $query = $table->find($finder, $options);
174
175 57
        return $query;
176
    }
177
178
    /**
179
     * Return password hasher object
180
     *
181
     * @return \Cake\Auth\AbstractPasswordHasher Password hasher instance
182
     * @throws \RuntimeException If password hasher class not found or
183
     *   it does not extend AbstractPasswordHasher
184
     */
185 4
    public function passwordHasher()
186
    {
187 4
        if ($this->_passwordHasher) {
188
            return $this->_passwordHasher;
189
        }
190
191 4
        $passwordHasher = $this->_config['passwordHasher'];
192
193 4
        return $this->_passwordHasher = PasswordHasherFactory::build($passwordHasher);
194
    }
195
196
    /**
197
     * Returns whether or not the password stored in the repository for the logged in user
198
     * requires to be rehashed with another algorithm
199
     *
200
     * @return bool
201
     */
202
    public function needsPasswordRehash()
203
    {
204
        return $this->_needsPasswordRehash;
205
    }
206
207
    /**
208
     * Authenticate a user based on the request information.
209
     *
210
     * @param \Cake\Http\ServerRequest $request Request to get authentication information from.
211
     * @param \Cake\Http\Response $response A response object that can have headers added.
212
     * @return mixed Either false on failure, or an array of user data on success.
213
     */
214
    abstract public function authenticate(ServerRequest $request, Response $response);
215
216
    /**
217
     * Get a user based on information in the request. Primarily used by stateless authentication
218
     * systems like basic and digest auth.
219
     *
220
     * @param \Cake\Http\ServerRequest $request Request object.
221
     * @return mixed Either false or an array of user information
222
     */
223
    public function getUser(ServerRequest $request)
224
    {
225
        return false;
226
    }
227
228
    /**
229
     * Handle unauthenticated access attempt. In implementation valid return values
230
     * can be:
231
     *
232
     * - Null - No action taken, AuthComponent should return appropriate response.
233
     * - Cake\Network\Response - A response object, which will cause AuthComponent to
234
     *   simply return that response.
235
     *
236
     * @param ServerRequest $request A request object.
237
     * @param \Cake\Http\Response $response A response object.
238
     * @return void
239
     */
240
    public function unauthenticated(ServerRequest $request, Response $response)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $response is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
241
    {
242
    }
243
244
    /**
245
     * Returns a list of all events that this authenticate class will listen to.
246
     *
247
     * An authenticate class can listen to following events fired by AuthComponent:
248
     *
249
     * - `Auth.afterIdentify` - Fired after a user has been identified using one of
250
     *   configured authenticate class. The callback function should have signature
251
     *   like `afterIdentify(Event $event, array $user)` when `$user` is the
252
     *   identified user record.
253
     *
254
     * - `Auth.logout` - Fired when AuthComponent::logout() is called. The callback
255
     *   function should have signature like `logout(Event $event, array $user)`
256
     *   where `$user` is the user about to be logged out.
257
     *
258
     * @return array List of events this class listens to. Defaults to `[]`.
259
     */
260 52
    public function implementedEvents()
261
    {
262 52
        return [];
263
    }
264
}
265