Skip to content

Commit 888e8a7

Browse files
committed
Deprecate SessionAuthenticator identify option
The `identify` option only verifies that the username exists in the database, it does not verify passwords as the documentation previously suggested. This makes it ineffective for the use case of detecting password changes or remotely invalidating sessions. Users should use `PrimaryKeySessionAuthenticator` instead if they need to fetch fresh user data from the database on each request. Also updated the Quick Start guide to clarify that SessionAuthenticator does not need an identifier - it uses session data directly as identity.
1 parent d5ac2be commit 888e8a7

File tree

5 files changed

+61
-48
lines changed

5 files changed

+61
-48
lines changed

docs/en/authenticators.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ Configuration options:
1818

1919
- **sessionKey**: The session key for the user data, default is
2020
``Auth``
21-
- **identify**: Set this key with a value of bool ``true`` to enable checking
22-
the session credentials against the identifiers. When ``true``, the configured
23-
:doc:`/identifiers` are used to identify the user using data
24-
stored in the session on each request. Default value is ``false``.
21+
- **identify**: Deprecated in 3.4.0. This option only verifies that the
22+
username exists in the database, it does not verify passwords as the
23+
documentation previously suggested. Use ``PrimaryKeySessionAuthenticator``
24+
instead if you need to fetch fresh user data from the database on each request.
2525
- **fields**: Allows you to map the ``username`` field to the unique
26-
identifier in your user storage. Defaults to ``username``. This option is
27-
used when the ``identify`` option is set to true.
26+
identifier in your user storage. Defaults to ``username``.
2827

2928
PrimaryKeySession
3029
=================

docs/en/index.rst

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ imports::
3232
use Authentication\AuthenticationServiceInterface;
3333
use Authentication\AuthenticationServiceProviderInterface;
3434
use Authentication\Identifier\AbstractIdentifier;
35-
use Authentication\Identifier\IdentifierInterface;
3635
use Authentication\Middleware\AuthenticationMiddleware;
3736
use Cake\Http\MiddlewareQueue;
3837
use Cake\Routing\Router;
@@ -94,23 +93,20 @@ define the ``AuthenticationService`` it wants to use. Add the following method t
9493
'queryParam' => 'redirect',
9594
]);
9695

97-
// Define identifiers
9896
$fields = [
9997
AbstractIdentifier::CREDENTIAL_USERNAME => 'email',
100-
AbstractIdentifier::CREDENTIAL_PASSWORD => 'password'
101-
];
102-
$passwordIdentifier = [
103-
'Authentication.Password' => [
104-
'fields' => $fields,
105-
],
98+
AbstractIdentifier::CREDENTIAL_PASSWORD => 'password',
10699
];
107100

108101
// Load the authenticators. Session should be first.
109-
$service->loadAuthenticator('Authentication.Session', [
110-
'identifier' => $passwordIdentifier,
111-
]);
102+
// Session just uses session data directly as identity, no identifier needed.
103+
$service->loadAuthenticator('Authentication.Session');
112104
$service->loadAuthenticator('Authentication.Form', [
113-
'identifier' => $passwordIdentifier,
105+
'identifier' => [
106+
'Authentication.Password' => [
107+
'fields' => $fields,
108+
],
109+
],
114110
'fields' => $fields,
115111
'loginUrl' => Router::url([
116112
'prefix' => false,
@@ -126,9 +122,9 @@ define the ``AuthenticationService`` it wants to use. Add the following method t
126122
First, we configure what to do with users when they are not authenticated.
127123
Next, we attach the ``Session`` and ``Form`` :doc:`/authenticators` which define the
128124
mechanisms that our application will use to authenticate users. ``Session`` enables us to identify
129-
users based on data in the session while ``Form`` enables us
130-
to handle a login form at the ``loginUrl``. Finally we attach an :doc:`identifier
131-
</identifiers>` to convert the credentials users will give us into an
125+
users based on data in the session - it uses the session data directly as identity without any
126+
database lookup. ``Form`` enables us to handle a login form at the ``loginUrl`` and uses an
127+
:doc:`identifier </identifiers>` to convert the credentials users will give us into an
132128
:doc:`identity </identity-object>` which represents our logged in user.
133129

134130
If one of the configured authenticators was able to validate the credentials,

src/Authenticator/SessionAuthenticator.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Cake\Http\Exception\UnauthorizedException;
2222
use Psr\Http\Message\ResponseInterface;
2323
use Psr\Http\Message\ServerRequestInterface;
24+
use function Cake\Core\deprecationWarning;
2425

2526
/**
2627
* Session Authenticator
@@ -31,9 +32,10 @@ class SessionAuthenticator extends AbstractAuthenticator implements PersistenceI
3132
* Default config for this object.
3233
* - `fields` The fields to use to verify a user by.
3334
* - `sessionKey` Session key.
34-
* - `identify` Whether to identify user data stored in a session. This is
35-
* useful if you want to remotely end sessions that have a different password stored,
36-
* or if your identification logic needs additional conditions before a user can login.
35+
* - `identify` Whether to identify user data stored in a session.
36+
* Deprecated: This option only verifies that the username exists in the database,
37+
* it does not verify passwords. Use `PrimaryKeySessionAuthenticator` instead if you
38+
* need to fetch fresh user data from the database on each request.
3739
*
3840
* @var array
3941
*/
@@ -65,6 +67,12 @@ public function authenticate(ServerRequestInterface $request): ResultInterface
6567
}
6668

6769
if ($this->getConfig('identify') === true) {
70+
deprecationWarning(
71+
'3.4.0',
72+
'The `identify` option is deprecated. ' .
73+
'This option only verifies that the username exists, not the password. ' .
74+
'Use `PrimaryKeySessionAuthenticator` instead to fetch fresh user data on each request.',
75+
);
6876
$credentials = [];
6977
foreach ($this->getConfig('fields') as $key => $field) {
7078
$credentials[$key] = $user[$field];

tests/TestCase/AuthenticationServiceTest.php

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ public function testAuthenticateWithChallengeDisabled()
172172
* Integration test for session auth + identify always getting a fresh user record.
173173
*
174174
* @return void
175+
* @deprecated The `identify` option is deprecated.
175176
*/
176177
public function testAuthenticationWithSessionIdentify()
177178
{
@@ -197,25 +198,28 @@ public function testAuthenticationWithSessionIdentify()
197198
],
198199
]);
199200
};
200-
$service = $factory();
201-
$result = $service->authenticate($request);
202-
$this->assertTrue($result->isValid());
203-
204-
$dateValue = new DateTime('2022-01-01 10:11:12');
205-
$identity = $result->getData();
206-
$this->assertEquals($identity->username, $user->username);
207-
$this->assertNotEquals($identity->created, $dateValue);
208-
209-
// Update the user so that we can ensure session is reading from the db.
210-
$user->created = $dateValue;
211-
$users->saveOrFail($user);
212201

213-
$service = $factory();
214-
$result = $service->authenticate($request);
215-
$this->assertTrue($result->isValid());
216-
$identity = $result->getData();
217-
$this->assertEquals($identity->username, $user->username);
218-
$this->assertEquals($identity->created, $dateValue);
202+
$this->deprecated(function () use ($factory, $request, $users, $user) {
203+
$service = $factory();
204+
$result = $service->authenticate($request);
205+
$this->assertTrue($result->isValid());
206+
207+
$dateValue = new DateTime('2022-01-01 10:11:12');
208+
$identity = $result->getData();
209+
$this->assertEquals($identity->username, $user->username);
210+
$this->assertNotEquals($identity->created, $dateValue);
211+
212+
// Update the user so that we can ensure session is reading from the db.
213+
$user->created = $dateValue;
214+
$users->saveOrFail($user);
215+
216+
$service = $factory();
217+
$result = $service->authenticate($request);
218+
$this->assertTrue($result->isValid());
219+
$identity = $result->getData();
220+
$this->assertEquals($identity->username, $user->username);
221+
$this->assertEquals($identity->created, $dateValue);
222+
});
219223
}
220224

221225
/**

tests/TestCase/Authenticator/SessionAuthenticatorTest.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ public function testAuthenticateFailure()
203203
* Test successful session data verification by database lookup
204204
*
205205
* @return void
206+
* @deprecated The `identify` option is deprecated.
206207
*/
207208
public function testVerifyByDatabaseSuccess()
208209
{
@@ -221,16 +222,19 @@ public function testVerifyByDatabaseSuccess()
221222
$authenticator = new SessionAuthenticator($this->identifiers, [
222223
'identify' => true,
223224
]);
224-
$result = $authenticator->authenticate($request);
225+
$this->deprecated(function () use ($authenticator, $request) {
226+
$result = $authenticator->authenticate($request);
225227

226-
$this->assertInstanceOf(Result::class, $result);
227-
$this->assertSame(Result::SUCCESS, $result->getStatus());
228+
$this->assertInstanceOf(Result::class, $result);
229+
$this->assertSame(Result::SUCCESS, $result->getStatus());
230+
});
228231
}
229232

230233
/**
231234
* Test session data verification by database lookup failure
232235
*
233236
* @return void
237+
* @deprecated The `identify` option is deprecated.
234238
*/
235239
public function testVerifyByDatabaseFailure()
236240
{
@@ -249,10 +253,12 @@ public function testVerifyByDatabaseFailure()
249253
$authenticator = new SessionAuthenticator($this->identifiers, [
250254
'identify' => true,
251255
]);
252-
$result = $authenticator->authenticate($request);
256+
$this->deprecated(function () use ($authenticator, $request) {
257+
$result = $authenticator->authenticate($request);
253258

254-
$this->assertInstanceOf(Result::class, $result);
255-
$this->assertSame(Result::FAILURE_CREDENTIALS_INVALID, $result->getStatus());
259+
$this->assertInstanceOf(Result::class, $result);
260+
$this->assertSame(Result::FAILURE_CREDENTIALS_INVALID, $result->getStatus());
261+
});
256262
}
257263

258264
/**

0 commit comments

Comments
 (0)