Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
13478ac
Bump actions/stale from 6 to 7
dependabot[bot] Dec 26, 2022
2d68b10
Added link to Users table structure
yosus Jan 3, 2023
95ef4dd
Merge pull request #601 from yosus/patch-1
markstory Jan 7, 2023
c326c90
Add missing links to sidebar and further reading
cleptric Feb 4, 2023
de2c7ad
Merge pull request #603 from cleptric/2.x
markstory Feb 5, 2023
76ef0d0
fix impersonation version info in docs
LordSimal Feb 5, 2023
75830c5
Merge pull request #604 from cakephp/2.x-docs
saeideng Feb 5, 2023
fd212e4
Merge pull request #599 from cakephp/dependabot/github_actions/action…
saeideng Feb 5, 2023
cdbef94
Update index.rst
luizcmarin Mar 3, 2023
10355d9
Merge pull request #605 from luizcmarin/patch-1
ADmad Mar 3, 2023
e23f6b6
add example on how to mimic Auth->deny
LordSimal Mar 13, 2023
422a55b
Merge pull request #607 from cakephp/2.x-deny-doc
markstory Mar 14, 2023
efb0f06
Store only the original data in the impersonation session
markstory Mar 15, 2023
6fc5c45
Address complaints from psalm
markstory Mar 15, 2023
43d33a0
Fix interface construction
markstory Mar 15, 2023
4b5cc23
Increase coverage.
markstory Mar 17, 2023
643e17b
Merge pull request #608 from cakephp/fix-606
markstory Mar 17, 2023
9aebb2d
fix tests
LordSimal Apr 25, 2023
c8fc3e6
Merge pull request #611 from cakephp/2.x-fix-tests
LordSimal Apr 25, 2023
fc84fac
Bump actions/stale from 7 to 8
dependabot[bot] Apr 25, 2023
73cab9a
Merge pull request #609 from cakephp/dependabot/github_actions/action…
LordSimal Apr 25, 2023
9713159
Merge branch '2.x' into 3.x-merge
LordSimal Apr 29, 2023
1a00fd8
fix tests
LordSimal Apr 29, 2023
75935c9
fix CS
LordSimal Apr 29, 2023
5c59aae
Update finder methods and find() calls.
ADmad Apr 30, 2023
ac2f649
Add missing type
ADmad Apr 30, 2023
b0db63d
remove deprecated middleware config
LordSimal Apr 30, 2023
254edbe
remove deprecated CookieAuthenticator config key fallbacks
LordSimal Apr 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/stale@v6
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open for 120 days with no activity. Remove the `stale` label or comment or this will be closed in 15 days'
Expand Down
1 change: 1 addition & 0 deletions docs/en/contents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Contents
/middleware
/authentication-component
/testing
/impersonation
/url-checkers
/view-helper
/migration-from-the-authcomponent
4 changes: 2 additions & 2 deletions docs/en/impersonation.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
User Impersonation
##################

.. versionadded:: 3.0.0
.. versionadded:: 2.10.0
User impersonation was added.

After deploying your application, you may occasionally need to
Expand All @@ -15,7 +15,7 @@ To impersonate another user you can use the ``impersonate()`` method on the
``AuthenticationComponent``. To impersonate a user you first need to load that
user from your application's database::

// In a controller
// In a controller
public function impersonate()
{
$this->request->allowMethod(['POST']);
Expand Down
5 changes: 3 additions & 2 deletions docs/en/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Project's ROOT directory (where the **composer.json** file is located)

.. code-block:: bash

php composer.phar require "cakephp/authentication:^2.0"
php composer.phar require cakephp/authentication

Version 2 of the Authentication Plugin is compatible with CakePHP 4.

Expand Down Expand Up @@ -149,7 +149,7 @@ Building a Login Action
=======================

Once you have the middleware applied to your application you'll need a way for
users to login. First generate a Users model and controller with bake:
users to login. Please ensure your database has been created with the Users table structure used in :doc:`tutorial </tutorials-and-examples/cms/database>`. First generate a Users model and controller with bake:

.. code-block:: shell

Expand Down Expand Up @@ -244,6 +244,7 @@ Further Reading
* :doc:`/identifiers`
* :doc:`/password-hashers`
* :doc:`/identity-object`
* :doc:`/middleware`
* :doc:`/authentication-component`
* :doc:`/impersonation`
* :doc:`/url-checkers`
Expand Down
7 changes: 7 additions & 0 deletions docs/en/migration-from-the-authcomponent.rst
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ present::
Each call to ``allowUnauthenticated()`` will overwrite the current
action list.

To mimic ``$this->Auth->deny(['register']);`` you can do::

$action = $this->getRequest()->getParam('action');
if ($action !== 'register') {
$this->Authentication->allowUnauthenticated([$action]);
}

Migrating Unauthenticated Redirects
===================================

Expand Down
15 changes: 1 addition & 14 deletions src/Authenticator/CookieAuthenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,23 +235,10 @@ protected function _createCookie(mixed $value): CookieInterface
$name = $options['name'];
unset($options['name']);

if (array_key_exists('expire', $options)) {
deprecationWarning('2.x', 'Config key `expire` is deprecated, use `expires` instead.');
$options['expires'] = $options['expire'];
unset($options['expire']);
}
if (array_key_exists('httpOnly', $options)) {
deprecationWarning('2.x', 'Config key `httpOnly` is deprecated, use `httponly` instead.');
$options['httponly'] = $options['httpOnly'];
unset($options['httpOnly']);
}

$cookie = Cookie::create(
return Cookie::create(
$name,
$value,
$options
);

return $cookie;
}
}
7 changes: 6 additions & 1 deletion src/Controller/Component/AuthenticationComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace Authentication\Controller\Component;

use ArrayAccess;
use ArrayObject;
use Authentication\AuthenticationServiceInterface;
use Authentication\Authenticator\ImpersonationInterface;
use Authentication\Authenticator\PersistenceInterface;
Expand Down Expand Up @@ -375,12 +376,16 @@ public function impersonate(ArrayAccess $impersonated)
if (!$identity) {
throw new UnauthenticatedException('You must be logged in before impersonating a user.');
}
$impersonator = $identity->getOriginalData();
if (!($impersonator instanceof ArrayAccess)) {
$impersonator = new ArrayObject($impersonator);
}
$controller = $this->getController();
/** @psalm-var array{request: \Cake\Http\ServerRequest, response: \Cake\Http\Response} $result */
$result = $service->impersonate(
$controller->getRequest(),
$controller->getResponse(),
$identity,
$impersonator,
$impersonated
);

Expand Down
4 changes: 2 additions & 2 deletions src/Identifier/Resolver/OrmResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function __construct(array $config = [])
/**
* @inheritDoc
*/
public function find(array $conditions, $type = self::TYPE_AND): ArrayAccess|array|null
public function find(array $conditions, string $type = self::TYPE_AND): ArrayAccess|array|null
{
$table = $this->getTableLocator()->get($this->_config['userModel']);

Expand All @@ -63,7 +63,7 @@ public function find(array $conditions, $type = self::TYPE_AND): ArrayAccess|arr
if (is_string($options)) {
$query->find($options);
} else {
$query->find($finder, $options);
$query->find($finder, ...$options);
}
}

Expand Down
45 changes: 1 addition & 44 deletions src/Middleware/AuthenticationMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,24 @@
*/
namespace Authentication\Middleware;

use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Authenticator\AuthenticationRequiredException;
use Authentication\Authenticator\StatelessInterface;
use Authentication\Authenticator\UnauthenticatedException;
use Cake\Core\InstanceConfigTrait;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\Response\RedirectResponse;
use Laminas\Diactoros\Stream;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;

/**
* Authentication Middleware
*/
class AuthenticationMiddleware implements MiddlewareInterface
{
use InstanceConfigTrait;

/**
* Configuration options
*
* The following keys are deprecated and should instead be set on the AuthenticationService
*
* - `identityAttribute` - The request attribute to store the identity in.
* - `unauthenticatedRedirect` - The URL to redirect unauthenticated errors to. See
* AuthenticationComponent::allowUnauthenticated()
* - `queryParam` - The name of the query string parameter containing the previously blocked
* URL in case of unauthenticated redirect, or null to disable appending the denied URL.
*
* @var array
*/
protected array $_defaultConfig = [];

/**
* Authentication service or application instance.
*
Expand All @@ -65,15 +45,12 @@ class AuthenticationMiddleware implements MiddlewareInterface
* Constructor
*
* @param \Authentication\AuthenticationServiceInterface|\Authentication\AuthenticationServiceProviderInterface $subject Authentication service or application instance.
* @param array $config Array of configuration settings.
* @throws \InvalidArgumentException When invalid subject has been passed.
*/
public function __construct(
AuthenticationServiceInterface|AuthenticationServiceProviderInterface $subject,
array $config = []
AuthenticationServiceInterface|AuthenticationServiceProviderInterface $subject
) {
$this->subject = $subject;
$this->setConfig($config);
}

/**
Expand Down Expand Up @@ -144,26 +121,6 @@ protected function getAuthenticationService(ServerRequestInterface $request): Au
$subject = $subject->getAuthenticationService($request);
}

$forwardKeys = ['identityAttribute', 'unauthenticatedRedirect', 'queryParam'];
foreach ($forwardKeys as $key) {
$value = $this->getConfig($key);
if ($value) {
deprecationWarning(
'2.x',
"The `{$key}` configuration key on AuthenticationMiddleware is deprecated. " .
"Instead set the `{$key}` on your AuthenticationService instance."
);
if ($subject instanceof AuthenticationService) {
$subject->setConfig($key, $value);
} else {
throw new RuntimeException(
'Could not forward configuration to authentication service as ' .
'it does not implement `getConfig()`'
);
}
}
}

return $subject;
}
}
2 changes: 1 addition & 1 deletion src/UrlChecker/DefaultUrlChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function check(ServerRequestInterface $request, $loginUrls, array $option
*/
protected function _mergeDefaultOptions(array $options): array
{
return $options += $this->_defaultOptions;
return $options + $this->_defaultOptions;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion tests/TestCase/Authenticator/CookieAuthenticatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ public function testClearIdentity()
$this->assertInstanceOf(RequestInterface::class, $result['request']);
$this->assertInstanceOf(ResponseInterface::class, $result['response']);

$this->assertSame('CookieAuth=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/', $result['response']->getHeaderLine('Set-Cookie'));
$cookieHeader = $result['response']->getHeaderLine('Set-Cookie');
$this->assertStringContainsString('CookieAuth=; expires=Thu, 01-Jan-1970 00:00:01', $cookieHeader);
$this->assertStringContainsString('; path=/', $cookieHeader);
}
}
3 changes: 2 additions & 1 deletion tests/TestCase/Authenticator/HttpDigestAuthenticatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;
use PHPUnit\Framework\Constraint\RegularExpression;
use function Cake\Core\env;

/**
* Test case for HttpDigestAuthentication
Expand Down Expand Up @@ -300,7 +301,7 @@ public function testUnauthorizedFailReChallenge()
{
$this->auth->setConfig('scope.username', 'nate');

$nonce = $this->generateNonce();
$this->generateNonce();
$digest = <<<DIGEST
Digest username="mariano",
realm="localhost",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,11 +561,47 @@ public function testImpersonate()
$controller = new Controller($request, $this->response);
$registry = new ComponentRegistry($controller);
$component = new AuthenticationComponent($registry);

$this->assertEquals($impersonator, $controller->getRequest()->getSession()->read('Auth'));
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->impersonate($impersonated);
$this->assertEquals($impersonated, $controller->getRequest()->getSession()->read('Auth'));
$this->assertEquals($identity, $controller->getRequest()->getSession()->read('AuthImpersonate'));
$this->assertEquals($impersonator, $controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->stopImpersonating();
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));
}

/**
* test that impersonate() can handle identities with array data within them.
*
* @return void
*/
public function testImpersonateDecoratorIgnored()
{
$impersonator = ['username' => 'mariano'];
$impersonated = new ArrayObject(['username' => 'larry']);

$this->request->getSession()->write('Auth', $impersonator);
$this->service->authenticate($this->request);
$identity = new Identity($impersonator);
$request = $this->request
->withAttribute('identity', $identity)
->withAttribute('authentication', $this->service);
$controller = new Controller($request, $this->response);
$registry = new ComponentRegistry($controller);
$component = new AuthenticationComponent($registry);

$this->assertEquals($impersonator, $controller->getRequest()->getSession()->read('Auth'));
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->impersonate($impersonated);
$this->assertEquals($impersonated, $controller->getRequest()->getSession()->read('Auth'));
$this->assertEquals(new ArrayObject($impersonator), $controller->getRequest()->getSession()->read('AuthImpersonate'));

$component->stopImpersonating();
$this->assertNull($controller->getRequest()->getSession()->read('AuthImpersonate'));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Identifier/IdentifierCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function testIdentify()
$this->assertInstanceOf('\ArrayAccess', $result);
$this->assertInstanceOf(PasswordIdentifier::class, $collection->getIdentificationProvider());

$result = $collection->identify([
$collection->identify([
'username' => 'mariano',
'password' => 'invalid password',
]);
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Identifier/Resolver/OrmResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function testFindConfig()
'userModel' => 'AuthUsers',
'finder' => [
'all',
'auth' => ['return_created' => true],
'auth' => ['returnCreated' => true],
],
]);

Expand Down
Loading