Skip to content

Commit

Permalink
merge 14.next-cake5
Browse files Browse the repository at this point in the history
  • Loading branch information
Andres Campanario committed Mar 12, 2024
2 parents 738489c + 6372588 commit d0fcabb
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 23 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ Changelog
=========
Releases for CakePHP 5
-------------
* 14.0
* Set dependecy for CakeDC/Auth to 10.0. Perform 2FA refactoring,

* 12.0
* Migrated to web-auth/webauthn-lib:^4.4
* Migrated to robthree/twofactorauth:^2.0
Expand All @@ -11,6 +14,20 @@ Releases for CakePHP 5

Releases for CakePHP 4.5
------------------------
* 13.0.0
* Set dependecy for CakeDC/Auth to 9.0. Perform 2FA refactoring,

* 11.3.5
* Update ci.yml with php8.2 and php8.3
* fix: minor fix on last_login datetime format
* Update Permissions.md
* fix: config for updateLastLogin
* fix: remove deprecated code on profile logic
* feat:flash message on login, on cake4

* 11.3.4
* Fix `Detected invalid UTF-8 for field...` issue when storing session data from `Webauthn` in a mongo database.

* 11.3.3
* Add display of unauthorized url in flash message when debug is true

Expand Down
2 changes: 1 addition & 1 deletion Docs/Documentation/Permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ return [
//...... all other rules
[
'controller' => 'Pages',
'action' => ['home', 'contact', 'projects']
'action' => ['home', 'contact', 'projects'],
'bypassAuth' => true,
],
],
Expand Down
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
"prefer-stable": true,
"require": {
"php": ">=8.1",
"cakephp/cakephp": "^5.0.0",
"cakedc/auth": "^8.0.0",
"cakephp/authorization": "^3.0.0",
"cakephp/authentication": "^3.0.0"
"cakephp/cakephp": "^5.0",
"cakedc/auth": "^10.0",
"cakephp/authorization": "^3.0",
"cakephp/authentication": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^10.0",
Expand Down
5 changes: 5 additions & 0 deletions config/users.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
'Profile' => [
// Allow view other users profiles
'viewOthers' => true,
'contain' => [],
],
'Key' => [
'Session' => [
Expand Down Expand Up @@ -149,6 +150,10 @@
'id' => null,//default value is the current domain
'checker' => \CakeDC\Auth\Authentication\DefaultWebauthn2FAuthenticationChecker::class,
],
'TwoFactorProcessors' => [
\CakeDC\Auth\Authentication\TwoFactorProcessor\Webauthn2faProcessor::class,
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
],
// default configuration used to auto-load the Auth Component, override to change the way Auth works
'Auth' => [
'Authentication' => [
Expand Down
14 changes: 7 additions & 7 deletions src/Loader/AuthenticationServiceLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Cake\Core\Configure;
use CakeDC\Auth\Authentication\AuthenticationService;
use CakeDC\Auth\Authentication\TwoFactorProcessorLoader;
use Psr\Http\Message\ServerRequestInterface;

/**
Expand All @@ -33,10 +34,11 @@ class AuthenticationServiceLoader
*/
public function __invoke(ServerRequestInterface $request)
{
$service = new AuthenticationService();
$processors = TwoFactorProcessorLoader::processors();
$service = new AuthenticationService(['processors' => $processors]);
$this->loadIdentifiers($service);
$this->loadAuthenticators($service);
$this->loadTwoFactorAuthenticator($service);
$this->loadTwoFactorAuthenticator($service, $processors);

return $service;
}
Expand Down Expand Up @@ -78,14 +80,12 @@ protected function loadAuthenticators($service)
* Load the CakeDC/Auth.TwoFactor based on config OneTimePasswordAuthenticator.login
*
* @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service to load identifiers
* @param \CakeDC\Auth\Authentication\TwoFactorProcessorCollection $processors TwoFactorProcessors collection
* @return void
*/
protected function loadTwoFactorAuthenticator($service)
protected function loadTwoFactorAuthenticator($service, $processors)
{
if (
Configure::read('OneTimePasswordAuthenticator.login') !== false
|| Configure::read('Webauthn2fa.enabled') !== false
) {
if (collection($processors)->some(fn ($processor) => $processor->enabled())) {
$service->loadAuthenticator('CakeDC/Auth.TwoFactor', [
'skipTwoFactorVerify' => true,
]);
Expand Down
7 changes: 3 additions & 4 deletions src/Loader/MiddlewareQueueLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Authorization\Middleware\RequestAuthorizationMiddleware;
use Cake\Core\Configure;
use Cake\Http\MiddlewareQueue;
use CakeDC\Auth\Authentication\TwoFactorProcessorLoader;
use CakeDC\Auth\Middleware\TwoFactorMiddleware;
use CakeDC\Users\Middleware\SocialAuthMiddleware;
use CakeDC\Users\Middleware\SocialEmailMiddleware;
Expand Down Expand Up @@ -95,10 +96,8 @@ protected function loadAuthenticationMiddleware(
*/
protected function load2faMiddleware(MiddlewareQueue $middlewareQueue)
{
if (
Configure::read('OneTimePasswordAuthenticator.login') !== false
|| Configure::read('Webauthn2fa.enabled') !== false
) {
$processors = TwoFactorProcessorLoader::processors();
if (collection($processors)->some(fn ($processor) => $processor->enabled())) {
$middlewareQueue->add(TwoFactorMiddleware::class);
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/Webauthn/AuthenticateAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function getOptions(): PublicKeyCredentialRequestOptions

$this->request->getSession()->write(
'Webauthn2fa.authenticateOptions',
$options
json_encode($options)
);

return $options;
Expand All @@ -54,7 +54,10 @@ public function getOptions(): PublicKeyCredentialRequestOptions
*/
public function verifyResponse(): \Webauthn\PublicKeyCredentialSource
{
$options = $this->request->getSession()->read('Webauthn2fa.authenticateOptions');
/** @var \Webauthn\PublicKeyCredentialRequestOptions $options */
$options = PublicKeyCredentialRequestOptions::createFromString(
(string)$this->request->getSession()->read('Webauthn2fa.authenticateOptions')
);

$publicKeyCredentialLoader = $this->createPublicKeyCredentialLoader();

Expand Down
5 changes: 3 additions & 2 deletions templates/Users/profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
)
?>
</h3>
<?php //@todo add to config ?>
<?= $this->Html->link(__d('cake_d_c/users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?>
<?php if ($isCurrentUser) : ?>
<?= $this->Html->link(__d('cake_d_c/users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?>
<?php endif; ?>
<div class="row">
<div class="large-6 columns strings">
<h6 class="subheader"><?= __d('cake_d_c/users', 'Username') ?></h6>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ public function testLoginPostRequestRightPasswordIsEnabledWebauthn2fa()
{
EventManager::instance()->on('TestApp.afterPluginBootstrap', function () {
Configure::write(['Webauthn2fa.enabled' => true, 'Webauthn2fa.appName' => 'TestUsers']);
Configure::write([
'TwoFactorProcessors' => [
\CakeDC\Auth\Authentication\TwoFactorProcessor\Webauthn2faProcessor::class,
],
]);
});
$this->enableRetainFlashMessages();
$this->post('/login', [
Expand Down
1 change: 0 additions & 1 deletion tests/TestCase/Model/Behavior/RegisterBehaviorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public function setUp(): void
{
parent::setUp();
$table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users');
$table->addBehavior('CakeDC/Users/Register.Register');
$this->Table = $table;
$this->Behavior = $table->behaviors()->Register;
TransportFactory::setConfig('test', ['className' => 'Debug']);
Expand Down
19 changes: 19 additions & 0 deletions tests/TestCase/PluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public function testMiddleware()
{
Configure::write('Users.Social.login', true);
Configure::write('OneTimePasswordAuthenticator.login', true);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);
Configure::write('Auth.Authorization.enable', true);

$plugin = new Plugin();
Expand Down Expand Up @@ -75,6 +78,9 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware()
Configure::write('Users.Social.login', true);
Configure::write('OneTimePasswordAuthenticator.login', true);
Configure::write('Auth.Authorization.enable', true);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);

$plugin = new Plugin();

Expand Down Expand Up @@ -106,6 +112,9 @@ public function testMiddlewareWithoutAuhorization()
Configure::write('Users.Social.login', true);
Configure::write('OneTimePasswordAuthenticator.login', true);
Configure::write('Auth.Authorization.enable', false);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);

$plugin = new Plugin();

Expand Down Expand Up @@ -133,6 +142,10 @@ public function testMiddlewareNotSocial()
Configure::write('Users.Social.login', false);
Configure::write('OneTimePasswordAuthenticator.login', true);
Configure::write('Auth.Authorization.enable', true);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);

$plugin = new Plugin();

$middleware = new MiddlewareQueue();
Expand All @@ -158,6 +171,9 @@ public function testMiddlewareNotOneTimePasswordAuthenticator()
Configure::write('Users.Social.login', true);
Configure::write('OneTimePasswordAuthenticator.login', false);
Configure::write('Auth.Authorization.enable', true);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);
$plugin = new Plugin();

$middleware = new MiddlewareQueue();
Expand Down Expand Up @@ -185,6 +201,9 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial()
Configure::write('Users.Social.login', false);
Configure::write('OneTimePasswordAuthenticator.login', false);
Configure::write('Auth.Authorization.enable', true);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);
$plugin = new Plugin();

$middleware = new MiddlewareQueue();
Expand Down
15 changes: 14 additions & 1 deletion tests/TestCase/Provider/AuthenticationServiceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ public function testGetAuthenticationService()
'Authentication.JwtSubject',
]);
Configure::write('OneTimePasswordAuthenticator.login', true);
Configure::write('TwoFactorProcessors', [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
]);

$authenticationServiceProvider = new AuthenticationServiceProvider();
$service = $authenticationServiceProvider->getAuthenticationService(new ServerRequest(), new Response());
Expand Down Expand Up @@ -114,7 +117,7 @@ public function testGetAuthenticationService()
'loginUrl' => null,
'urlChecker' => 'Authentication.Default',
'skipTwoFactorVerify' => true,
'className' => 'CakeDC/Auth.TwoFactor'
'className' => 'CakeDC/Auth.TwoFactor',
],
];
$actual = [];
Expand All @@ -136,17 +139,20 @@ public function testGetAuthenticationService()
],
'resolver' => 'Authentication.Orm',
'passwordHasher' => null,
'className' => 'Authentication.Password',
],
TokenIdentifier::class => [
'tokenField' => 'api_token',
'dataField' => 'token',
'resolver' => 'Authentication.Orm',
'hashAlgorithm' => null,
'className' => 'Authentication.Token',
],
JwtSubjectIdentifier::class => [
'tokenField' => 'id',
'dataField' => 'sub',
'resolver' => 'Authentication.Orm',
'className' => 'Authentication.JwtSubject',
],
];
$actual = [];
Expand Down Expand Up @@ -197,18 +203,21 @@ public function testGetAuthenticationServiceWithoutOneTimePasswordAuthenticator(
'fields' => ['username' => 'email'],
'identify' => true,
'impersonateSessionKey' => 'AuthImpersonate',
'className' => 'Authentication.Session',
],
'Form' => [
'className' => 'CakeDC/Auth.Form',
'loginUrl' => '/login',
'fields' => ['username' => 'email', 'password' => 'alt_password'],
'className' => 'CakeDC/Auth.Form',
],
'Token' => [
'className' => 'Authentication.Token',
'skipTwoFactorVerify' => true,
'header' => null,
'queryParam' => 'api_key',
'tokenPrefix' => null,
'className' => 'Authentication.Token',
],
]);
Configure::write('Auth.Identifiers', [
Expand All @@ -220,6 +229,7 @@ public function testGetAuthenticationServiceWithoutOneTimePasswordAuthenticator(
'Authentication.JwtSubject',
]);
Configure::write('OneTimePasswordAuthenticator.login', false);
Configure::write('TwoFactorProcessors', []);

$authenticationServiceProvider = new AuthenticationServiceProvider();
$service = $authenticationServiceProvider->getAuthenticationService(new ServerRequest(), new Response());
Expand All @@ -237,17 +247,20 @@ public function testGetAuthenticationServiceWithoutOneTimePasswordAuthenticator(
'identityAttribute' => 'identity',
'skipTwoFactorVerify' => true,
'impersonateSessionKey' => 'AuthImpersonate',
'className' => 'Authentication.Session',
],
FormAuthenticator::class => [
'loginUrl' => '/login',
'fields' => ['username' => 'email', 'password' => 'alt_password'],
'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login',
'className' => 'CakeDC/Auth.Form',
],
TokenAuthenticator::class => [
'header' => null,
'queryParam' => 'api_key',
'tokenPrefix' => null,
'skipTwoFactorVerify' => true,
'className' => 'Authentication.Token',
],
];
$actual = [];
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Webauthn/AuthenticateAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ public function testGetOptions()
$adapter = new AuthenticateAdapter($request);
$options = $adapter->getOptions();
$this->assertInstanceOf(PublicKeyCredentialRequestOptions::class, $options);
$this->assertSame($options, $request->getSession()->read('Webauthn2fa.authenticateOptions'));
$this->assertSame(json_encode($options), $request->getSession()->read('Webauthn2fa.authenticateOptions'));
}
}
4 changes: 4 additions & 0 deletions tests/test_app/config/users.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
'OAuth.providers.twitter.options.clientSecret' => '999988899',
'OAuth.providers.google.options.clientId' => '0000000990909090',
'OAuth.providers.google.options.clientSecret' => '1565464559789798',
'TwoFactorProcessors' => [
\CakeDC\Auth\Authentication\TwoFactorProcessor\OneTimePasswordProcessor::class,
\CakeDC\Auth\Authentication\TwoFactorProcessor\Webauthn2faProcessor::class,
],
];

0 comments on commit d0fcabb

Please sign in to comment.