From 8404b3dc9e34a33393157e2db5c63b6b5a7bf61a Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 9 Oct 2023 15:25:21 +0900 Subject: [PATCH 001/128] docs: small improvements --- admin/RELEASE.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 69cb216b2..5940307c3 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -36,11 +36,11 @@ the changelog. ## Preparation -* Clone **codeigniter4/shield** and resolve any necessary PRs +* [ ] Clone **codeigniter4/shield** and resolve any necessary PRs ```console git clone git@github.com:codeigniter4/shield.git ``` -* Merge any Security Advisory PRs in private forks +* [ ] Merge any Security Advisory PRs in private forks ## Process @@ -48,29 +48,31 @@ the changelog. > been included with their PR, so this process assumes you will not be > generating much new content. -* Create a new branch `release-1.x.x` -* Update **src/Auth.php** with the new version number: +* [ ] Create a new branch `release-1.x.x` +* [ ] Update **src/Auth.php** with the new version number: `const SHIELD_VERSION = '1.x.x';` -* Commit the changes with "Prep for 1.x.x release" and push to origin -* Create a new PR from `release-1.x.x` to `develop`: +* [ ] Commit the changes with "Prep for 1.x.x release" and push to origin +* [ ] Create a new PR from `release-1.x.x` to `develop`: * Title: "Prep for 1.x.x release" * Description: "Updates version references for `1.x.x`." (plus checklist) -* Let all tests run, then review and merge the PR -* Create a new PR from `develop` to `master`: +* [ ] Let all tests run, then review and merge the PR +* [ ] Create a new PR from `develop` to `master`: * Title: "1.x.x Ready code" * Description: blank -* Merge the PR -* Create a new Release: +* [ ] Merge the PR +* [ ] Create a new Release: * Version: "v1.x.x" * Target: master * Title: "v1.x.x" * Click the "Generate release notes" button * Remove "### Others (Only for checking. Remove this category)" section + * Add important notes if necessary + * Add link to Upgrade Guide if necessary * Check "Create a discussion for this release" * Click the "Publish release" button -* Watch for the "docs" action and verify that the user guide updated: +* [ ] Watch for the "docs" action and verify that the user guide updated: * [docs](https://github.com/codeigniter4/shield/actions/workflows/docs.yml) -* Fast-forward `develop` branch to catch the merge commit from `master` +* [ ] Fast-forward `develop` branch to catch the merge commit from `master` (note: pushing to `develop` is restricted to administrators): ```console git fetch origin @@ -82,9 +84,9 @@ the changelog. **At this point, `master` must be merged into `develop`.** Otherwise, the GitHub-generated release note from `develop` for the next release will not be generated correctly. -* Publish any Security Advisories that were resolved from private forks +* [ ] Publish any Security Advisories that were resolved from private forks (note: publishing is restricted to administrators) -* Announce the release on the forums and Slack channel +* [ ] Announce the release on the forums and Slack channel (note: this forum is restricted to administrators): * Make a new topic in the "News & Discussion" forums: https://forum.codeigniter.com/forum-2.html From dbdafb1fa0131b7764b9ca63e5c38c38a68fdcfa Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 10 Oct 2023 06:59:45 +0700 Subject: [PATCH 002/128] [Rector] Apply StringifyStrNeedlesRector --- rector.php | 2 -- src/Authentication/Passwords/NothingPersonalValidator.php | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rector.php b/rector.php index 12a24007d..76a02ab28 100644 --- a/rector.php +++ b/rector.php @@ -31,7 +31,6 @@ use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; -use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; use Rector\PHPUnit\AnnotationsToAttributes\Rector\Class_\AnnotationWithValueToAttributeRector; use Rector\PHPUnit\CodeQuality\Rector\Class_\YieldDataProviderRector; use Rector\PHPUnit\Set\PHPUnitSetList; @@ -82,7 +81,6 @@ __DIR__ . '/src/Views', JsonThrowOnErrorRector::class, - StringifyStrNeedlesRector::class, YieldDataProviderRector::class, // Note: requires php 8 diff --git a/src/Authentication/Passwords/NothingPersonalValidator.php b/src/Authentication/Passwords/NothingPersonalValidator.php index 92151e8b0..1a2d7eaf6 100644 --- a/src/Authentication/Passwords/NothingPersonalValidator.php +++ b/src/Authentication/Passwords/NothingPersonalValidator.php @@ -183,6 +183,8 @@ protected function isNotSimilar(string $password, ?User $user): bool * * Replaces all non-word characters and underscores in $str with a space. * Then it explodes that result using the space for a delimiter. + * + * @return array */ protected function strip_explode(string $str): array { From e0c53d7d28aaaebaef7e460cc63d64d8654a6d65 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 10 Oct 2023 07:00:47 +0700 Subject: [PATCH 003/128] Run Rector --- src/Authentication/Passwords/NothingPersonalValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Authentication/Passwords/NothingPersonalValidator.php b/src/Authentication/Passwords/NothingPersonalValidator.php index 1a2d7eaf6..14a8c587b 100644 --- a/src/Authentication/Passwords/NothingPersonalValidator.php +++ b/src/Authentication/Passwords/NothingPersonalValidator.php @@ -79,7 +79,7 @@ protected function isNotPersonal(string $password, ?User $user): bool if (! empty($domain)) { $emailParts[] = $domain; } - $needles = array_merge($needles, $emailParts); + $needles = [...$needles, ...$emailParts]; // Get any other "personal" fields defined in config $personalFields = $this->config->personalFields; From 282c5175990131e8ad6efabcf20b3d9b60fcde47 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 10 Oct 2023 10:43:16 +0900 Subject: [PATCH 004/128] chore: it fails on master branch --- .github/workflows/no-merge-commits.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/no-merge-commits.yml b/.github/workflows/no-merge-commits.yml index 11173fbb4..6ce03b88c 100644 --- a/.github/workflows/no-merge-commits.yml +++ b/.github/workflows/no-merge-commits.yml @@ -2,6 +2,8 @@ name: Detect Merge Commits on: pull_request: + branches: + - develop permissions: contents: read From 1393c18418d715f9d3432b5bed60d1c7d1046a13 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 10 Oct 2023 08:43:55 +0700 Subject: [PATCH 005/128] Fix php 7.4 substr can return false --- src/Authentication/Passwords/PwnedValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Authentication/Passwords/PwnedValidator.php b/src/Authentication/Passwords/PwnedValidator.php index ef862b2b8..4023da3cc 100644 --- a/src/Authentication/Passwords/PwnedValidator.php +++ b/src/Authentication/Passwords/PwnedValidator.php @@ -35,7 +35,7 @@ public function check(string $password, ?User $user = null): Result { $hashedPword = strtoupper(sha1($password)); $rangeHash = substr($hashedPword, 0, 5); - $searchHash = substr($hashedPword, 5); + $searchHash = (string) substr($hashedPword, 5); try { $client = Services::curlrequest([ From 6fb9594fa668a89832486d8a01827c1b966c0db8 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 10 Oct 2023 08:45:29 +0700 Subject: [PATCH 006/128] Fix php 7.4 substr can return false --- src/Authentication/Passwords/PwnedValidator.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Authentication/Passwords/PwnedValidator.php b/src/Authentication/Passwords/PwnedValidator.php index 4023da3cc..a68e92e99 100644 --- a/src/Authentication/Passwords/PwnedValidator.php +++ b/src/Authentication/Passwords/PwnedValidator.php @@ -35,7 +35,8 @@ public function check(string $password, ?User $user = null): Result { $hashedPword = strtoupper(sha1($password)); $rangeHash = substr($hashedPword, 0, 5); - $searchHash = (string) substr($hashedPword, 5); + /** @var string $searchHash */ + $searchHash = substr($hashedPword, 5); try { $client = Services::curlrequest([ From 71e0ddcb65092d84511476c83a344137b782872e Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 08:54:42 +0900 Subject: [PATCH 007/128] fix: replace `/>` with `>` for input tags --- src/Views/email_2fa_show.php | 2 +- src/Views/email_2fa_verify.php | 2 +- src/Views/email_activate_show.php | 2 +- src/Views/login.php | 4 ++-- src/Views/magic_link_form.php | 2 +- src/Views/register.php | 8 ++++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Views/email_2fa_show.php b/src/Views/email_2fa_show.php index 46cf68cf4..b030cfde8 100644 --- a/src/Views/email_2fa_show.php +++ b/src/Views/email_2fa_show.php @@ -23,7 +23,7 @@ - value="email) ?>" required /> + value="email) ?>" required>
diff --git a/src/Views/email_2fa_verify.php b/src/Views/email_2fa_verify.php index 722977b8c..dbaac3067 100644 --- a/src/Views/email_2fa_verify.php +++ b/src/Views/email_2fa_verify.php @@ -21,7 +21,7 @@
+ inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" required>
diff --git a/src/Views/email_activate_show.php b/src/Views/email_activate_show.php index 066bd0b1c..6b41d4626 100644 --- a/src/Views/email_activate_show.php +++ b/src/Views/email_activate_show.php @@ -21,7 +21,7 @@
+ pattern="[0-9]*" autocomplete="one-time-code" value="" required>
diff --git a/src/Views/login.php b/src/Views/login.php index 71b4501d0..838734b44 100644 --- a/src/Views/login.php +++ b/src/Views/login.php @@ -33,13 +33,13 @@
- +
- +
diff --git a/src/Views/magic_link_form.php b/src/Views/magic_link_form.php index ed820717e..6bef87a16 100644 --- a/src/Views/magic_link_form.php +++ b/src/Views/magic_link_form.php @@ -30,7 +30,7 @@
+ value="user()->email ?? null) ?>" required>
diff --git a/src/Views/register.php b/src/Views/register.php index 7adba1aa3..57726e8e8 100644 --- a/src/Views/register.php +++ b/src/Views/register.php @@ -29,25 +29,25 @@
- +
- +
- +
- +
From 5b4f1654fa9db6d9e1061f3de4707b553a42290c Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 09:00:32 +0900 Subject: [PATCH 008/128] docs: improve instructions --- docs/customization/login_identifier.md | 60 ++++++++++++++++++-------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/docs/customization/login_identifier.md b/docs/customization/login_identifier.md index aa51d4b4d..2e143c899 100644 --- a/docs/customization/login_identifier.md +++ b/docs/customization/login_identifier.md @@ -1,35 +1,61 @@ # Customizing Login Identifier -If your application has a need to use something other than `email` or `username`, you may specify any valid column within the `users` table that you may have added. This allows you to easily use phone numbers, employee or school IDs, etc as the user identifier. You must implement the following steps to set this up: +If your application has a need to use something other than `email` or `username`, you may specify any valid column within the `users` table that you may have added. This allows you to easily use phone numbers, employee or school IDs, etc. as the user identifier. You must implement the following steps to set this up: This only works with the Session authenticator. -1. Create a [migration](http://codeigniter.com/user_guide/dbmgmt/migration.html) that adds a new column to the `users` table. -2. Edit `app/Config/Auth.php` so that the new column you just created is within the `$validFields` array. +## Create Migration File - ```php - public array $validFields = [ - 'employee_id' - ]; - ``` +Create a [migration](http://codeigniter.com/user_guide/dbmgmt/migration.html) that +adds a new column to the `users` table. + +## Change $validFields + +Edit `app/Config/Auth.php` so that the new column you just created is within the +`$validFields` array. + +```php +public array $validFields = [ + 'employee_id' +]; +``` + +If you have multiple login forms on your site that use different credentials, you +must have all of the valid identifying fields in the array. - If you have multiple login forms on your site that use different credentials, you must have all of the valid identifying fields in the array. +```php +public array $validFields = [ + 'email', + 'employee_id' +]; +``` + +## Update Validation Rules + +!!! warning + + This is very important for security. + +You must write new **Validation Rules** and then set them using the +[Customizing Validation Rules](./validation_rules.md#login) description. + +## Customize Login View + +1. Change the `login` view file in the `app/Config/Auth.php` file. ```php - public array $validFields = [ - 'email', - 'employee_id' + public array $views = [ + 'login' => '\App\Views\Shield\login', + // ... ]; ``` - !!! warning - - It is very important for security that if you add a new column for identifier, you must write a new **Validation Rules** and then set it using the [Customizing Validation Rules](./validation_rules.md) description. -3. Edit the login form to change the name of the default `email` input to the new field name. +2. Copy file `vendor\codeigniter4\shield\src\Views\login.php` to `app\Views\Shield\login.php`. +3. Customize the login form to change the name of the default `email` input to the new field name. ```php
- +
``` From ba07cfd22aedac46a5d1869f4a42d51362147dd6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 09:49:26 +0900 Subject: [PATCH 009/128] docs: add "Customizing Views" --- docs/customization/views.md | 35 +++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 36 insertions(+) create mode 100644 docs/customization/views.md diff --git a/docs/customization/views.md b/docs/customization/views.md new file mode 100644 index 000000000..8173d7095 --- /dev/null +++ b/docs/customization/views.md @@ -0,0 +1,35 @@ +# Customizing Views + +Shield provides the default view files, but they are sample files. +Customization is recommended. + +## Change $views + +Change values in `$views` in the **app/Config/Auth.php** file. + +For example, if you customize the login page, change the value for `'login'`: + +```php +public array $views = [ + 'login' => '\App\Views\Shield\login', // changed this line. + 'register' => '\CodeIgniter\Shield\Views\register', + 'layout' => '\CodeIgniter\Shield\Views\layout', + 'action_email_2fa' => '\CodeIgniter\Shield\Views\email_2fa_show', + 'action_email_2fa_verify' => '\CodeIgniter\Shield\Views\email_2fa_verify', + 'action_email_2fa_email' => '\CodeIgniter\Shield\Views\Email\email_2fa_email', + 'action_email_activate_show' => '\CodeIgniter\Shield\Views\email_activate_show', + 'action_email_activate_email' => '\CodeIgniter\Shield\Views\Email\email_activate_email', + 'magic-link-login' => '\CodeIgniter\Shield\Views\magic_link_form', + 'magic-link-message' => '\CodeIgniter\Shield\Views\magic_link_message', + 'magic-link-email' => '\CodeIgniter\Shield\Views\Email\magic_link_email', +]; +``` + +## Copy View File + +Copy the file you want to customize in **vendor/codeigniter4/shield/src/Views/** +to the **app/Views/Shield/** folder. + +## Customize Content + +Customize the content of the view file in **app/Views/Shield/** as you like. diff --git a/mkdocs.yml b/mkdocs.yml index 64917aeef..b68ce068e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -106,6 +106,7 @@ nav: - quick_start_guide/using_authorization.md - Customization: - customization/table_names.md + - customization/views.md - customization/route_config.md - customization/redirect_urls.md - customization/validation_rules.md From d22a6ae1dc03cdbea11a8d74b824fd3d39b22de5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 09:53:59 +0900 Subject: [PATCH 010/128] docs: fix directory separators --- docs/customization/login_identifier.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customization/login_identifier.md b/docs/customization/login_identifier.md index 2e143c899..fc4abd91c 100644 --- a/docs/customization/login_identifier.md +++ b/docs/customization/login_identifier.md @@ -50,7 +50,7 @@ You must write new **Validation Rules** and then set them using the ]; ``` -2. Copy file `vendor\codeigniter4\shield\src\Views\login.php` to `app\Views\Shield\login.php`. +2. Copy file `vendor/codeigniter4/shield/src/Views/login.php` to `app/Views/Shield/login.php`. 3. Customize the login form to change the name of the default `email` input to the new field name. ```php From cae1d34a8e85b104686ba27f43051549cce2dadd Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 09:54:52 +0900 Subject: [PATCH 011/128] docs: fix text decoration for file paths --- docs/customization/login_identifier.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/customization/login_identifier.md b/docs/customization/login_identifier.md index fc4abd91c..6bcec7393 100644 --- a/docs/customization/login_identifier.md +++ b/docs/customization/login_identifier.md @@ -11,7 +11,7 @@ adds a new column to the `users` table. ## Change $validFields -Edit `app/Config/Auth.php` so that the new column you just created is within the +Edit **app/Config/Auth.php** so that the new column you just created is within the `$validFields` array. ```php @@ -41,7 +41,7 @@ You must write new **Validation Rules** and then set them using the ## Customize Login View -1. Change the `login` view file in the `app/Config/Auth.php` file. +1. Change the `login` view file in the **app/Config/Auth.php** file. ```php public array $views = [ @@ -50,7 +50,7 @@ You must write new **Validation Rules** and then set them using the ]; ``` -2. Copy file `vendor/codeigniter4/shield/src/Views/login.php` to `app/Views/Shield/login.php`. +2. Copy file **vendor/codeigniter4/shield/src/Views/login.php** to **app/Views/Shield/login.php**. 3. Customize the login form to change the name of the default `email` input to the new field name. ```php From 874e02433e969c9e8c2a1ea5aa02ab681bc06ad6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 10:20:50 +0900 Subject: [PATCH 012/128] docs: add link to "Integrating Custom View Libraries" --- docs/customization/views.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/customization/views.md b/docs/customization/views.md index 8173d7095..e38961da6 100644 --- a/docs/customization/views.md +++ b/docs/customization/views.md @@ -3,6 +3,10 @@ Shield provides the default view files, but they are sample files. Customization is recommended. +If your application uses a different method to convert view files to HTML than +CodeIgniter's built-in `view()` helper, see +[Integrating Custom View Libraries](./integrating_custom_view_libs.md). + ## Change $views Change values in `$views` in the **app/Config/Auth.php** file. From b7d591a83f82e2397da4a06f50d5a3e222ddd262 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 10 Oct 2023 11:06:15 +0900 Subject: [PATCH 013/128] chore: remove autoload of auth_helper.php by Composer --- composer.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/composer.json b/composer.json index d7a4327bd..a412e5817 100644 --- a/composer.json +++ b/composer.json @@ -52,9 +52,6 @@ "psr-4": { "CodeIgniter\\Shield\\": "src" }, - "files": [ - "src/Helpers/auth_helper.php" - ], "exclude-from-classmap": [ "**/Database/Migrations/**" ] From 7c6a01794811c5923349f6f43eaaab61b537c9b1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 10 Oct 2023 11:08:15 +0900 Subject: [PATCH 014/128] test: add 'auth' and 'setting' helper loading --- tests/_support/TestCase.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php index 22ba985d6..22a547932 100644 --- a/tests/_support/TestCase.php +++ b/tests/_support/TestCase.php @@ -26,6 +26,9 @@ protected function setUp(): void $settings = new Settings($configSettings); Services::injectMock('settings', $settings); + // Load helpers that should be autoloaded + helper(['auth', 'setting']); + // Ensure from email is available anywhere during Tests helper('setting'); setting('Email.fromEmail', 'foo@example.com'); From 81d2d756a996265590783792a14019ef4c699e75 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 10 Oct 2023 11:09:56 +0900 Subject: [PATCH 015/128] feat: setup command configure helper autoloading --- src/Commands/Setup.php | 62 +++++++++++++++++++++++++++++------- tests/Commands/SetupTest.php | 7 ++-- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/Commands/Setup.php b/src/Commands/Setup.php index a39e7de10..350a0836b 100644 --- a/src/Commands/Setup.php +++ b/src/Commands/Setup.php @@ -8,6 +8,7 @@ use CodeIgniter\Commands\Database\Migrate; use CodeIgniter\Shield\Commands\Setup\ContentReplacer; use CodeIgniter\Test\Filters\CITestStreamFilter; +use Config\Autoload as AutoloadConfig; use Config\Email as EmailConfig; use Config\Services; @@ -78,7 +79,7 @@ private function publishConfig(): void $this->publishConfigAuthGroups(); $this->publishConfigAuthToken(); - $this->setupHelper(); + $this->setAutoloadHelpers(); $this->setupRoutes(); $this->setSecurityCSRF(); @@ -236,24 +237,61 @@ private function replace(string $file, array $replaces): bool return false; } - private function setupHelper(): void + private function setAutoloadHelpers(): void { - $file = 'Controllers/BaseController.php'; - $check = '$this->helpers = array_merge($this->helpers, [\'setting\']);'; + $file = 'Config/Autoload.php'; + + $path = $this->distPath . $file; + $cleanPath = clean_path($path); + + if (! is_file($path)) { + $this->error(" Not found file '{$cleanPath}'."); + + return; + } + + $config = new AutoloadConfig(); + $helpers = $config->helpers; + $newHelpers = array_unique(array_merge($helpers, ['auth', 'setting'])); + + $pattern = '/^ public \$helpers = \[.*\];/mu'; + $replace = ' public $helpers = [\'' . implode("', '", $newHelpers) . '\'];'; + $content = file_get_contents($path); + $output = preg_replace($pattern, $replace, $content); + + // check if the content is updated + if ($output === $content) { + $this->write(CLI::color(' Autoload Setup: ', 'green') . 'Everything is fine.'); + + return; + } + + if (write_file($path, $output)) { + $this->write(CLI::color(' Updated: ', 'green') . $cleanPath); + + $this->removeHelperLoadingInBaseController(); + } else { + $this->error(" Error updating file '{$cleanPath}'."); + } + } + + private function removeHelperLoadingInBaseController(): void + { + $file = 'Controllers/BaseController.php'; + + $check = ' $this->helpers = array_merge($this->helpers, [\'setting\']);'; // Replace old helper setup $replaces = [ '$this->helpers = array_merge($this->helpers, [\'auth\', \'setting\']);' => $check, ]; - if ($this->replace($file, $replaces)) { - return; - } + $this->replace($file, $replaces); - // Add helper setup - $pattern = '/(' . preg_quote('// Do Not Edit This Line', '/') . ')/u'; - $replace = $check . "\n\n " . '$1'; - - $this->add($file, $check, $pattern, $replace); + // Remove helper setup + $replaces = [ + "\n" . $check . "\n" => '', + ]; + $this->replace($file, $replaces); } private function setupRoutes(): void diff --git a/tests/Commands/SetupTest.php b/tests/Commands/SetupTest.php index 648f0f12e..3401295a0 100644 --- a/tests/Commands/SetupTest.php +++ b/tests/Commands/SetupTest.php @@ -65,6 +65,9 @@ public function testRun(): void $this->assertStringContainsString('namespace Config;', $authToken); $this->assertStringContainsString('use CodeIgniter\Shield\Config\AuthToken as ShieldAuthToken;', $authToken); + $autoload = file_get_contents($appFolder . 'Config/Autoload.php'); + $this->assertStringContainsString('$helpers = [\'auth\', \'setting\'];', $autoload); + $routes = file_get_contents($appFolder . 'Config/Routes.php'); $this->assertStringContainsString('service(\'auth\')->routes($routes);', $routes); @@ -77,7 +80,7 @@ public function testRun(): void ' Created: vfs://root/Config/Auth.php Created: vfs://root/Config/AuthGroups.php Created: vfs://root/Config/AuthToken.php - Updated: vfs://root/Controllers/BaseController.php + Updated: vfs://root/Config/Autoload.php Updated: vfs://root/Config/Routes.php Updated: We have updated file \'vfs://root/Config/Security.php\' for security reasons. Updated: vfs://root/Config/Email.php', @@ -112,7 +115,7 @@ public function testRunEmailConfigIsFine(): void ' Created: vfs://root/Config/Auth.php Created: vfs://root/Config/AuthGroups.php Created: vfs://root/Config/AuthToken.php - Updated: vfs://root/Controllers/BaseController.php + Updated: vfs://root/Config/Autoload.php Updated: vfs://root/Config/Routes.php Updated: We have updated file \'vfs://root/Config/Security.php\' for security reasons.', $result From 068be1f4a34a3f523c0d94faaa9be8236fbaa1a7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 10 Oct 2023 11:11:58 +0900 Subject: [PATCH 016/128] docs: update docs --- docs/getting_started/install.md | 29 +++++++++---------- .../authentication/authentication.md | 5 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/getting_started/install.md b/docs/getting_started/install.md index c608bd3f3..2f9534e3f 100644 --- a/docs/getting_started/install.md +++ b/docs/getting_started/install.md @@ -72,7 +72,8 @@ your project. ### Manual Setup -1. Copy the **Auth.php**, **AuthGroups.php**, and **AuthToken.php** from **vendor/codeigniter4/shield/src/Config/** into your project's config folder and update the namespace to `Config`. You will also need to have these classes extend the original classes. See the example below. These files contain all the settings, group, and permission information for your application and will need to be modified to meet the needs of your site. +1. **Config Setup:** + Copy the **Auth.php**, **AuthGroups.php**, and **AuthToken.php** from **vendor/codeigniter4/shield/src/Config/** into your project's config folder and update the namespace to `Config`. You will also need to have these classes extend the original classes. See the example below. These files contain all the settings, group, and permission information for your application and will need to be modified to meet the needs of your site. ```php // new file - app/Config/Auth.php @@ -91,29 +92,26 @@ your project. } ``` -2. **Helper Setup** The `setting` helper needs to be included in almost every page. The simplest way to do this is to add it to the `BaseController::initController()` method: +2. **Helper Setup:** + The `auth` and `setting` helpers need to be included in almost every page. + The simplest way to do this is to add it to the **app/Config/Autoload.php** file: ```php - public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) - { - $this->helpers = array_merge($this->helpers, ['setting']); - - // Do Not Edit This Line - parent::initController($request, $response, $logger); - } + public $helpers = ['auth', 'setting']; ``` - This requires that all of your controllers extend the `BaseController`, but that's a good practice anyway. - -3. **Routes Setup** The default auth routes can be setup with a single call in **app/Config/Routes.php**: +3. **Routes Setup:** + The default auth routes can be setup with a single call in **app/Config/Routes.php**: ```php service('auth')->routes($routes); ``` -4. **Security Setup** Set `Config\Security::$csrfProtection` to `'session'` for security reasons, if you use Session Authenticator. +4. **Security Setup:** + Set `Config\Security::$csrfProtection` to `'session'` for security reasons, if you use Session Authenticator. -5. Configure **app/Config/Email.php** to allow Shield to send emails with the [Email Class](https://codeigniter.com/user_guide/libraries/email.html). +5. **Email Setup:** + Configure **app/Config/Email.php** to allow Shield to send emails. ```php getProvider(); !!! note - The `auth_helper` is autoloaded by Composer. If you want to *override* the functions, - you need to define them in **app/Common.php**. + The `auth_helper` is autoloaded by CodeIgniter's autoloader if you follow the + installation instruction. If you want to *override* the functions, create + **app/Helpers/auth_helper.php**. ## Authenticator Responses From a8f2a8a4b6ce31e09a110975f24e2fb373e30337 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 10 Oct 2023 11:12:10 +0900 Subject: [PATCH 017/128] docs: add UPGRADING.md --- UPGRADING.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/UPGRADING.md b/UPGRADING.md index 1a6bcd5cd..bfcef207c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,30 @@ # Upgrade Guide +## Version 1.0.0-beta.7 to 1.0.0-beta.8 + +### Mandatory Config Changes + +#### Helper Autoloading + +Helper autoloading has been changed to be done by CodeIgniter's autoloader +instead of Composer. + +So you need to update the settings. Run `php spark shield:setup` again, and the +following steps will be done. + +1. Add `auth` and `setting` to the `$helpers` array in **app/Config/Autoload.php**: + + ```php + public $helpers = ['auth', 'setting']; + ``` + +2. Remove the following code in the `initController()` method in + `**app/Controllers/BaseController.php**: + + ```php + $this->helpers = array_merge($this->helpers, ['setting']); + ``` + ## Version 1.0.0-beta.6 to 1.0.0-beta.7 ### The minimum CodeIgniter version From ef50333d8ac5cb2333e60b126dc01b19fb7a7a4c Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 11 Oct 2023 09:27:38 +0900 Subject: [PATCH 018/128] refactor: remove duplicated code --- tests/_support/TestCase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php index 22a547932..021fccfd9 100644 --- a/tests/_support/TestCase.php +++ b/tests/_support/TestCase.php @@ -30,7 +30,6 @@ protected function setUp(): void helper(['auth', 'setting']); // Ensure from email is available anywhere during Tests - helper('setting'); setting('Email.fromEmail', 'foo@example.com'); setting('Email.fromName', 'John Smith'); From d2ea9d3620d8aad2282211a874cd3a7f1f92ae0d Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 12 Oct 2023 09:13:00 +0900 Subject: [PATCH 019/128] refactor: remove unneeded check --- src/Commands/Setup.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Commands/Setup.php b/src/Commands/Setup.php index 350a0836b..f4b14657e 100644 --- a/src/Commands/Setup.php +++ b/src/Commands/Setup.php @@ -244,12 +244,6 @@ private function setAutoloadHelpers(): void $path = $this->distPath . $file; $cleanPath = clean_path($path); - if (! is_file($path)) { - $this->error(" Not found file '{$cleanPath}'."); - - return; - } - $config = new AutoloadConfig(); $helpers = $config->helpers; $newHelpers = array_unique(array_merge($helpers, ['auth', 'setting'])); From dbd6f5cb1228b2e06ec1152f58cb99937c4473b2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 12 Oct 2023 10:51:47 +0900 Subject: [PATCH 020/128] refator: remove code that loads setting helper --- src/Authentication/Authenticators/Session.php | 2 -- src/Authorization/Groups.php | 7 ------- src/Authorization/Traits/Authorizable.php | 12 +++--------- src/Controllers/ActionController.php | 1 - src/Controllers/LoginController.php | 2 -- src/Controllers/MagicLinkController.php | 2 -- src/Controllers/RegisterController.php | 2 -- src/Filters/ForcePasswordResetFilter.php | 2 -- src/Filters/HmacAuth.php | 2 -- src/Filters/JWTAuth.php | 2 -- src/Filters/SessionAuth.php | 2 -- src/Filters/TokenAuth.php | 2 -- src/Helpers/email_helper.php | 2 -- src/Validation/ValidationRules.php | 4 ---- 14 files changed, 3 insertions(+), 41 deletions(-) diff --git a/src/Authentication/Authenticators/Session.php b/src/Authentication/Authenticators/Session.php index c5e9ba138..e15fba3ae 100644 --- a/src/Authentication/Authenticators/Session.php +++ b/src/Authentication/Authenticators/Session.php @@ -73,8 +73,6 @@ class Session implements AuthenticatorInterface public function __construct(UserModel $provider) { - helper('setting'); - $this->provider = $provider; $this->loginModel = model(LoginModel::class); diff --git a/src/Authorization/Groups.php b/src/Authorization/Groups.php index 918168ec3..ae223fb44 100644 --- a/src/Authorization/Groups.php +++ b/src/Authorization/Groups.php @@ -13,13 +13,6 @@ */ class Groups { - public function __construct() - { - if (! function_exists('setting')) { - helper('setting'); - } - } - /** * Grabs a group info from settings. */ diff --git a/src/Authorization/Traits/Authorizable.php b/src/Authorization/Traits/Authorizable.php index 6cee326ce..eb57cd788 100644 --- a/src/Authorization/Traits/Authorizable.php +++ b/src/Authorization/Traits/Authorizable.php @@ -259,9 +259,7 @@ public function can(string ...$permissions): bool return false; } - $matrix = function_exists('setting') - ? setting('AuthGroups.matrix') - : config('AuthGroups')->matrix; + $matrix = setting('AuthGroups.matrix'); foreach ($this->groupCache as $group) { // Check exact match @@ -396,9 +394,7 @@ private function saveGroupsOrPermissions(string $type, $model, array $cache): vo */ private function getConfigGroups(): array { - return function_exists('setting') - ? array_keys(setting('AuthGroups.groups')) - : array_keys(config('AuthGroups')->groups); + return array_keys(setting('AuthGroups.groups')); } /** @@ -406,8 +402,6 @@ private function getConfigGroups(): array */ private function getConfigPermissions(): array { - return function_exists('setting') - ? array_keys(setting('AuthGroups.permissions')) - : array_keys(config('AuthGroups')->permissions); + return array_keys(setting('AuthGroups.permissions')); } } diff --git a/src/Controllers/ActionController.php b/src/Controllers/ActionController.php index 805df0b88..8bcbb4f80 100644 --- a/src/Controllers/ActionController.php +++ b/src/Controllers/ActionController.php @@ -18,7 +18,6 @@ class ActionController extends BaseController { protected ?ActionInterface $action = null; - protected $helpers = ['setting']; /** * Perform an initial check if we have a valid action or not. diff --git a/src/Controllers/LoginController.php b/src/Controllers/LoginController.php index e38fa3817..0dc49436e 100644 --- a/src/Controllers/LoginController.php +++ b/src/Controllers/LoginController.php @@ -14,8 +14,6 @@ class LoginController extends BaseController { use Viewable; - protected $helpers = ['setting']; - /** * Displays the form the login to the site. * diff --git a/src/Controllers/MagicLinkController.php b/src/Controllers/MagicLinkController.php index 25ab09d99..3357f3d7d 100644 --- a/src/Controllers/MagicLinkController.php +++ b/src/Controllers/MagicLinkController.php @@ -34,8 +34,6 @@ class MagicLinkController extends BaseController public function __construct() { - helper('setting'); - /** @var class-string $providerClass */ $providerClass = setting('Auth.userProvider'); diff --git a/src/Controllers/RegisterController.php b/src/Controllers/RegisterController.php index 20daf5f73..43761b990 100644 --- a/src/Controllers/RegisterController.php +++ b/src/Controllers/RegisterController.php @@ -27,8 +27,6 @@ class RegisterController extends BaseController { use Viewable; - protected $helpers = ['setting']; - public function initController( RequestInterface $request, ResponseInterface $response, diff --git a/src/Filters/ForcePasswordResetFilter.php b/src/Filters/ForcePasswordResetFilter.php index bfa3d21aa..ce64492b4 100644 --- a/src/Filters/ForcePasswordResetFilter.php +++ b/src/Filters/ForcePasswordResetFilter.php @@ -32,8 +32,6 @@ public function before(RequestInterface $request, $arguments = null) return; } - helper('setting'); - /** @var Session $authenticator */ $authenticator = auth('session')->getAuthenticator(); diff --git a/src/Filters/HmacAuth.php b/src/Filters/HmacAuth.php index f655d0264..986175caa 100644 --- a/src/Filters/HmacAuth.php +++ b/src/Filters/HmacAuth.php @@ -23,8 +23,6 @@ public function before(RequestInterface $request, $arguments = null) { $authenticator = auth('hmac')->getAuthenticator(); - helper('setting'); - $requestParams = [ 'token' => $request->getHeaderLine(setting('Auth.authenticatorHeader')['hmac'] ?? 'Authorization'), 'body' => $request->getBody() ?? '', diff --git a/src/Filters/JWTAuth.php b/src/Filters/JWTAuth.php index 84914511b..735bf2f2d 100644 --- a/src/Filters/JWTAuth.php +++ b/src/Filters/JWTAuth.php @@ -33,8 +33,6 @@ public function before(RequestInterface $request, $arguments = null) return; } - helper('setting'); - /** @var JWT $authenticator */ $authenticator = auth('jwt')->getAuthenticator(); diff --git a/src/Filters/SessionAuth.php b/src/Filters/SessionAuth.php index b7d449666..18ec1a571 100644 --- a/src/Filters/SessionAuth.php +++ b/src/Filters/SessionAuth.php @@ -39,8 +39,6 @@ public function before(RequestInterface $request, $arguments = null) return; } - helper('setting'); - /** @var Session $authenticator */ $authenticator = auth('session')->getAuthenticator(); diff --git a/src/Filters/TokenAuth.php b/src/Filters/TokenAuth.php index 4425c14ff..8094f8f38 100644 --- a/src/Filters/TokenAuth.php +++ b/src/Filters/TokenAuth.php @@ -39,8 +39,6 @@ public function before(RequestInterface $request, $arguments = null) return; } - helper('setting'); - /** @var AccessTokens $authenticator */ $authenticator = auth('tokens')->getAuthenticator(); diff --git a/src/Helpers/email_helper.php b/src/Helpers/email_helper.php index 0e4961790..09a99e480 100644 --- a/src/Helpers/email_helper.php +++ b/src/Helpers/email_helper.php @@ -12,8 +12,6 @@ */ function emailer(array $overrides = []): Email { - helper('setting'); - $config = [ 'userAgent' => setting('Email.userAgent'), 'protocol' => setting('Email.protocol'), diff --git a/src/Validation/ValidationRules.php b/src/Validation/ValidationRules.php index 33ab171f2..4f38a7c64 100644 --- a/src/Validation/ValidationRules.php +++ b/src/Validation/ValidationRules.php @@ -27,8 +27,6 @@ public function __construct() public function getRegistrationRules(): array { - helper('setting'); - $setting = setting('Validation.registration'); if ($setting !== null) { return $setting; @@ -59,8 +57,6 @@ public function getRegistrationRules(): array public function getLoginRules(): array { - helper('setting'); - return setting('Validation.login') ?? [ // 'username' => $this->config->usernameValidationRules, 'email' => $this->config->emailValidationRules, From e167b69794ee83fb11d8a805b83ec444c619e597 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Fri, 13 Oct 2023 02:07:51 +0330 Subject: [PATCH 021/128] fix: phpstan errors for new ver of phpstan-codeigniter --- phpstan-baseline.php | 96 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 2e880e9ff..997b5f0c8 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -27,12 +27,22 @@ 'count' => 2, 'path' => __DIR__ . '/src/Authentication/Actions/Email2FA.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/src/Authentication/Actions/Email2FA.php', +]; $ignoreErrors[] = [ 'message' => '#^Call to deprecated function random_string\\(\\)\\: The type \'basic\', \'md5\', and \'sha1\' are deprecated\\. They are not cryptographically secure\\.$#', 'count' => 1, 'path' => __DIR__ . '/src/Authentication/Actions/EmailActivator.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/src/Authentication/Actions/EmailActivator.php', +]; $ignoreErrors[] = [ 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', 'count' => 1, @@ -48,6 +58,16 @@ 'count' => 1, 'path' => __DIR__ . '/src/Authentication/Authenticators/AccessTokens.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\TokenLoginModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/AccessTokens.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/AccessTokens.php', +]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$credentials \\(array\\{token\\?\\: string\\}\\) of method CodeIgniter\\\\Shield\\\\Authentication\\\\Authenticators\\\\JWT\\:\\:attempt\\(\\) should be contravariant with parameter \\$credentials \\(array\\) of method CodeIgniter\\\\Shield\\\\Authentication\\\\AuthenticatorInterface\\:\\:attempt\\(\\)$#', 'count' => 1, @@ -58,6 +78,11 @@ 'count' => 1, 'path' => __DIR__ . '/src/Authentication/Authenticators/JWT.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\TokenLoginModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/JWT.php', +]; $ignoreErrors[] = [ 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', 'count' => 3, @@ -88,6 +113,21 @@ 'count' => 1, 'path' => __DIR__ . '/src/Authentication/Authenticators/Session.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\LoginModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/Session.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\RememberModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/Session.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/Session.php', +]; $ignoreErrors[] = [ 'message' => '#^Call to method CodeIgniter\\\\Shield\\\\Result\\:\\:isOK\\(\\) with incorrect case\\: isOk$#', 'count' => 1, @@ -159,6 +199,16 @@ 'count' => 1, 'path' => __DIR__ . '/src/Controllers/MagicLinkController.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/src/Controllers/MagicLinkController.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\LoginModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Controllers/MagicLinkController.php', +]; $ignoreErrors[] = [ 'message' => '#^Call to function assert\\(\\) with false and \'Config Auth…\' will always evaluate to false\\.$#', 'count' => 1, @@ -224,6 +274,21 @@ 'count' => 1, 'path' => __DIR__ . '/src/Entities/User.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 19, + 'path' => __DIR__ . '/src/Entities/User.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\LoginModel\\:\\:class is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/src/Entities/User.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserModel\\:\\:class is discouraged\\.$#', + 'count' => 9, + 'path' => __DIR__ . '/src/Commands/User.php', +]; $ignoreErrors[] = [ 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', 'count' => 1, @@ -306,6 +371,11 @@ 'count' => 1, 'path' => __DIR__ . '/src/Models/UserModel.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Models/UserModel.php', +]; $ignoreErrors[] = [ 'message' => '#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with \'CodeIgniter\\\\\\\\Shield\\\\\\\\Result\' and CodeIgniter\\\\Shield\\\\Result will always evaluate to true\\.$#', 'count' => 2, @@ -366,5 +436,29 @@ 'count' => 1, 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', ]; - +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\TokenLoginModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/HmacSha256.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Authentication/Authenticators/HmacSha256.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\GroupModel\\:\\:class is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/src/Authorization/Traits/Authorizable.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\PermissionModel\\:\\:class is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/src/Authorization/Traits/Authorizable.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Call to function config with Config\\\\Email\\:\\:class is discouraged\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/src/Commands/Setup.php', +]; return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; From 577eb155017c866632a76fe2a2c480333fb3a6f5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Oct 2023 04:08:25 +0330 Subject: [PATCH 022/128] chore: update .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 2d47978cb..3e4d68617 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,11 @@ phpunit vendor/ composer.lock +#------------------------- +# MkDocs +#------------------------- +site/ + #------------------------- # IDE / Development Files #------------------------- From 3eb3fac2335a67beb3d335985d74def99925b8f6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Oct 2023 04:12:58 +0330 Subject: [PATCH 023/128] add `array` for `$passwordValidators` --- docs/getting_started/concepts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting_started/concepts.md b/docs/getting_started/concepts.md index 04ad6db9f..4b94fd6e8 100644 --- a/docs/getting_started/concepts.md +++ b/docs/getting_started/concepts.md @@ -70,7 +70,7 @@ systems that are appropriate for your application. The following Validators are You can choose which validators are used in `Config\Auth::$passwordValidators`: ```php -public $passwordValidators = [ +public array $passwordValidators = [ CompositionValidator::class, NothingPersonalValidator::class, DictionaryValidator::class, From e5bfec199a01f1de81ab4569bf86a0e3dd889e28 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Oct 2023 04:37:43 +0330 Subject: [PATCH 024/128] Improved sample code for PHP file --- docs/customization/integrating_custom_view_libs.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/customization/integrating_custom_view_libs.md b/docs/customization/integrating_custom_view_libs.md index 4025de85c..93e51d3cc 100644 --- a/docs/customization/integrating_custom_view_libs.md +++ b/docs/customization/integrating_custom_view_libs.md @@ -5,6 +5,12 @@ If your application uses a different method to convert view files to HTML than C All controllers and actions use the `CodeIgniter\Shield\Traits\Viewable` trait which provides a simple `view()` method that takes the same arguments as the `view()` helper. This allows you to extend the Action or Controller and only change the single method of rendering the view, leaving all of the logic untouched so your app will not need to maintain Shield logic when it doesn't need to change it. ```php + Date: Fri, 13 Oct 2023 04:47:01 +0330 Subject: [PATCH 025/128] add `post('auth/token', '\App\Controllers\Auth\LoginController::mobileLogin'); +``` + +```php + Date: Fri, 13 Oct 2023 04:51:10 +0330 Subject: [PATCH 026/128] add type for `$authenticators ` and `$defaultAuthenticator` --- docs/references/authentication/authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/references/authentication/authentication.md b/docs/references/authentication/authentication.md index 1ade0ffed..a499fc247 100644 --- a/docs/references/authentication/authentication.md +++ b/docs/references/authentication/authentication.md @@ -12,7 +12,7 @@ You can see the [Authenticator List](../../getting_started/authenticators.md). The available authenticators are defined in `Config\Auth`: ```php -public $authenticators = [ +public array $authenticators = [ // alias => classname 'session' => Session::class, 'tokens' => AccessTokens::class, @@ -24,7 +24,7 @@ public $authenticators = [ The default authenticator is also defined in the configuration file, and uses the alias given above: ```php -public $defaultAuthenticator = 'session'; +public string $defaultAuthenticator = 'session'; ``` ## Auth Helper From 258dfb5a8241a1658ae276cf01e231267742fec1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Oct 2023 04:55:45 +0330 Subject: [PATCH 027/128] comment output resulte --- docs/references/events.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/references/events.md b/docs/references/events.md index 20344fd96..744362187 100644 --- a/docs/references/events.md +++ b/docs/references/events.md @@ -44,8 +44,7 @@ Events::on('failedLogin', function($credentials) { dd($credentials); }); -// Outputs: -['email' => 'foo@example.com']; +// Outputs: ['email' => 'foo@example.com']; ``` When the magic link login fails, the following array will be provided: From fef4ff33339a20ef2032f5be313fb37b2cc04a02 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Oct 2023 05:02:02 +0330 Subject: [PATCH 028/128] add `post('auth/jwt', '\App\Controllers\Auth\LoginController::jwtLogin'); ``` ```php +group('api', ['filter' => 'jwt'], static function ($routes) { // ... }); + $routes->get('users', 'UserController::list', ['filter' => 'jwt']); ``` From 1efc8f466dd5f5fd155ad2e616d732eeedeca589 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 13 Oct 2023 07:55:53 +0900 Subject: [PATCH 029/128] test: update DBDebug values --- tests/_support/Config/Registrar.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index 5258da8e6..ddec3d8f7 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -37,7 +37,7 @@ class Registrar 'DBDriver' => 'MySQLi', 'DBPrefix' => 'db_', 'pConnect' => false, - 'DBDebug' => (ENVIRONMENT !== 'production'), + 'DBDebug' => true, 'charset' => 'utf8', 'DBCollat' => 'utf8_general_ci', 'swapPre' => '', @@ -56,7 +56,7 @@ class Registrar 'DBDriver' => 'Postgre', 'DBPrefix' => 'db_', 'pConnect' => false, - 'DBDebug' => (ENVIRONMENT !== 'production'), + 'DBDebug' => true, 'charset' => 'utf8', 'DBCollat' => 'utf8_general_ci', 'swapPre' => '', @@ -75,7 +75,7 @@ class Registrar 'DBDriver' => 'SQLite3', 'DBPrefix' => 'db_', 'pConnect' => false, - 'DBDebug' => (ENVIRONMENT !== 'production'), + 'DBDebug' => true, 'charset' => 'utf8', 'DBCollat' => 'utf8_general_ci', 'swapPre' => '', @@ -95,7 +95,7 @@ class Registrar 'DBDriver' => 'SQLSRV', 'DBPrefix' => 'db_', 'pConnect' => false, - 'DBDebug' => (ENVIRONMENT !== 'production'), + 'DBDebug' => true, 'charset' => 'utf8', 'DBCollat' => 'utf8_general_ci', 'swapPre' => '', @@ -114,7 +114,7 @@ class Registrar 'DBDriver' => 'OCI8', 'DBPrefix' => 'db_', 'pConnect' => false, - 'DBDebug' => (ENVIRONMENT !== 'production'), + 'DBDebug' => true, 'charset' => 'utf8', 'DBCollat' => 'utf8_general_ci', 'swapPre' => '', From 5676a07f4c8e625ec174d77c7425740f9a078a24 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 13 Oct 2023 08:00:47 +0900 Subject: [PATCH 030/128] test: replace empty() with isset() --- phpstan-baseline.php | 5 ----- tests/_support/Config/Registrar.php | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 997b5f0c8..c333a0fea 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -431,11 +431,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/Unit/UserTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', -]; $ignoreErrors[] = [ 'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\TokenLoginModel\\:\\:class is discouraged\\.$#', 'count' => 1, diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index ddec3d8f7..7a08e4dc7 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -136,7 +136,7 @@ public static function Database() // Under GitHub Actions, we can set an ENV var named 'DB' // so that we can test against multiple databases. - if (($group = getenv('DB')) && ! empty(self::$dbConfig[$group])) { + if (($group = getenv('DB')) && ! isset(self::$dbConfig[$group])) { $config['tests'] = self::$dbConfig[$group]; } From ff2ea5ca30be0e35b696fcff059cb68cc92153e6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 08:57:01 +0900 Subject: [PATCH 031/128] docs: add note for removing email from registration --- docs/customization/login_identifier.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/customization/login_identifier.md b/docs/customization/login_identifier.md index 6bcec7393..cafb9c6e8 100644 --- a/docs/customization/login_identifier.md +++ b/docs/customization/login_identifier.md @@ -1,9 +1,18 @@ # Customizing Login Identifier -If your application has a need to use something other than `email` or `username`, you may specify any valid column within the `users` table that you may have added. This allows you to easily use phone numbers, employee or school IDs, etc. as the user identifier. You must implement the following steps to set this up: +If your application has a need to use something other than `email` or `username`, you may specify any valid column within the `users` table that you may have added. + +This allows you to easily use phone numbers, employee or school IDs, etc. as the user identifier. +You must implement the following steps to set this up. This only works with the Session authenticator. +!!! note + + By default, Shield requires users to register their email and password. + Further customization is required beyond the steps on this page to remove + emails from user registrations. + ## Create Migration File Create a [migration](http://codeigniter.com/user_guide/dbmgmt/migration.html) that From d6aad430fdb699407b538448321f039de9090b4f Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 10:02:16 +0900 Subject: [PATCH 032/128] docs: add note on validation rules for registration --- docs/customization/login_identifier.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/customization/login_identifier.md b/docs/customization/login_identifier.md index cafb9c6e8..db9c50319 100644 --- a/docs/customization/login_identifier.md +++ b/docs/customization/login_identifier.md @@ -48,6 +48,12 @@ public array $validFields = [ You must write new **Validation Rules** and then set them using the [Customizing Validation Rules](./validation_rules.md#login) description. +!!! note + + Not only the Validation Rules for **login**, but also the rules for + [registration](./validation_rules.md#registration) should be updated. If you do + not add the new **Validation Rules**, the new field will not be saved to the database. + ## Customize Login View 1. Change the `login` view file in the **app/Config/Auth.php** file. From a0dffd19d63551aef337439fb3cc304059aabc74 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 13:11:51 +0900 Subject: [PATCH 033/128] docs: add "Adding Attributes to Users" --- .../adding_attributes_to_users.md | 159 ++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 160 insertions(+) create mode 100644 docs/customization/adding_attributes_to_users.md diff --git a/docs/customization/adding_attributes_to_users.md b/docs/customization/adding_attributes_to_users.md new file mode 100644 index 000000000..4bc89a5b4 --- /dev/null +++ b/docs/customization/adding_attributes_to_users.md @@ -0,0 +1,159 @@ +# Adding Attributes to Users + +If you need to add new attributes like phone numbers, employee or school IDs, etc. +to users, one way is to add columns to `users` table. + +## Create Migration File + +Create a migration file to add new columns. + +You can easily create a file for it with the `spark` command: +```console +php spark make:migration AddMobileNumberToUsers +``` + +And write code to add/drop columns. + +```php + ['type' => 'VARCHAR', 'constraint' => '20', 'null' => true], + ]; + $this->forge->addColumn('users', $fields); + } + + public function down() + { + $fields = [ + 'mobile_number', + ]; + $this->forge->dropColumn('users', $fields); + } +} +``` + +## Run Migrations + +Run the migration file: + +```console +php spark migrate +``` + +And check the `users` table: + +```console +php spark db:table users +``` + +## Create UserModel + +See [Customizing User Provider](./user_provider.md). + +## Update Validation Rules + +You need to update the [validation rules](./validation_rules.md) for registration. + +If you do not add the validation rules for the new fields, the new field data will +not be saved to the database. + +Add the `$registration` property with the all validation rules for registration +in **app/Config/Validation.php**: + +```php + [ + 'label' => 'Auth.username', + 'rules' => [ + 'required', + 'max_length[30]', + 'min_length[3]', + 'regex_match[/\A[a-zA-Z0-9\.]+\z/]', + 'is_unique[users.username]', + ], + ], + 'mobile_number' => [ + 'label' => 'Mobile Number', + 'rules' => [ + 'max_length[20]', + 'min_length[10]', + 'regex_match[/\A[0-9]+\z/]', + 'is_unique[users.mobile_number]', + ], + ], + 'email' => [ + 'label' => 'Auth.email', + 'rules' => [ + 'required', + 'max_length[254]', + 'valid_email', + 'is_unique[auth_identities.secret]', + ], + ], + 'password' => [ + 'label' => 'Auth.password', + 'rules' => [ + 'required', + 'max_byte[72]', + 'strong_password[]', + ], + 'errors' => [ + 'max_byte' => 'Auth.errorPasswordTooLongBytes' + ] + ], + 'password_confirm' => [ + 'label' => 'Auth.passwordConfirm', + 'rules' => 'required|matches[password]', + ], + ]; +} +``` + +## Customize Register View + +1. Change the `register` view file in the **app/Config/Auth.php** file. + + ```php + public array $views = [ + // ... + 'register' => '\App\Views\Shield\register', + // ... + ]; + ``` + +2. Copy file **vendor/codeigniter4/shield/src/Views/register.php** to **app/Views/Shield/register.php**. +3. Customize the registration form to add the new fields. + + ```php + +
+ + +
+ ``` diff --git a/mkdocs.yml b/mkdocs.yml index b68ce068e..24808cccf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -111,6 +111,7 @@ nav: - customization/redirect_urls.md - customization/validation_rules.md - customization/user_provider.md + - customization/adding_attributes_to_users.md - customization/extending_controllers.md - customization/integrating_custom_view_libs.md - customization/login_identifier.md From 97cf0c094ad6e6f37305a31423542bea8e82959a Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 09:26:06 +0900 Subject: [PATCH 034/128] docs: add/update doc comments --- src/Auth.php | 4 +++- src/Authentication/Authentication.php | 14 +++++++------- src/Helpers/auth_helper.php | 3 +-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Auth.php b/src/Auth.php index 32b163db0..9191af89e 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -12,6 +12,8 @@ use CodeIgniter\Shield\Models\UserModel; /** + * Facade for Authentication + * * @method Result attempt(array $credentials) * @method Result check(array $credentials) * @method bool checkAction(string $token, string $type) [Session] @@ -148,7 +150,7 @@ public function getProvider(): UserModel /** * Provide magic function-access to Authenticators to save use - * from repeating code here, and to allow them have their + * from repeating code here, and to allow them to have their * own, additional, features on top of the required ones, * like "remember-me" functionality. * diff --git a/src/Authentication/Authentication.php b/src/Authentication/Authentication.php index b6fb7eb5c..015357e44 100644 --- a/src/Authentication/Authentication.php +++ b/src/Authentication/Authentication.php @@ -7,6 +7,9 @@ use CodeIgniter\Shield\Config\Auth as AuthConfig; use CodeIgniter\Shield\Models\UserModel; +/** + * Factory for Authenticators. + */ class Authentication { /** @@ -26,13 +29,10 @@ public function __construct(AuthConfig $config) } /** - * Returns an instance of the specified Authenticator. + * Creates and returns the shared instance of the specified Authenticator. * - * You can pass 'default' as the Authenticator and it - * will return an instance of the first Authenticator specified - * in the Auth config file. - * - * @param string|null $alias Authenticator alias + * @param string|null $alias Authenticator alias. Passing `null` returns the + * default authenticator. * * @throws AuthenticationException */ @@ -61,7 +61,7 @@ public function factory(?string $alias = null): AuthenticatorInterface } /** - * Sets the User provider to use + * Sets the User Provider to use. * * @return $this */ diff --git a/src/Helpers/auth_helper.php b/src/Helpers/auth_helper.php index e126d2c81..3396ffb55 100644 --- a/src/Helpers/auth_helper.php +++ b/src/Helpers/auth_helper.php @@ -22,8 +22,7 @@ function auth(?string $alias = null): Auth if (! function_exists('user_id')) { /** - * Returns the ID for the current logged in user. - * Note: For \CodeIgniter\Shield\Entities\User this will always return an int. + * Returns the ID for the current logged-in user. * * @return int|string|null */ From 543a36ac7ca428cc4dc3facb12921d254ea2faf4 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 09:29:39 +0900 Subject: [PATCH 035/128] refactor: rename variable name --- src/Auth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Auth.php b/src/Auth.php index 9191af89e..655b373a4 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -160,10 +160,10 @@ public function getProvider(): UserModel */ public function __call(string $method, array $args) { - $authenticate = $this->authenticate->factory($this->alias); + $authenticator = $this->authenticate->factory($this->alias); - if (method_exists($authenticate, $method)) { - return $authenticate->{$method}(...$args); + if (method_exists($authenticator, $method)) { + return $authenticator->{$method}(...$args); } } } From 97bda91b40d06d0087bb7243e27fa3cdf44db1f9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 09:43:06 +0900 Subject: [PATCH 036/128] refactor!: defer instantiation of Authentication --- src/Auth.php | 23 ++++++++++++++++++++--- src/Config/Services.php | 5 +---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Auth.php b/src/Auth.php index 655b373a4..07fa55365 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -8,6 +8,7 @@ use CodeIgniter\Shield\Authentication\Authentication; use CodeIgniter\Shield\Authentication\AuthenticationException; use CodeIgniter\Shield\Authentication\AuthenticatorInterface; +use CodeIgniter\Shield\Config\Auth as AuthConfig; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Models\UserModel; @@ -32,7 +33,7 @@ class Auth */ public const SHIELD_VERSION = '1.0.0-beta.7'; - protected Authentication $authenticate; + protected ?Authentication $authenticate = null; /** * The Authenticator alias to use for this request. @@ -41,9 +42,19 @@ class Auth protected ?UserModel $userProvider = null; - public function __construct(Authentication $authenticate) + protected function ensureAuthentication(): void { - $this->authenticate = $authenticate->setProvider($this->getProvider()); + if ($this->authenticate !== null) { + return; + } + + /** @var AuthConfig $config */ + $config = config('Auth'); + + $authenticate = new Authentication($config); + $authenticate->setProvider($this->getProvider()); + + $this->authenticate = $authenticate; } /** @@ -65,6 +76,8 @@ public function setAuthenticator(?string $alias = null): self */ public function getAuthenticator(): AuthenticatorInterface { + $this->ensureAuthentication(); + return $this->authenticate ->factory($this->alias); } @@ -93,6 +106,8 @@ public function id() public function authenticate(array $credentials): Result { + $this->ensureAuthentication(); + return $this->authenticate ->factory($this->alias) ->attempt($credentials); @@ -160,6 +175,8 @@ public function getProvider(): UserModel */ public function __call(string $method, array $args) { + $this->ensureAuthentication(); + $authenticator = $this->authenticate->factory($this->alias); if (method_exists($authenticator, $method)) { diff --git a/src/Config/Services.php b/src/Config/Services.php index 42960ff7d..b1fa2f465 100644 --- a/src/Config/Services.php +++ b/src/Config/Services.php @@ -6,7 +6,6 @@ use CodeIgniter\Config\BaseService; use CodeIgniter\Shield\Auth; -use CodeIgniter\Shield\Authentication\Authentication; use CodeIgniter\Shield\Authentication\JWTManager; use CodeIgniter\Shield\Authentication\Passwords; @@ -21,9 +20,7 @@ public static function auth(bool $getShared = true): Auth return self::getSharedInstance('auth'); } - $config = config('Auth'); - - return new Auth(new Authentication($config)); + return new Auth(); } /** From 5e6faf38f0eca4235e0ef3d9503fbb0bd9c17ce6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 17:49:50 +0900 Subject: [PATCH 037/128] refactor!: add $config property --- src/Auth.php | 18 +++++++++--------- src/Config/Services.php | 6 +++++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Auth.php b/src/Auth.php index 07fa55365..5d13c41e3 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -33,6 +33,7 @@ class Auth */ public const SHIELD_VERSION = '1.0.0-beta.7'; + protected AuthConfig $config; protected ?Authentication $authenticate = null; /** @@ -42,16 +43,18 @@ class Auth protected ?UserModel $userProvider = null; + public function __construct(AuthConfig $config) + { + $this->config = $config; + } + protected function ensureAuthentication(): void { if ($this->authenticate !== null) { return; } - /** @var AuthConfig $config */ - $config = config('Auth'); - - $authenticate = new Authentication($config); + $authenticate = new Authentication($this->config); $authenticate->setProvider($this->getProvider()); $this->authenticate = $authenticate; @@ -150,14 +153,11 @@ public function getProvider(): UserModel return $this->userProvider; } - /** @var \CodeIgniter\Shield\Config\Auth $config */ - $config = config('Auth'); - - if (! property_exists($config, 'userProvider')) { + if (! property_exists($this->config, 'userProvider')) { throw AuthenticationException::forUnknownUserProvider(); } - $className = $config->userProvider; + $className = $this->config->userProvider; $this->userProvider = new $className(); return $this->userProvider; diff --git a/src/Config/Services.php b/src/Config/Services.php index b1fa2f465..aa922f834 100644 --- a/src/Config/Services.php +++ b/src/Config/Services.php @@ -8,6 +8,7 @@ use CodeIgniter\Shield\Auth; use CodeIgniter\Shield\Authentication\JWTManager; use CodeIgniter\Shield\Authentication\Passwords; +use CodeIgniter\Shield\Config\Auth as AuthConfig; class Services extends BaseService { @@ -20,7 +21,10 @@ public static function auth(bool $getShared = true): Auth return self::getSharedInstance('auth'); } - return new Auth(); + /** @var AuthConfig $config */ + $config = config('Auth'); + + return new Auth($config); } /** From c12177a83aa0dcdce6bfbde79441d9dbe8a9cb3d Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 17:53:42 +0900 Subject: [PATCH 038/128] refactor: remove unneeded property check --- phpstan-baseline.php | 5 ----- src/Auth.php | 4 ---- 2 files changed, 9 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index c333a0fea..58462ed12 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1,11 +1,6 @@ '#^Call to function property_exists\\(\\) with CodeIgniter\\\\Shield\\\\Config\\\\Auth and \'userProvider\' will always evaluate to true\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/src/Auth.php', -]; $ignoreErrors[] = [ 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', 'count' => 1, diff --git a/src/Auth.php b/src/Auth.php index 5d13c41e3..54bda2acd 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -153,10 +153,6 @@ public function getProvider(): UserModel return $this->userProvider; } - if (! property_exists($this->config, 'userProvider')) { - throw AuthenticationException::forUnknownUserProvider(); - } - $className = $this->config->userProvider; $this->userProvider = new $className(); From 7d4bd5c97e17a2b251fda2d2b0edd9b4ae6dd847 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 16 Oct 2023 17:58:33 +0900 Subject: [PATCH 039/128] refactor: replace empty() --- phpstan-baseline.php | 10 ---------- src/Auth.php | 8 ++++---- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 58462ed12..92a1ea564 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1,16 +1,6 @@ '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/src/Auth.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Only booleans are allowed in a ternary operator condition, CodeIgniter\\\\Shield\\\\Entities\\\\User\\|null given\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/src/Auth.php', -]; $ignoreErrors[] = [ 'message' => '#^Call to deprecated function random_string\\(\\)\\: The type \'basic\', \'md5\', and \'sha1\' are deprecated\\. They are not cryptographically secure\\.$#', diff --git a/src/Auth.php b/src/Auth.php index 54bda2acd..3f8d65aac 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -67,7 +67,7 @@ protected function ensureAuthentication(): void */ public function setAuthenticator(?string $alias = null): self { - if (! empty($alias)) { + if ($alias !== null) { $this->alias = $alias; } @@ -102,9 +102,9 @@ public function user(): ?User */ public function id() { - return ($user = $this->user()) - ? $user->id - : null; + $user = $this->user(); + + return ($user !== null) ? $user->id : null; } public function authenticate(array $credentials): Result From 997023bce2d6d7044fd99a222121434b90762a0a Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 17 Oct 2023 11:47:15 +0900 Subject: [PATCH 040/128] docs: use Config\Auth::$tables --- .../adding_attributes_to_users.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/customization/adding_attributes_to_users.md b/docs/customization/adding_attributes_to_users.md index 4bc89a5b4..1a95497aa 100644 --- a/docs/customization/adding_attributes_to_users.md +++ b/docs/customization/adding_attributes_to_users.md @@ -19,16 +19,31 @@ And write code to add/drop columns. namespace App\Database\Migrations; +use CodeIgniter\Database\Forge; use CodeIgniter\Database\Migration; class AddMobileNumberToUsers extends Migration { + /** + * @var string[] + */ + private array $tables; + + public function __construct(?Forge $forge = null) + { + parent::__construct($forge); + + /** @var \Config\Auth $authConfig */ + $authConfig = config('Auth'); + $this->tables = $authConfig->tables; + } + public function up() { $fields = [ 'mobile_number' => ['type' => 'VARCHAR', 'constraint' => '20', 'null' => true], ]; - $this->forge->addColumn('users', $fields); + $this->forge->addColumn($this->tables['users'], $fields); } public function down() @@ -36,7 +51,7 @@ class AddMobileNumberToUsers extends Migration $fields = [ 'mobile_number', ]; - $this->forge->dropColumn('users', $fields); + $this->forge->dropColumn($this->tables['users'], $fields); } } ``` From 4c4658c115b4c28377b2af74ffab2d80cfec646b Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 17 Oct 2023 11:48:18 +0900 Subject: [PATCH 041/128] docs: add missing "," --- docs/customization/adding_attributes_to_users.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customization/adding_attributes_to_users.md b/docs/customization/adding_attributes_to_users.md index 1a95497aa..05530c6f3 100644 --- a/docs/customization/adding_attributes_to_users.md +++ b/docs/customization/adding_attributes_to_users.md @@ -139,7 +139,7 @@ class Validation extends BaseConfig 'strong_password[]', ], 'errors' => [ - 'max_byte' => 'Auth.errorPasswordTooLongBytes' + 'max_byte' => 'Auth.errorPasswordTooLongBytes', ] ], 'password_confirm' => [ From 27f9983d0fcd50468dc9275c6f8e19ccf5b62764 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 17 Oct 2023 09:45:54 +0330 Subject: [PATCH 042/128] fix date localized-plugin and refactor action --- .github/workflows/docs.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e6e623ce8..b596d4a9a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -9,11 +9,18 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Python + uses: actions/setup-python@v4 with: python-version: 3.x - - run: pip3 install mkdocs-material - - run: pip3 install mkdocs-git-revision-date-localized-plugin - - run: pip3 install mkdocs-redirects - - run: mkdocs gh-deploy --force + - name: Install Dependencies + run: | + pip3 install mkdocs-material + pip3 install mkdocs-git-revision-date-localized-plugin + pip3 install mkdocs-redirects + - name: Publish Shiled Documentation + run: mkdocs gh-deploy --force From b1d32a6f99b08712b044603ab4156945837b0fae Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 16 Aug 2023 16:30:04 +0330 Subject: [PATCH 043/128] feat: add `after_permission_denied` and `after_group_denied` --- src/Config/Auth.php | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/Config/Auth.php b/src/Config/Auth.php index e7ad04189..6be7cdd33 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -65,10 +65,12 @@ class Auth extends BaseConfig * to apply any logic you may need. */ public array $redirects = [ - 'register' => '/', - 'login' => '/', - 'logout' => 'login', - 'force_reset' => '/', + 'register' => '/', + 'login' => '/', + 'logout' => 'login', + 'force_reset' => '/', + 'after_permission_denied' => '/', + 'after_group_denied' => '/', ]; /** @@ -475,6 +477,28 @@ public function forcePasswordResetRedirect(): string return $this->getUrl($url); } + /** + * Returns the URL the user should be redirected to + * if permission denied. + */ + public function afterPermissionDeniedRedirect(): string + { + $url = setting('Auth.redirects')['after_permission_denied']; + + return $this->getUrl($url); + } + + /** + * Returns the URL the user should be redirected to + * if group denied. + */ + public function afterGroupDeniedRedirect(): string + { + $url = setting('Auth.redirects')['after_group_denied']; + + return $this->getUrl($url); + } + /** * Accepts a string which can be an absolute URL or * a named route or just a URI path, and returns the From 10660b6eab5c05e1525f701f6381c19fc54ea420 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 16 Aug 2023 16:40:22 +0330 Subject: [PATCH 044/128] feat: add filter name to filter class --- src/Filters/GroupFilter.php | 2 ++ src/Filters/PermissionFilter.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Filters/GroupFilter.php b/src/Filters/GroupFilter.php index 22e73ab4c..77df70fb9 100644 --- a/src/Filters/GroupFilter.php +++ b/src/Filters/GroupFilter.php @@ -9,6 +9,8 @@ */ class GroupFilter extends AbstractAuthFilter { + protected string $filterName = 'group'; + /** * Ensures the user is logged in and a member of one or * more groups as specified in the filter. diff --git a/src/Filters/PermissionFilter.php b/src/Filters/PermissionFilter.php index 486910818..0de74e3ba 100644 --- a/src/Filters/PermissionFilter.php +++ b/src/Filters/PermissionFilter.php @@ -9,6 +9,8 @@ */ class PermissionFilter extends AbstractAuthFilter { + protected string $filterName = 'permission'; + /** * Ensures the user is logged in and has one or more * of the permissions as specified in the filter. From bf6c733ba19fdeccc2d582cad848bfd4a863107e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 16 Aug 2023 16:42:04 +0330 Subject: [PATCH 045/128] feat: update AbstractAuthFilter --- src/Filters/AbstractAuthFilter.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Filters/AbstractAuthFilter.php b/src/Filters/AbstractAuthFilter.php index 750f5993a..aad91e569 100644 --- a/src/Filters/AbstractAuthFilter.php +++ b/src/Filters/AbstractAuthFilter.php @@ -9,6 +9,7 @@ use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; +use CodeIgniter\Shield\Config\Auth; /** * Group Authorization Filter. @@ -43,8 +44,15 @@ public function before(RequestInterface $request, $arguments = null) return; } - // Otherwise, we'll just send them to the home page. - return redirect()->to('/')->with('error', lang('Auth.notEnoughPrivilege')); + switch ($this->filterName) { + case 'group': + return redirect()->to(config(Auth::class)->afterGroupDeniedRedirect()) + ->with('error', lang('Auth.notEnoughPrivilege')); + + case 'permission': + return redirect()->to(config(Auth::class)->afterPermissionDeniedRedirect()) + ->with('error', lang('Auth.notEnoughPrivilege')); + } } /** From 056e8be9e244a95bf13524427c0afa891fa6c402 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 16 Aug 2023 17:23:50 +0330 Subject: [PATCH 046/128] tests: fix phpunit test --- tests/Authentication/Filters/GroupFilterTest.php | 5 +++-- tests/Authentication/Filters/PermissionFilterTest.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/Authentication/Filters/GroupFilterTest.php b/tests/Authentication/Filters/GroupFilterTest.php index 2690eeaff..fd3dfca93 100644 --- a/tests/Authentication/Filters/GroupFilterTest.php +++ b/tests/Authentication/Filters/GroupFilterTest.php @@ -4,6 +4,7 @@ namespace Tests\Authentication\Filters; +use CodeIgniter\Shield\Config\Auth; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Filters\GroupFilter; use CodeIgniter\Shield\Models\UserModel; @@ -69,8 +70,8 @@ public function testFilterIncorrectGroupNoPrevious(): void ->get('protected-route'); // Should redirect to home page since previous_url is not set - $result->assertRedirectTo(site_url('/')); + $result->assertRedirectTo(config(Auth::class)->afterGroupDeniedRedirect()); // Should have error message - $result->assertSessionHas('error'); + $result->assertSessionHas('error', lang('Auth.notEnoughPrivilege')); } } diff --git a/tests/Authentication/Filters/PermissionFilterTest.php b/tests/Authentication/Filters/PermissionFilterTest.php index 140bde35b..d441c49a5 100644 --- a/tests/Authentication/Filters/PermissionFilterTest.php +++ b/tests/Authentication/Filters/PermissionFilterTest.php @@ -4,6 +4,7 @@ namespace Tests\Authentication\Filters; +use CodeIgniter\Shield\Config\Auth; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Filters\PermissionFilter; use CodeIgniter\Shield\Models\UserModel; @@ -69,8 +70,8 @@ public function testFilterIncorrectGroupNoPrevious(): void ->get('protected-route'); // Should redirect to home page since previous_url is not set - $result->assertRedirectTo(site_url('/')); + $result->assertRedirectTo(config(Auth::class)->afterPermissionDeniedRedirect()); // Should have error message - $result->assertSessionHas('error'); + $result->assertSessionHas('error', lang('Auth.notEnoughPrivilege')); } } From 1eb0dce5511e6f0b2e6a93edbda910f24ec0e736 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 16 Aug 2023 17:48:29 +0330 Subject: [PATCH 047/128] fix: rector/phpstan error --- src/Filters/AbstractAuthFilter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Filters/AbstractAuthFilter.php b/src/Filters/AbstractAuthFilter.php index aad91e569..e290abdfc 100644 --- a/src/Filters/AbstractAuthFilter.php +++ b/src/Filters/AbstractAuthFilter.php @@ -7,7 +7,6 @@ use CodeIgniter\Filters\FilterInterface; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; -use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\Shield\Config\Auth; @@ -16,6 +15,8 @@ */ abstract class AbstractAuthFilter implements FilterInterface { + protected string $filterName; + /** * Ensures the user is logged in and a member of one or * more groups as specified in the filter. @@ -58,8 +59,7 @@ public function before(RequestInterface $request, $arguments = null) /** * We don't have anything to do here. * - * @param Response|ResponseInterface $response - * @param array|null $arguments + * @param array|null $arguments */ public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void { From e7f5c3eb80265d5bff534fcb1ec83c4189c71b1b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Thu, 17 Aug 2023 11:15:49 +0330 Subject: [PATCH 048/128] refctor: rename methods and keys --- src/Config/Auth.php | 20 +++++++++---------- .../Filters/GroupFilterTest.php | 2 +- .../Filters/PermissionFilterTest.php | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Config/Auth.php b/src/Config/Auth.php index 6be7cdd33..1b9bad087 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -65,12 +65,12 @@ class Auth extends BaseConfig * to apply any logic you may need. */ public array $redirects = [ - 'register' => '/', - 'login' => '/', - 'logout' => 'login', - 'force_reset' => '/', - 'after_permission_denied' => '/', - 'after_group_denied' => '/', + 'register' => '/', + 'login' => '/', + 'logout' => 'login', + 'force_reset' => '/', + 'permission_denied' => '/', + 'group_denied' => '/', ]; /** @@ -481,9 +481,9 @@ public function forcePasswordResetRedirect(): string * Returns the URL the user should be redirected to * if permission denied. */ - public function afterPermissionDeniedRedirect(): string + public function permissionDeniedRedirect(): string { - $url = setting('Auth.redirects')['after_permission_denied']; + $url = setting('Auth.redirects')['permission_denied']; return $this->getUrl($url); } @@ -492,9 +492,9 @@ public function afterPermissionDeniedRedirect(): string * Returns the URL the user should be redirected to * if group denied. */ - public function afterGroupDeniedRedirect(): string + public function groupDeniedRedirect(): string { - $url = setting('Auth.redirects')['after_group_denied']; + $url = setting('Auth.redirects')['group_denied']; return $this->getUrl($url); } diff --git a/tests/Authentication/Filters/GroupFilterTest.php b/tests/Authentication/Filters/GroupFilterTest.php index fd3dfca93..ef6475ab3 100644 --- a/tests/Authentication/Filters/GroupFilterTest.php +++ b/tests/Authentication/Filters/GroupFilterTest.php @@ -70,7 +70,7 @@ public function testFilterIncorrectGroupNoPrevious(): void ->get('protected-route'); // Should redirect to home page since previous_url is not set - $result->assertRedirectTo(config(Auth::class)->afterGroupDeniedRedirect()); + $result->assertRedirectTo(config(Auth::class)->groupDeniedRedirect()); // Should have error message $result->assertSessionHas('error', lang('Auth.notEnoughPrivilege')); } diff --git a/tests/Authentication/Filters/PermissionFilterTest.php b/tests/Authentication/Filters/PermissionFilterTest.php index d441c49a5..d075282f5 100644 --- a/tests/Authentication/Filters/PermissionFilterTest.php +++ b/tests/Authentication/Filters/PermissionFilterTest.php @@ -70,7 +70,7 @@ public function testFilterIncorrectGroupNoPrevious(): void ->get('protected-route'); // Should redirect to home page since previous_url is not set - $result->assertRedirectTo(config(Auth::class)->afterPermissionDeniedRedirect()); + $result->assertRedirectTo(config(Auth::class)->permissionDeniedRedirect()); // Should have error message $result->assertSessionHas('error', lang('Auth.notEnoughPrivilege')); } From a327eae80e0dc77d2d430f8659fbb29618f4cf9e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Thu, 17 Aug 2023 11:19:19 +0330 Subject: [PATCH 049/128] refactor: add `redirectToDeniedUrl()` for able inherit from `AbstractAuthFilter` --- src/Filters/AbstractAuthFilter.php | 15 +++------------ src/Filters/GroupFilter.php | 15 +++++++++++++-- src/Filters/PermissionFilter.php | 15 +++++++++++++-- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/Filters/AbstractAuthFilter.php b/src/Filters/AbstractAuthFilter.php index e290abdfc..a66d1183a 100644 --- a/src/Filters/AbstractAuthFilter.php +++ b/src/Filters/AbstractAuthFilter.php @@ -8,15 +8,12 @@ use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use CodeIgniter\Shield\Config\Auth; /** * Group Authorization Filter. */ abstract class AbstractAuthFilter implements FilterInterface { - protected string $filterName; - /** * Ensures the user is logged in and a member of one or * more groups as specified in the filter. @@ -45,15 +42,7 @@ public function before(RequestInterface $request, $arguments = null) return; } - switch ($this->filterName) { - case 'group': - return redirect()->to(config(Auth::class)->afterGroupDeniedRedirect()) - ->with('error', lang('Auth.notEnoughPrivilege')); - - case 'permission': - return redirect()->to(config(Auth::class)->afterPermissionDeniedRedirect()) - ->with('error', lang('Auth.notEnoughPrivilege')); - } + return $this->redirectToDeniedUrl(); } /** @@ -67,4 +56,6 @@ public function after(RequestInterface $request, ResponseInterface $response, $a } abstract protected function isAuthorized(array $arguments): bool; + + abstract protected function redirectToDeniedUrl(): RedirectResponse; } diff --git a/src/Filters/GroupFilter.php b/src/Filters/GroupFilter.php index 77df70fb9..5741cab4f 100644 --- a/src/Filters/GroupFilter.php +++ b/src/Filters/GroupFilter.php @@ -4,13 +4,14 @@ namespace CodeIgniter\Shield\Filters; +use CodeIgniter\HTTP\RedirectResponse; +use CodeIgniter\Shield\Config\Auth; + /** * Group Authorization Filter. */ class GroupFilter extends AbstractAuthFilter { - protected string $filterName = 'group'; - /** * Ensures the user is logged in and a member of one or * more groups as specified in the filter. @@ -19,4 +20,14 @@ protected function isAuthorized(array $arguments): bool { return auth()->user()->inGroup(...$arguments); } + + /** + * If there is no necessary access to the group, + * it will redirect the user to the set URL with an error message. + */ + protected function redirectToDeniedUrl(): RedirectResponse + { + return redirect()->to(config(Auth::class)->groupDeniedRedirect()) + ->with('error', lang('Auth.notEnoughPrivilege')); + } } diff --git a/src/Filters/PermissionFilter.php b/src/Filters/PermissionFilter.php index 0de74e3ba..fad88de90 100644 --- a/src/Filters/PermissionFilter.php +++ b/src/Filters/PermissionFilter.php @@ -4,13 +4,14 @@ namespace CodeIgniter\Shield\Filters; +use CodeIgniter\HTTP\RedirectResponse; +use CodeIgniter\Shield\Config\Auth; + /** * Permission Authorization Filter. */ class PermissionFilter extends AbstractAuthFilter { - protected string $filterName = 'permission'; - /** * Ensures the user is logged in and has one or more * of the permissions as specified in the filter. @@ -25,4 +26,14 @@ protected function isAuthorized(array $arguments): bool return false; } + + /** + * If there is no necessary access to the permission, + * it will redirect the user to the set URL with an error message. + */ + protected function redirectToDeniedUrl(): RedirectResponse + { + return redirect()->to(config(Auth::class)->permissionDeniedRedirect()) + ->with('error', lang('Auth.notEnoughPrivilege')); + } } From c37823e149a3035d0a0c36f577ed7c84b71a0e25 Mon Sep 17 00:00:00 2001 From: kikukeii Date: Tue, 17 Oct 2023 19:37:17 +0700 Subject: [PATCH 050/128] add translation ID --- src/Language/id/Auth.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Language/id/Auth.php b/src/Language/id/Auth.php index 0c5e1533c..a2b8f6246 100644 --- a/src/Language/id/Auth.php +++ b/src/Language/id/Auth.php @@ -30,7 +30,7 @@ 'password' => 'Kata Sandi', 'passwordConfirm' => 'Kata Sandi (lagi)', 'haveAccount' => 'Sudah punya akun?', - 'token' => '(To be translated) Token', + 'token' => 'Token', // Buttons 'confirm' => 'Konfirmasi', @@ -52,7 +52,7 @@ 'magicLinkExpired' => 'Maaf, tautan sudah tidak berlaku.', 'checkYourEmail' => 'Periksa email Anda!', 'magicLinkDetails' => 'Kami baru saja mengirimi Anda email dengan tautan Masuk di dalamnya. Ini hanya berlaku selama {0} menit.', - 'magicLinkDisabled' => '(To be translated) Use of MagicLink is currently not allowed.', + 'magicLinkDisabled' => 'Penggunaan MagicLink saat ini tidak diperbolehkan.', 'successLogout' => 'Anda telah berhasil keluar.', 'backToLogin' => 'Kembali ke masuk', @@ -71,7 +71,7 @@ 'errorPasswordTooLongBytes' => 'Panjang kata sandi tidak boleh lebih dari {param} byte.', 'passwordChangeSuccess' => 'Kata sandi berhasil diubah', 'userDoesNotExist' => 'Kata sandi tidak diubah. User tidak ditemukan', - 'resetTokenExpired' => 'Maaf, token setel ulang Anda sudah habis waktu.', + 'resetTokenExpired' => 'Maaf, token setel ulang Anda sudah kedaluwarsa.', // Email Globals 'emailInfo' => 'Beberapa informasi tentang seseorang:', @@ -81,7 +81,7 @@ // 2FA 'email2FATitle' => 'Otentikasi Dua Faktor', - 'confirmEmailAddress' => 'Alamat email konfirmasi Anda.', + 'confirmEmailAddress' => 'Konfirmasi alamat email Anda.', 'emailEnterCode' => 'Konfirmasi email Anda', 'emailConfirmCode' => 'Masukkan kode 6 digit yang baru saja kami kirimkan ke alamat email Anda.', 'email2FASubject' => 'Kode otentikasi Anda', From 0ba826370b92a0211ead7947a5fb589adfa3f828 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 17 Oct 2023 16:08:21 +0330 Subject: [PATCH 051/128] docs: add how to properly upgrade for `$permission_denied`&`$group_denied` --- UPGRADING.md | 22 +++++++++++++++++++ src/Filters/GroupFilter.php | 3 +-- src/Filters/PermissionFilter.php | 3 +-- .../Filters/GroupFilterTest.php | 3 +-- .../Filters/PermissionFilterTest.php | 3 +-- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index bfcef207c..ec989e3d2 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -25,6 +25,28 @@ following steps will be done. $this->helpers = array_merge($this->helpers, ['setting']); ``` +#### Config\Auth + +The following items have been added. Copy the properties in **src/Config/Auth.php**. + +- `$permission_denied` and `$group_denied` are added to `Config\Auth::$redirects`. +- `permissionDeniedRedirect()` and `groupDeniedRedirect()` are added. + +#### Fix Custom Filter If extends `AbstractAuthFilter` +If you have written a custom filter that extends `AbstractAuthFilter`. Now you need to add and implement method `redirectToDeniedUrl()` to your custom filter. +The following example is related to the above explanation for **group** filter. +```php +/** + * If there is no necessary access to the group, + * it will redirect the user to the set URL with an error message. + */ +protected function redirectToDeniedUrl(): RedirectResponse +{ + return redirect()->to(config('Auth')->groupDeniedRedirect()) + ->with('error', lang('Auth.notEnoughPrivilege')); +} +``` + ## Version 1.0.0-beta.6 to 1.0.0-beta.7 ### The minimum CodeIgniter version diff --git a/src/Filters/GroupFilter.php b/src/Filters/GroupFilter.php index 5741cab4f..b80acc15c 100644 --- a/src/Filters/GroupFilter.php +++ b/src/Filters/GroupFilter.php @@ -5,7 +5,6 @@ namespace CodeIgniter\Shield\Filters; use CodeIgniter\HTTP\RedirectResponse; -use CodeIgniter\Shield\Config\Auth; /** * Group Authorization Filter. @@ -27,7 +26,7 @@ protected function isAuthorized(array $arguments): bool */ protected function redirectToDeniedUrl(): RedirectResponse { - return redirect()->to(config(Auth::class)->groupDeniedRedirect()) + return redirect()->to(config('Auth')->groupDeniedRedirect()) ->with('error', lang('Auth.notEnoughPrivilege')); } } diff --git a/src/Filters/PermissionFilter.php b/src/Filters/PermissionFilter.php index fad88de90..6d2ba19c1 100644 --- a/src/Filters/PermissionFilter.php +++ b/src/Filters/PermissionFilter.php @@ -5,7 +5,6 @@ namespace CodeIgniter\Shield\Filters; use CodeIgniter\HTTP\RedirectResponse; -use CodeIgniter\Shield\Config\Auth; /** * Permission Authorization Filter. @@ -33,7 +32,7 @@ protected function isAuthorized(array $arguments): bool */ protected function redirectToDeniedUrl(): RedirectResponse { - return redirect()->to(config(Auth::class)->permissionDeniedRedirect()) + return redirect()->to(config('Auth')->permissionDeniedRedirect()) ->with('error', lang('Auth.notEnoughPrivilege')); } } diff --git a/tests/Authentication/Filters/GroupFilterTest.php b/tests/Authentication/Filters/GroupFilterTest.php index ef6475ab3..ddfb423b1 100644 --- a/tests/Authentication/Filters/GroupFilterTest.php +++ b/tests/Authentication/Filters/GroupFilterTest.php @@ -4,7 +4,6 @@ namespace Tests\Authentication\Filters; -use CodeIgniter\Shield\Config\Auth; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Filters\GroupFilter; use CodeIgniter\Shield\Models\UserModel; @@ -70,7 +69,7 @@ public function testFilterIncorrectGroupNoPrevious(): void ->get('protected-route'); // Should redirect to home page since previous_url is not set - $result->assertRedirectTo(config(Auth::class)->groupDeniedRedirect()); + $result->assertRedirectTo(config('Auth')->groupDeniedRedirect()); // Should have error message $result->assertSessionHas('error', lang('Auth.notEnoughPrivilege')); } diff --git a/tests/Authentication/Filters/PermissionFilterTest.php b/tests/Authentication/Filters/PermissionFilterTest.php index d075282f5..d4580017b 100644 --- a/tests/Authentication/Filters/PermissionFilterTest.php +++ b/tests/Authentication/Filters/PermissionFilterTest.php @@ -4,7 +4,6 @@ namespace Tests\Authentication\Filters; -use CodeIgniter\Shield\Config\Auth; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Filters\PermissionFilter; use CodeIgniter\Shield\Models\UserModel; @@ -70,7 +69,7 @@ public function testFilterIncorrectGroupNoPrevious(): void ->get('protected-route'); // Should redirect to home page since previous_url is not set - $result->assertRedirectTo(config(Auth::class)->permissionDeniedRedirect()); + $result->assertRedirectTo(config('Auth')->permissionDeniedRedirect()); // Should have error message $result->assertSessionHas('error', lang('Auth.notEnoughPrivilege')); } From afa30957623a6d9a95d66a7913e40e1d43c4e5b5 Mon Sep 17 00:00:00 2001 From: kikukeii Date: Tue, 17 Oct 2023 21:16:13 +0700 Subject: [PATCH 052/128] add Auth.token in excludedLocaleKeyTranslations --- tests/Language/IndonesianTranslationTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Language/IndonesianTranslationTest.php b/tests/Language/IndonesianTranslationTest.php index 5e23c1792..31a244ca1 100644 --- a/tests/Language/IndonesianTranslationTest.php +++ b/tests/Language/IndonesianTranslationTest.php @@ -18,4 +18,7 @@ */ final class IndonesianTranslationTest extends AbstractTranslationTestCase { + protected array $excludedLocaleKeyTranslations = [ + 'Auth.token', + ]; } From a8287bbb955a568e819bbedae9099e0bcbc09f19 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 18 Oct 2023 17:25:13 +0900 Subject: [PATCH 053/128] fix: replace url_is() url_is() checks the URI path. If the path is changed, it will not work. --- src/Filters/AbstractAuthFilter.php | 2 +- src/Filters/SessionAuth.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Filters/AbstractAuthFilter.php b/src/Filters/AbstractAuthFilter.php index 750f5993a..5da0031da 100644 --- a/src/Filters/AbstractAuthFilter.php +++ b/src/Filters/AbstractAuthFilter.php @@ -31,7 +31,7 @@ public function before(RequestInterface $request, $arguments = null) if (! auth()->loggedIn()) { // Set the entrance url to redirect a user after successful login - if (! url_is('login')) { + if (uri_string() !== route_to('login')) { $session = session(); $session->setTempdata('beforeLoginUrl', current_url(), 300); } diff --git a/src/Filters/SessionAuth.php b/src/Filters/SessionAuth.php index 18ec1a571..97e85c98b 100644 --- a/src/Filters/SessionAuth.php +++ b/src/Filters/SessionAuth.php @@ -75,7 +75,7 @@ public function before(RequestInterface $request, $arguments = null) ->with('error', $authenticator->getPendingMessage()); } - if (! url_is('login')) { + if (uri_string() !== route_to('login')) { $session = session(); $session->setTempdata('beforeLoginUrl', current_url(), 300); } From 6d5683a0cc70514130dc0e147f9b0f0a92647ea4 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 18 Oct 2023 14:14:02 +0330 Subject: [PATCH 054/128] docs: apply suggestions from code review Co-authored-by: kenjis --- UPGRADING.md | 9 +++++---- src/Filters/AbstractAuthFilter.php | 7 +++++++ src/Filters/GroupFilter.php | 3 +-- src/Filters/PermissionFilter.php | 3 +-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index ec989e3d2..d63032446 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -29,16 +29,17 @@ following steps will be done. The following items have been added. Copy the properties in **src/Config/Auth.php**. -- `$permission_denied` and `$group_denied` are added to `Config\Auth::$redirects`. +- `permission_denied` and `group_denied` are added to `Config\Auth::$redirects`. - `permissionDeniedRedirect()` and `groupDeniedRedirect()` are added. #### Fix Custom Filter If extends `AbstractAuthFilter` -If you have written a custom filter that extends `AbstractAuthFilter`. Now you need to add and implement method `redirectToDeniedUrl()` to your custom filter. + +If you have written a custom filter that extends `AbstractAuthFilter`, now you need to add and implement the `redirectToDeniedUrl()` method to your custom filter. The following example is related to the above explanation for **group** filter. + ```php /** - * If there is no necessary access to the group, - * it will redirect the user to the set URL with an error message. + * If the user does not belong to the group, redirect to the configured URL with an error message. */ protected function redirectToDeniedUrl(): RedirectResponse { diff --git a/src/Filters/AbstractAuthFilter.php b/src/Filters/AbstractAuthFilter.php index a66d1183a..d4a38a379 100644 --- a/src/Filters/AbstractAuthFilter.php +++ b/src/Filters/AbstractAuthFilter.php @@ -55,7 +55,14 @@ public function after(RequestInterface $request, ResponseInterface $response, $a // Nothing required } + /** + * Ensures the user is logged in and has one or more + * of the permissions as specified in the filter. + */ abstract protected function isAuthorized(array $arguments): bool; + /** + * Returns redirect response when the user does not have access authorizations. + */ abstract protected function redirectToDeniedUrl(): RedirectResponse; } diff --git a/src/Filters/GroupFilter.php b/src/Filters/GroupFilter.php index b80acc15c..7c0a33b16 100644 --- a/src/Filters/GroupFilter.php +++ b/src/Filters/GroupFilter.php @@ -21,8 +21,7 @@ protected function isAuthorized(array $arguments): bool } /** - * If there is no necessary access to the group, - * it will redirect the user to the set URL with an error message. + * If the user does not belong to the group, redirect to the configured URL with an error message. */ protected function redirectToDeniedUrl(): RedirectResponse { diff --git a/src/Filters/PermissionFilter.php b/src/Filters/PermissionFilter.php index 6d2ba19c1..e20f7a23d 100644 --- a/src/Filters/PermissionFilter.php +++ b/src/Filters/PermissionFilter.php @@ -27,8 +27,7 @@ protected function isAuthorized(array $arguments): bool } /** - * If there is no necessary access to the permission, - * it will redirect the user to the set URL with an error message. + * If the user does not have the permission, redirect to the configured URL with an error message. */ protected function redirectToDeniedUrl(): RedirectResponse { From cc07d8e0704551d36cea13d218d1b44799e0fa39 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 18 Oct 2023 15:22:32 +0330 Subject: [PATCH 055/128] update defaulte value `$hashCost` to 12 --- src/Config/Auth.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Config/Auth.php b/src/Config/Auth.php index e7ad04189..6a1bd8d6b 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -354,14 +354,14 @@ class Auth extends BaseConfig * -------------------------------------------------------------------- * The BCRYPT method of hashing allows you to define the "cost" * or number of iterations made, whenever a password hash is created. - * This defaults to a value of 10 which is an acceptable number. + * This defaults to a value of 12 which is an acceptable number. * However, depending on the security needs of your application * and the power of your hardware, you might want to increase the * cost. This makes the hashing process takes longer. * * Valid range is between 4 - 31. */ - public int $hashCost = 10; + public int $hashCost = 12; /** * If you need to support passwords saved in versions prior to Shield v1.0.0-beta.4. From 05826bcecbe051a23254e4d4051cbaf17c507c24 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 18 Oct 2023 15:40:21 +0330 Subject: [PATCH 056/128] tests: set hashCost=13 for fix test --- tests/Unit/PasswordsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/PasswordsTest.php b/tests/Unit/PasswordsTest.php index 7398fc533..fc892013b 100644 --- a/tests/Unit/PasswordsTest.php +++ b/tests/Unit/PasswordsTest.php @@ -52,7 +52,7 @@ public function testHash(): string public function testNeedsRehashTakesCareOptions(string $hashedPassword): void { $config = new AuthConfig(); - $config->hashCost = 12; + $config->hashCost = 13; $passwords = new Passwords($config); $result = $passwords->needsRehash($hashedPassword); From 1546bec713fcd55096661b715f4be76d2fd6ba35 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 19 Oct 2023 00:39:17 +0330 Subject: [PATCH 057/128] docs: use h3 for title Co-authored-by: kenjis --- UPGRADING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index d63032446..6a558a894 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -32,7 +32,7 @@ The following items have been added. Copy the properties in **src/Config/Auth.ph - `permission_denied` and `group_denied` are added to `Config\Auth::$redirects`. - `permissionDeniedRedirect()` and `groupDeniedRedirect()` are added. -#### Fix Custom Filter If extends `AbstractAuthFilter` +### Fix Custom Filter If extends `AbstractAuthFilter` If you have written a custom filter that extends `AbstractAuthFilter`, now you need to add and implement the `redirectToDeniedUrl()` method to your custom filter. The following example is related to the above explanation for **group** filter. From 193b10df78e89c93c2d9930e654307b10c4b4cab Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Thu, 19 Oct 2023 04:59:37 +0330 Subject: [PATCH 058/128] docs: remove unneeded / from routes --- docs/guides/api_hmac_keys.md | 2 +- docs/guides/api_tokens.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index f64825d0b..b0a565537 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -24,7 +24,7 @@ The `generateHmacToken()` method requires a name for the token. These are free s the user/device the token was generated from/for, like 'Johns MacBook Air'. ```php -$routes->get('/hmac/token', static function () { +$routes->get('hmac/token', static function () { $token = auth()->user()->generateHmacToken(service('request')->getVar('token_name')); return json_encode(['key' => $token->secret, 'secretKey' => $token->secret2]); diff --git a/docs/guides/api_tokens.md b/docs/guides/api_tokens.md index 60f238b50..a2ce6c2d4 100644 --- a/docs/guides/api_tokens.md +++ b/docs/guides/api_tokens.md @@ -11,7 +11,7 @@ Tokens are issued with the `generateAccessToken()` method on the user. This retu The `generateAccessToken()` method requires a name for the token. These are free strings and are often used to identify the user/device the token was generated from, like 'Johns MacBook Air'. ```php -$routes->get('/access/token', static function() { +$routes->get('access/token', static function() { $token = auth()->user()->generateAccessToken(service('request')->getVar('token_name')); return json_encode(['token' => $token->raw_token]); From 231bdf8359f18f534bd7708292ac8c15e7c5332a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 19 Oct 2023 09:48:47 +0330 Subject: [PATCH 059/128] docs: fix email rule for mobileLogin --- docs/guides/mobile_apps.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/guides/mobile_apps.md b/docs/guides/mobile_apps.md index 30db76926..9f1af569f 100644 --- a/docs/guides/mobile_apps.md +++ b/docs/guides/mobile_apps.md @@ -28,10 +28,7 @@ class LoginController extends BaseController { // Validate credentials $rules = setting('Validation.login') ?? [ - 'email' => [ - 'label' => 'Auth.email', - 'rules' => config('Auth')->emailValidationRules, - ], + 'email' => config('Auth')->emailValidationRules, 'password' => [ 'label' => 'Auth.password', 'rules' => 'required', From f969893cdd9c0c3e71ea540997fc0c0711bc6e58 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Thu, 19 Oct 2023 21:35:17 +0330 Subject: [PATCH 060/128] docs: add logout to session except list --- docs/customization/route_config.md | 2 +- docs/quick_start_guide/using_session_auth.md | 2 +- docs/references/controller_filters.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/customization/route_config.md b/docs/customization/route_config.md index 46d1c6597..af56af08f 100644 --- a/docs/customization/route_config.md +++ b/docs/customization/route_config.md @@ -57,7 +57,7 @@ update the paths for `except`: public $globals = [ 'before' => [ // ... - 'session' => ['except' => ['*/login*', '*/register', '*/auth/a/*']], + 'session' => ['except' => ['*/login*', '*/register', '*/auth/a/*', 'logout']], ], // ... ]; diff --git a/docs/quick_start_guide/using_session_auth.md b/docs/quick_start_guide/using_session_auth.md index 645d2a1b2..43e3fe80f 100644 --- a/docs/quick_start_guide/using_session_auth.md +++ b/docs/quick_start_guide/using_session_auth.md @@ -100,7 +100,7 @@ If you want to limit all routes (e.g. `localhost:8080/admin`, `localhost:8080/pa public $globals = [ 'before' => [ // ... - 'session' => ['except' => ['login*', 'register', 'auth/a/*']], + 'session' => ['except' => ['login*', 'register', 'auth/a/*', 'logout']], ], // ... ]; diff --git a/docs/references/controller_filters.md b/docs/references/controller_filters.md index 88dfe4c1a..7b88cc264 100644 --- a/docs/references/controller_filters.md +++ b/docs/references/controller_filters.md @@ -47,7 +47,7 @@ If you want to limit all routes (e.g. `localhost:8080/admin`, `localhost:8080/pa public $globals = [ 'before' => [ // ... - 'session' => ['except' => ['login*', 'register', 'auth/a/*']], + 'session' => ['except' => ['login*', 'register', 'auth/a/*', 'logout']], ], // ... ]; @@ -102,7 +102,7 @@ Then the global `before` filter for `session` should look like so: public $globals = [ 'before' => [ // ... - 'session' => ['except' => ['accounts/login*', 'accounts/register', 'accounts/auth/a/*']] + 'session' => ['except' => ['accounts/login*', 'accounts/register', 'accounts/auth/a/*', 'accounts/logout']] ] ] ``` From eef12aebd6964219261227454373244ca3f7ee13 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Oct 2023 03:54:57 +0330 Subject: [PATCH 061/128] fix logout route for `{locale}` --- docs/customization/route_config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customization/route_config.md b/docs/customization/route_config.md index af56af08f..09a15da09 100644 --- a/docs/customization/route_config.md +++ b/docs/customization/route_config.md @@ -57,7 +57,7 @@ update the paths for `except`: public $globals = [ 'before' => [ // ... - 'session' => ['except' => ['*/login*', '*/register', '*/auth/a/*', 'logout']], + 'session' => ['except' => ['*/login*', '*/register', '*/auth/a/*', '*/logout']], ], // ... ]; From 485592b9daa0e54509c642dff48137fc6fc72996 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Sat, 21 Oct 2023 09:19:43 +0330 Subject: [PATCH 062/128] happy phpstan for `forget()` --- src/Auth.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Auth.php b/src/Auth.php index 32b163db0..c2bd95344 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -15,6 +15,7 @@ * @method Result attempt(array $credentials) * @method Result check(array $credentials) * @method bool checkAction(string $token, string $type) [Session] + * @method void forget(?User $user = null) [Session] * @method User|null getUser() * @method bool loggedIn() * @method bool login(User $user) From 4a388576b04b1f8f3826f9f11dd1f6d691c8dc71 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Sun, 22 Oct 2023 03:57:50 +0330 Subject: [PATCH 063/128] phpstan: fix phpstan error --- phpstan-baseline.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 92a1ea564..f66ecb7d9 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -436,9 +436,4 @@ 'count' => 2, 'path' => __DIR__ . '/src/Authorization/Traits/Authorizable.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Call to function config with Config\\\\Email\\:\\:class is discouraged\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/src/Commands/Setup.php', -]; return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; From edbe65917492c026ca9ebfdfd5128178b8760906 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Sun, 22 Oct 2023 06:12:43 +0330 Subject: [PATCH 064/128] style: add copyright to all files with linter --- .php-cs-fixer.dist.php | 15 ++++++++++++++- rector.php | 9 +++++++++ src/Auth.php | 9 +++++++++ src/Authentication/Actions/ActionInterface.php | 9 +++++++++ src/Authentication/Actions/Email2FA.php | 9 +++++++++ src/Authentication/Actions/EmailActivator.php | 9 +++++++++ src/Authentication/Authentication.php | 9 +++++++++ src/Authentication/AuthenticationException.php | 9 +++++++++ src/Authentication/AuthenticatorInterface.php | 9 +++++++++ .../Authenticators/AccessTokens.php | 9 +++++++++ src/Authentication/Authenticators/HmacSha256.php | 9 +++++++++ src/Authentication/Authenticators/JWT.php | 9 +++++++++ src/Authentication/Authenticators/Session.php | 9 +++++++++ .../JWT/Adapters/FirebaseAdapter.php | 9 +++++++++ .../JWT/Exceptions/InvalidTokenException.php | 9 +++++++++ src/Authentication/JWT/JWSAdapterInterface.php | 9 +++++++++ src/Authentication/JWT/JWSDecoder.php | 9 +++++++++ src/Authentication/JWT/JWSEncoder.php | 9 +++++++++ src/Authentication/JWTManager.php | 9 +++++++++ src/Authentication/Passwords.php | 9 +++++++++ src/Authentication/Passwords/BaseValidator.php | 9 +++++++++ .../Passwords/CompositionValidator.php | 9 +++++++++ .../Passwords/DictionaryValidator.php | 9 +++++++++ .../Passwords/NothingPersonalValidator.php | 9 +++++++++ src/Authentication/Passwords/PwnedValidator.php | 9 +++++++++ src/Authentication/Passwords/ValidationRules.php | 9 +++++++++ .../Passwords/ValidatorInterface.php | 9 +++++++++ src/Authentication/Traits/HasAccessTokens.php | 9 +++++++++ src/Authentication/Traits/HasHmacTokens.php | 9 +++++++++ src/Authorization/AuthorizationException.php | 9 +++++++++ src/Authorization/Groups.php | 9 +++++++++ src/Authorization/Traits/Authorizable.php | 9 +++++++++ src/Collectors/Auth.php | 9 +++++++++ src/Commands/BaseCommand.php | 9 +++++++++ src/Commands/Exceptions/BadInputException.php | 9 +++++++++ src/Commands/Exceptions/CancelException.php | 9 +++++++++ src/Commands/Generators/UserModelGenerator.php | 9 +++++++++ src/Commands/Setup.php | 9 +++++++++ src/Commands/Setup/ContentReplacer.php | 9 +++++++++ src/Commands/User.php | 9 +++++++++ src/Commands/Utils/InputOutput.php | 9 +++++++++ src/Config/Auth.php | 9 +++++++++ src/Config/AuthGroups.php | 9 +++++++++ src/Config/AuthJWT.php | 9 +++++++++ src/Config/AuthRoutes.php | 9 +++++++++ src/Config/AuthToken.php | 9 +++++++++ src/Config/Registrar.php | 9 +++++++++ src/Config/Services.php | 9 +++++++++ src/Controllers/ActionController.php | 9 +++++++++ src/Controllers/LoginController.php | 9 +++++++++ src/Controllers/MagicLinkController.php | 9 +++++++++ src/Controllers/RegisterController.php | 9 +++++++++ .../2020-12-28-223112_create_auth_tables.php | 9 +++++++++ src/Entities/AccessToken.php | 9 +++++++++ src/Entities/Cast/IntBoolCast.php | 9 +++++++++ src/Entities/Entity.php | 9 +++++++++ src/Entities/Group.php | 9 +++++++++ src/Entities/Login.php | 9 +++++++++ src/Entities/User.php | 9 +++++++++ src/Entities/UserIdentity.php | 9 +++++++++ src/Exceptions/BaseException.php | 9 +++++++++ src/Exceptions/GroupException.php | 9 +++++++++ src/Exceptions/InvalidArgumentException.php | 9 +++++++++ src/Exceptions/LogicException.php | 9 +++++++++ src/Exceptions/PermissionException.php | 9 +++++++++ src/Exceptions/RuntimeException.php | 9 +++++++++ src/Exceptions/SecurityException.php | 9 +++++++++ src/Exceptions/UserNotFoundException.php | 9 +++++++++ src/Exceptions/ValidationException.php | 9 +++++++++ src/Filters/AbstractAuthFilter.php | 9 +++++++++ src/Filters/AuthRates.php | 9 +++++++++ src/Filters/ChainAuth.php | 9 +++++++++ src/Filters/ForcePasswordResetFilter.php | 9 +++++++++ src/Filters/GroupFilter.php | 9 +++++++++ src/Filters/HmacAuth.php | 9 +++++++++ src/Filters/JWTAuth.php | 9 +++++++++ src/Filters/PermissionFilter.php | 9 +++++++++ src/Filters/SessionAuth.php | 9 +++++++++ src/Filters/TokenAuth.php | 9 +++++++++ src/Helpers/auth_helper.php | 9 +++++++++ src/Helpers/email_helper.php | 9 +++++++++ src/Language/ar/Auth.php | 9 +++++++++ src/Language/bg/Auth.php | 9 +++++++++ src/Language/de/Auth.php | 9 +++++++++ src/Language/en/Auth.php | 9 +++++++++ src/Language/es/Auth.php | 9 +++++++++ src/Language/fa/Auth.php | 9 +++++++++ src/Language/fr/Auth.php | 9 +++++++++ src/Language/id/Auth.php | 9 +++++++++ src/Language/it/Auth.php | 9 +++++++++ src/Language/ja/Auth.php | 9 +++++++++ src/Language/lt/Auth.php | 9 +++++++++ src/Language/pt-BR/Auth.php | 9 +++++++++ src/Language/pt/Auth.php | 9 +++++++++ src/Language/sk/Auth.php | 9 +++++++++ src/Language/sr/Auth.php | 9 +++++++++ src/Language/sv-SE/Auth.php | 9 +++++++++ src/Language/tr/Auth.php | 9 +++++++++ src/Language/uk/Auth.php | 9 +++++++++ src/Models/BaseModel.php | 9 +++++++++ src/Models/CheckQueryReturnTrait.php | 9 +++++++++ src/Models/DatabaseException.php | 9 +++++++++ src/Models/GroupModel.php | 9 +++++++++ src/Models/LoginModel.php | 9 +++++++++ src/Models/PermissionModel.php | 9 +++++++++ src/Models/RememberModel.php | 9 +++++++++ src/Models/TokenLoginModel.php | 9 +++++++++ src/Models/UserIdentityModel.php | 9 +++++++++ src/Models/UserModel.php | 9 +++++++++ src/Result.php | 9 +++++++++ src/Test/AuthenticationTesting.php | 9 +++++++++ src/Test/MockInputOutput.php | 9 +++++++++ src/Traits/Activatable.php | 9 +++++++++ src/Traits/Bannable.php | 9 +++++++++ src/Traits/Resettable.php | 9 +++++++++ src/Traits/Viewable.php | 9 +++++++++ src/Validation/ValidationRules.php | 9 +++++++++ tests/Authentication/AccessTokenTest.php | 9 +++++++++ tests/Authentication/AuthHelperTest.php | 9 +++++++++ tests/Authentication/AuthTest.php | 9 +++++++++ tests/Authentication/AuthenticationTest.php | 9 +++++++++ .../AccessTokenAuthenticatorTest.php | 9 +++++++++ .../Authenticators/HmacAuthenticatorTest.php | 9 +++++++++ .../Authenticators/JWTAuthenticatorTest.php | 9 +++++++++ .../Authenticators/SessionAuthenticatorTest.php | 9 +++++++++ .../Filters/AbstractFilterTestCase.php | 9 +++++++++ tests/Authentication/Filters/ChainFilterTest.php | 9 +++++++++ tests/Authentication/Filters/GroupFilterTest.php | 9 +++++++++ tests/Authentication/Filters/HmacFilterTest.php | 9 +++++++++ tests/Authentication/Filters/JWTFilterTest.php | 9 +++++++++ .../Filters/PermissionFilterTest.php | 9 +++++++++ .../Authentication/Filters/SessionFilterTest.php | 9 +++++++++ tests/Authentication/Filters/TokenFilterTest.php | 9 +++++++++ tests/Authentication/ForcePasswordResetTest.php | 9 +++++++++ tests/Authentication/HasAccessTokensTest.php | 9 +++++++++ tests/Authentication/HasHmacTokensTest.php | 9 +++++++++ tests/Authentication/MagicLinkTest.php | 9 +++++++++ tests/Authorization/AuthorizableTest.php | 9 +++++++++ tests/Authorization/GroupTest.php | 9 +++++++++ tests/Authorization/GroupsTest.php | 9 +++++++++ tests/Collectors/AuthTest.php | 9 +++++++++ tests/Commands/Setup/ContentReplacerTest.php | 9 +++++++++ tests/Commands/SetupTest.php | 9 +++++++++ tests/Commands/UserModelGeneratorTest.php | 9 +++++++++ tests/Commands/UserTest.php | 9 +++++++++ tests/Controllers/ActionsTest.php | 9 +++++++++ tests/Controllers/LoginTest.php | 9 +++++++++ tests/Controllers/MagicLinkTest.php | 9 +++++++++ tests/Controllers/RegisterTest.php | 9 +++++++++ tests/Language/AbstractTranslationTestCase.php | 2 +- tests/Language/ArabicTranslationTest.php | 2 +- tests/Language/BrazilianTranslationTest.php | 9 +++++++++ tests/Language/BulgarianTranslationTest.php | 2 +- tests/Language/FarsiTranslationTest.php | 2 +- tests/Language/FrenchTranslationTest.php | 2 +- tests/Language/GermanTranslationTest.php | 2 +- tests/Language/IndonesianTranslationTest.php | 2 +- tests/Language/ItalianTranslationTest.php | 9 +++++++++ tests/Language/JapaneseTranslationTest.php | 2 +- tests/Language/LithuanianTranslationTest.php | 2 +- tests/Language/PortugueseTranslationTest.php | 9 +++++++++ tests/Language/SerbianTranslationTest.php | 2 +- tests/Language/SlovakTranslationTest.php | 2 +- tests/Language/SpanishTranslationTest.php | 2 +- tests/Language/SwedishTranslationTest.php | 2 +- tests/Language/TurkishTranslationTest.php | 2 +- tests/Language/UkrainianTranslationTest.php | 2 +- tests/Unit/AuthRoutesTest.php | 9 +++++++++ .../JWT/Adapters/FirebaseAdapaterTest.php | 9 +++++++++ tests/Unit/Authentication/JWT/JWTManagerTest.php | 9 +++++++++ tests/Unit/CompositionValidatorTest.php | 9 +++++++++ tests/Unit/DictionaryValidatorTest.php | 9 +++++++++ tests/Unit/EmailActivatorTest.php | 9 +++++++++ tests/Unit/FilterInCliTest.php | 9 +++++++++ tests/Unit/LoginModelTest.php | 9 +++++++++ tests/Unit/NothingPersonalValidatorTest.php | 9 +++++++++ tests/Unit/PasswordsTest.php | 9 +++++++++ tests/Unit/PwnedValidatorTest.php | 9 +++++++++ tests/Unit/UserIdentityModelTest.php | 9 +++++++++ tests/Unit/UserModelTest.php | 9 +++++++++ tests/Unit/UserTest.php | 9 +++++++++ tests/_support/Config/Registrar.php | 2 +- tests/_support/DatabaseTestCase.php | 9 +++++++++ tests/_support/FakeUser.php | 9 +++++++++ tests/_support/TestCase.php | 9 +++++++++ 185 files changed, 1542 insertions(+), 17 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 5636649d5..0e986f3c2 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + use CodeIgniter\CodingStandard\CodeIgniter4; use Nexus\CsConfig\Factory; use PhpCsFixer\Finder; @@ -28,4 +37,8 @@ 'cacheFile' => 'build/.php-cs-fixer.cache', ]; -return Factory::create(new CodeIgniter4(), $overrides, $options)->forProjects(); +return Factory::create(new CodeIgniter4(), $overrides, $options)->forLibrary( + 'CodeIgniter Shield', + 'CodeIgniter Foundation', + 'admin@codeigniter.com' +); diff --git a/rector.php b/rector.php index 76a02ab28..04b2685d8 100644 --- a/rector.php +++ b/rector.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + use Rector\CodeQuality\Rector\BooleanAnd\SimplifyEmptyArrayCheckRector; use Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector; use Rector\CodeQuality\Rector\Expression\InlineIfToExplicitIfRector; diff --git a/src/Auth.php b/src/Auth.php index 28b2b0f0b..6a84c5cd7 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield; use CodeIgniter\Router\RouteCollection; diff --git a/src/Authentication/Actions/ActionInterface.php b/src/Authentication/Actions/ActionInterface.php index 73b625b06..b2025bde3 100644 --- a/src/Authentication/Actions/ActionInterface.php +++ b/src/Authentication/Actions/ActionInterface.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Actions; use CodeIgniter\HTTP\IncomingRequest; diff --git a/src/Authentication/Actions/Email2FA.php b/src/Authentication/Actions/Email2FA.php index 54883b7be..2d9cf2bd3 100644 --- a/src/Authentication/Actions/Email2FA.php +++ b/src/Authentication/Actions/Email2FA.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Actions; use CodeIgniter\HTTP\IncomingRequest; diff --git a/src/Authentication/Actions/EmailActivator.php b/src/Authentication/Actions/EmailActivator.php index 5017798f0..f91316cc3 100644 --- a/src/Authentication/Actions/EmailActivator.php +++ b/src/Authentication/Actions/EmailActivator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Actions; use CodeIgniter\Exceptions\PageNotFoundException; diff --git a/src/Authentication/Authentication.php b/src/Authentication/Authentication.php index 015357e44..9e2dd2d75 100644 --- a/src/Authentication/Authentication.php +++ b/src/Authentication/Authentication.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication; use CodeIgniter\Shield\Config\Auth as AuthConfig; diff --git a/src/Authentication/AuthenticationException.php b/src/Authentication/AuthenticationException.php index ced1ff2e4..982166b70 100644 --- a/src/Authentication/AuthenticationException.php +++ b/src/Authentication/AuthenticationException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication; use CodeIgniter\HTTP\Exceptions\HTTPException; diff --git a/src/Authentication/AuthenticatorInterface.php b/src/Authentication/AuthenticatorInterface.php index acd6c8b61..b39591f14 100644 --- a/src/Authentication/AuthenticatorInterface.php +++ b/src/Authentication/AuthenticatorInterface.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication; use CodeIgniter\Shield\Entities\User; diff --git a/src/Authentication/Authenticators/AccessTokens.php b/src/Authentication/Authenticators/AccessTokens.php index f8e2e9254..86824ed61 100644 --- a/src/Authentication/Authenticators/AccessTokens.php +++ b/src/Authentication/Authenticators/AccessTokens.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Authenticators; use CodeIgniter\HTTP\IncomingRequest; diff --git a/src/Authentication/Authenticators/HmacSha256.php b/src/Authentication/Authenticators/HmacSha256.php index 697c7a447..42a6cdc31 100644 --- a/src/Authentication/Authenticators/HmacSha256.php +++ b/src/Authentication/Authenticators/HmacSha256.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Authenticators; use CodeIgniter\HTTP\IncomingRequest; diff --git a/src/Authentication/Authenticators/JWT.php b/src/Authentication/Authenticators/JWT.php index 09590275c..d962f86f2 100644 --- a/src/Authentication/Authenticators/JWT.php +++ b/src/Authentication/Authenticators/JWT.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Authenticators; use CodeIgniter\HTTP\IncomingRequest; diff --git a/src/Authentication/Authenticators/Session.php b/src/Authentication/Authenticators/Session.php index e15fba3ae..98e4a29a0 100644 --- a/src/Authentication/Authenticators/Session.php +++ b/src/Authentication/Authenticators/Session.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Authenticators; use CodeIgniter\Config\Factories; diff --git a/src/Authentication/JWT/Adapters/FirebaseAdapter.php b/src/Authentication/JWT/Adapters/FirebaseAdapter.php index 70141393d..0c7bb95ef 100644 --- a/src/Authentication/JWT/Adapters/FirebaseAdapter.php +++ b/src/Authentication/JWT/Adapters/FirebaseAdapter.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\JWT\Adapters; use CodeIgniter\Shield\Authentication\JWT\Exceptions\InvalidTokenException; diff --git a/src/Authentication/JWT/Exceptions/InvalidTokenException.php b/src/Authentication/JWT/Exceptions/InvalidTokenException.php index b3f9b5569..033855970 100644 --- a/src/Authentication/JWT/Exceptions/InvalidTokenException.php +++ b/src/Authentication/JWT/Exceptions/InvalidTokenException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\JWT\Exceptions; use CodeIgniter\Shield\Exceptions\ValidationException; diff --git a/src/Authentication/JWT/JWSAdapterInterface.php b/src/Authentication/JWT/JWSAdapterInterface.php index 991fdabba..7305a018f 100644 --- a/src/Authentication/JWT/JWSAdapterInterface.php +++ b/src/Authentication/JWT/JWSAdapterInterface.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\JWT; use stdClass; diff --git a/src/Authentication/JWT/JWSDecoder.php b/src/Authentication/JWT/JWSDecoder.php index 3ba548ac6..145eb5623 100644 --- a/src/Authentication/JWT/JWSDecoder.php +++ b/src/Authentication/JWT/JWSDecoder.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\JWT; use CodeIgniter\Shield\Authentication\JWT\Adapters\FirebaseAdapter; diff --git a/src/Authentication/JWT/JWSEncoder.php b/src/Authentication/JWT/JWSEncoder.php index e426e7eda..458aeec01 100644 --- a/src/Authentication/JWT/JWSEncoder.php +++ b/src/Authentication/JWT/JWSEncoder.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\JWT; use CodeIgniter\I18n\Time; diff --git a/src/Authentication/JWTManager.php b/src/Authentication/JWTManager.php index 11f1dba93..ad638bc3a 100644 --- a/src/Authentication/JWTManager.php +++ b/src/Authentication/JWTManager.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication; use CodeIgniter\I18n\Time; diff --git a/src/Authentication/Passwords.php b/src/Authentication/Passwords.php index 3a5b7b041..994c192a8 100644 --- a/src/Authentication/Passwords.php +++ b/src/Authentication/Passwords.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication; use CodeIgniter\Shield\Authentication\Passwords\ValidatorInterface; diff --git a/src/Authentication/Passwords/BaseValidator.php b/src/Authentication/Passwords/BaseValidator.php index 6f7bfe4cf..64e7a3eac 100644 --- a/src/Authentication/Passwords/BaseValidator.php +++ b/src/Authentication/Passwords/BaseValidator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\Shield\Config\Auth as AuthConfig; diff --git a/src/Authentication/Passwords/CompositionValidator.php b/src/Authentication/Passwords/CompositionValidator.php index dec8f34af..49ae3738a 100644 --- a/src/Authentication/Passwords/CompositionValidator.php +++ b/src/Authentication/Passwords/CompositionValidator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\Shield\Authentication\AuthenticationException; diff --git a/src/Authentication/Passwords/DictionaryValidator.php b/src/Authentication/Passwords/DictionaryValidator.php index b7cb6add4..8394428a8 100644 --- a/src/Authentication/Passwords/DictionaryValidator.php +++ b/src/Authentication/Passwords/DictionaryValidator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\Shield\Entities\User; diff --git a/src/Authentication/Passwords/NothingPersonalValidator.php b/src/Authentication/Passwords/NothingPersonalValidator.php index 14a8c587b..90112bf2d 100644 --- a/src/Authentication/Passwords/NothingPersonalValidator.php +++ b/src/Authentication/Passwords/NothingPersonalValidator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\Shield\Entities\User; diff --git a/src/Authentication/Passwords/PwnedValidator.php b/src/Authentication/Passwords/PwnedValidator.php index a68e92e99..ff933fe49 100644 --- a/src/Authentication/Passwords/PwnedValidator.php +++ b/src/Authentication/Passwords/PwnedValidator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\Config\Services; diff --git a/src/Authentication/Passwords/ValidationRules.php b/src/Authentication/Passwords/ValidationRules.php index 2ad59c87d..ca6f07638 100644 --- a/src/Authentication/Passwords/ValidationRules.php +++ b/src/Authentication/Passwords/ValidationRules.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\HTTP\IncomingRequest; diff --git a/src/Authentication/Passwords/ValidatorInterface.php b/src/Authentication/Passwords/ValidatorInterface.php index af187ffa7..5fc3845be 100644 --- a/src/Authentication/Passwords/ValidatorInterface.php +++ b/src/Authentication/Passwords/ValidatorInterface.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Passwords; use CodeIgniter\Shield\Entities\User; diff --git a/src/Authentication/Traits/HasAccessTokens.php b/src/Authentication/Traits/HasAccessTokens.php index e19aecaa2..f2fd7e283 100644 --- a/src/Authentication/Traits/HasAccessTokens.php +++ b/src/Authentication/Traits/HasAccessTokens.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Traits; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/src/Authentication/Traits/HasHmacTokens.php b/src/Authentication/Traits/HasHmacTokens.php index 435a19bd2..a9db79303 100644 --- a/src/Authentication/Traits/HasHmacTokens.php +++ b/src/Authentication/Traits/HasHmacTokens.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\Traits; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/src/Authorization/AuthorizationException.php b/src/Authorization/AuthorizationException.php index fa85b44b6..bdc5f793b 100644 --- a/src/Authorization/AuthorizationException.php +++ b/src/Authorization/AuthorizationException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authorization; use CodeIgniter\Shield\Exceptions\RuntimeException; diff --git a/src/Authorization/Groups.php b/src/Authorization/Groups.php index ae223fb44..eb76920c9 100644 --- a/src/Authorization/Groups.php +++ b/src/Authorization/Groups.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authorization; use CodeIgniter\Shield\Entities\Group; diff --git a/src/Authorization/Traits/Authorizable.php b/src/Authorization/Traits/Authorizable.php index eb57cd788..4167341b2 100644 --- a/src/Authorization/Traits/Authorizable.php +++ b/src/Authorization/Traits/Authorizable.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authorization\Traits; use CodeIgniter\I18n\Time; diff --git a/src/Collectors/Auth.php b/src/Collectors/Auth.php index f265b2e58..a1824d4bd 100644 --- a/src/Collectors/Auth.php +++ b/src/Collectors/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Collectors; use CodeIgniter\Debug\Toolbar\Collectors\BaseCollector; diff --git a/src/Commands/BaseCommand.php b/src/Commands/BaseCommand.php index 2b30856f0..f7ad9962d 100644 --- a/src/Commands/BaseCommand.php +++ b/src/Commands/BaseCommand.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands; use CodeIgniter\CLI\BaseCommand as FrameworkBaseCommand; diff --git a/src/Commands/Exceptions/BadInputException.php b/src/Commands/Exceptions/BadInputException.php index 0316394e1..35d6ec898 100644 --- a/src/Commands/Exceptions/BadInputException.php +++ b/src/Commands/Exceptions/BadInputException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands\Exceptions; use CodeIgniter\Shield\Exceptions\RuntimeException; diff --git a/src/Commands/Exceptions/CancelException.php b/src/Commands/Exceptions/CancelException.php index 44ac64067..6eb126673 100644 --- a/src/Commands/Exceptions/CancelException.php +++ b/src/Commands/Exceptions/CancelException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands\Exceptions; use CodeIgniter\Shield\Exceptions\RuntimeException; diff --git a/src/Commands/Generators/UserModelGenerator.php b/src/Commands/Generators/UserModelGenerator.php index 3a9b63590..605a05cea 100644 --- a/src/Commands/Generators/UserModelGenerator.php +++ b/src/Commands/Generators/UserModelGenerator.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands\Generators; use CodeIgniter\CLI\BaseCommand; diff --git a/src/Commands/Setup.php b/src/Commands/Setup.php index f4b14657e..0f14a6e26 100644 --- a/src/Commands/Setup.php +++ b/src/Commands/Setup.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands; use CodeIgniter\CLI\CLI; diff --git a/src/Commands/Setup/ContentReplacer.php b/src/Commands/Setup/ContentReplacer.php index e603e7a11..20061e763 100644 --- a/src/Commands/Setup/ContentReplacer.php +++ b/src/Commands/Setup/ContentReplacer.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands\Setup; class ContentReplacer diff --git a/src/Commands/User.php b/src/Commands/User.php index e5d42daa9..c5ef8513c 100644 --- a/src/Commands/User.php +++ b/src/Commands/User.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands; use CodeIgniter\Shield\Authentication\Authenticators\Session; diff --git a/src/Commands/Utils/InputOutput.php b/src/Commands/Utils/InputOutput.php index 5bbfb4474..c6a3ceabc 100644 --- a/src/Commands/Utils/InputOutput.php +++ b/src/Commands/Utils/InputOutput.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands\Utils; use CodeIgniter\CLI\CLI; diff --git a/src/Config/Auth.php b/src/Config/Auth.php index 40b57c2ae..e711fb3e2 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseConfig; diff --git a/src/Config/AuthGroups.php b/src/Config/AuthGroups.php index 3b92aee82..9bc24580a 100644 --- a/src/Config/AuthGroups.php +++ b/src/Config/AuthGroups.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseConfig; diff --git a/src/Config/AuthJWT.php b/src/Config/AuthJWT.php index adf9bf404..2db352f93 100644 --- a/src/Config/AuthJWT.php +++ b/src/Config/AuthJWT.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseConfig; diff --git a/src/Config/AuthRoutes.php b/src/Config/AuthRoutes.php index 0428bbcb3..141978565 100644 --- a/src/Config/AuthRoutes.php +++ b/src/Config/AuthRoutes.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseConfig; diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index d945bc454..8ff13f97e 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseConfig; diff --git a/src/Config/Registrar.php b/src/Config/Registrar.php index 8c366e8cd..4ac13b3ac 100644 --- a/src/Config/Registrar.php +++ b/src/Config/Registrar.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Shield\Authentication\Passwords\ValidationRules as PasswordRules; diff --git a/src/Config/Services.php b/src/Config/Services.php index aa922f834..88e5e05c2 100644 --- a/src/Config/Services.php +++ b/src/Config/Services.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseService; diff --git a/src/Controllers/ActionController.php b/src/Controllers/ActionController.php index 8bcbb4f80..706dfcba7 100644 --- a/src/Controllers/ActionController.php +++ b/src/Controllers/ActionController.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Controllers; use App\Controllers\BaseController; diff --git a/src/Controllers/LoginController.php b/src/Controllers/LoginController.php index 0dc49436e..1296632cf 100644 --- a/src/Controllers/LoginController.php +++ b/src/Controllers/LoginController.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Controllers; use App\Controllers\BaseController; diff --git a/src/Controllers/MagicLinkController.php b/src/Controllers/MagicLinkController.php index 3357f3d7d..2a1b25785 100644 --- a/src/Controllers/MagicLinkController.php +++ b/src/Controllers/MagicLinkController.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Controllers; use App\Controllers\BaseController; diff --git a/src/Controllers/RegisterController.php b/src/Controllers/RegisterController.php index 43761b990..aad49b5a0 100644 --- a/src/Controllers/RegisterController.php +++ b/src/Controllers/RegisterController.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Controllers; use App\Controllers\BaseController; diff --git a/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php b/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php index 792cdad3a..2833e81cd 100644 --- a/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php +++ b/src/Database/Migrations/2020-12-28-223112_create_auth_tables.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Database\Migrations; use CodeIgniter\Database\Forge; diff --git a/src/Entities/AccessToken.php b/src/Entities/AccessToken.php index 6f81a3b3b..406910f21 100644 --- a/src/Entities/AccessToken.php +++ b/src/Entities/AccessToken.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities; use CodeIgniter\Entity\Entity; diff --git a/src/Entities/Cast/IntBoolCast.php b/src/Entities/Cast/IntBoolCast.php index 401a52aa7..40c3bb2cf 100644 --- a/src/Entities/Cast/IntBoolCast.php +++ b/src/Entities/Cast/IntBoolCast.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities\Cast; use CodeIgniter\Entity\Cast\BaseCast; diff --git a/src/Entities/Entity.php b/src/Entities/Entity.php index 5708c8a41..550945049 100644 --- a/src/Entities/Entity.php +++ b/src/Entities/Entity.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities; use CodeIgniter\Entity\Entity as FrameworkEntity; diff --git a/src/Entities/Group.php b/src/Entities/Group.php index 8fe30b184..62384a159 100644 --- a/src/Entities/Group.php +++ b/src/Entities/Group.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities; use CodeIgniter\Entity\Entity; diff --git a/src/Entities/Login.php b/src/Entities/Login.php index d6859f132..785e3c79a 100644 --- a/src/Entities/Login.php +++ b/src/Entities/Login.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities; class Login extends Entity diff --git a/src/Entities/User.php b/src/Entities/User.php index 1aff561ab..573e9e987 100644 --- a/src/Entities/User.php +++ b/src/Entities/User.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities; use CodeIgniter\Database\Exceptions\DataException; diff --git a/src/Entities/UserIdentity.php b/src/Entities/UserIdentity.php index 31ab3e249..b0a491fe9 100644 --- a/src/Entities/UserIdentity.php +++ b/src/Entities/UserIdentity.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Entities; use CodeIgniter\I18n\Time; diff --git a/src/Exceptions/BaseException.php b/src/Exceptions/BaseException.php index 693d58c8f..61221a9f1 100644 --- a/src/Exceptions/BaseException.php +++ b/src/Exceptions/BaseException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; use Throwable; diff --git a/src/Exceptions/GroupException.php b/src/Exceptions/GroupException.php index bda9ef35c..4653bd5d4 100644 --- a/src/Exceptions/GroupException.php +++ b/src/Exceptions/GroupException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; use CodeIgniter\Shield\Authorization\AuthorizationException; diff --git a/src/Exceptions/InvalidArgumentException.php b/src/Exceptions/InvalidArgumentException.php index f01a5382a..9de15e6e9 100644 --- a/src/Exceptions/InvalidArgumentException.php +++ b/src/Exceptions/InvalidArgumentException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; class InvalidArgumentException extends LogicException implements BaseException diff --git a/src/Exceptions/LogicException.php b/src/Exceptions/LogicException.php index 5825f9159..384edd6e6 100644 --- a/src/Exceptions/LogicException.php +++ b/src/Exceptions/LogicException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; class LogicException extends \LogicException implements BaseException diff --git a/src/Exceptions/PermissionException.php b/src/Exceptions/PermissionException.php index 57f037420..bf65c6776 100644 --- a/src/Exceptions/PermissionException.php +++ b/src/Exceptions/PermissionException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; use CodeIgniter\Shield\Authorization\AuthorizationException; diff --git a/src/Exceptions/RuntimeException.php b/src/Exceptions/RuntimeException.php index e5a507ecd..0a7d371e8 100644 --- a/src/Exceptions/RuntimeException.php +++ b/src/Exceptions/RuntimeException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; class RuntimeException extends \RuntimeException implements BaseException diff --git a/src/Exceptions/SecurityException.php b/src/Exceptions/SecurityException.php index c72d7aa04..62f0ecc24 100644 --- a/src/Exceptions/SecurityException.php +++ b/src/Exceptions/SecurityException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; class SecurityException extends RuntimeException diff --git a/src/Exceptions/UserNotFoundException.php b/src/Exceptions/UserNotFoundException.php index 485f5c04e..64b4945e5 100644 --- a/src/Exceptions/UserNotFoundException.php +++ b/src/Exceptions/UserNotFoundException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; class UserNotFoundException extends RuntimeException diff --git a/src/Exceptions/ValidationException.php b/src/Exceptions/ValidationException.php index 3aae180ef..1922ae115 100644 --- a/src/Exceptions/ValidationException.php +++ b/src/Exceptions/ValidationException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Exceptions; class ValidationException extends RuntimeException diff --git a/src/Filters/AbstractAuthFilter.php b/src/Filters/AbstractAuthFilter.php index fb81d1274..652d8940b 100644 --- a/src/Filters/AbstractAuthFilter.php +++ b/src/Filters/AbstractAuthFilter.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/AuthRates.php b/src/Filters/AuthRates.php index 7c1ad4e5e..2b9a9eae2 100644 --- a/src/Filters/AuthRates.php +++ b/src/Filters/AuthRates.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/ChainAuth.php b/src/Filters/ChainAuth.php index eb4ee0fbb..4f014898b 100644 --- a/src/Filters/ChainAuth.php +++ b/src/Filters/ChainAuth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/ForcePasswordResetFilter.php b/src/Filters/ForcePasswordResetFilter.php index ce64492b4..017aad124 100644 --- a/src/Filters/ForcePasswordResetFilter.php +++ b/src/Filters/ForcePasswordResetFilter.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/GroupFilter.php b/src/Filters/GroupFilter.php index 7c0a33b16..9a863843b 100644 --- a/src/Filters/GroupFilter.php +++ b/src/Filters/GroupFilter.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\HTTP\RedirectResponse; diff --git a/src/Filters/HmacAuth.php b/src/Filters/HmacAuth.php index 986175caa..14e38ad0c 100644 --- a/src/Filters/HmacAuth.php +++ b/src/Filters/HmacAuth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/JWTAuth.php b/src/Filters/JWTAuth.php index 735bf2f2d..e49fb476b 100644 --- a/src/Filters/JWTAuth.php +++ b/src/Filters/JWTAuth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/PermissionFilter.php b/src/Filters/PermissionFilter.php index e20f7a23d..d406ffa56 100644 --- a/src/Filters/PermissionFilter.php +++ b/src/Filters/PermissionFilter.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\HTTP\RedirectResponse; diff --git a/src/Filters/SessionAuth.php b/src/Filters/SessionAuth.php index 97e85c98b..915d92a4c 100644 --- a/src/Filters/SessionAuth.php +++ b/src/Filters/SessionAuth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Filters/TokenAuth.php b/src/Filters/TokenAuth.php index 8094f8f38..9e2fdd91a 100644 --- a/src/Filters/TokenAuth.php +++ b/src/Filters/TokenAuth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Filters; use CodeIgniter\Filters\FilterInterface; diff --git a/src/Helpers/auth_helper.php b/src/Helpers/auth_helper.php index 3396ffb55..b05accb86 100644 --- a/src/Helpers/auth_helper.php +++ b/src/Helpers/auth_helper.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + use CodeIgniter\Shield\Auth; if (! function_exists('auth')) { diff --git a/src/Helpers/email_helper.php b/src/Helpers/email_helper.php index 09a99e480..20e9ccf47 100644 --- a/src/Helpers/email_helper.php +++ b/src/Helpers/email_helper.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + use CodeIgniter\Email\Email; if (! defined('emailer')) { diff --git a/src/Language/ar/Auth.php b/src/Language/ar/Auth.php index 3f92deec0..5f44a4284 100644 --- a/src/Language/ar/Auth.php +++ b/src/Language/ar/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} ليس توثيق صحيح.', diff --git a/src/Language/bg/Auth.php b/src/Language/bg/Auth.php index b4bee29dd..8aa8f898d 100644 --- a/src/Language/bg/Auth.php +++ b/src/Language/bg/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Изключения 'unknownAuthenticator' => '{0} не е валиден аутентикатор.', diff --git a/src/Language/de/Auth.php b/src/Language/de/Auth.php index 53b67542a..6ac29d5e2 100644 --- a/src/Language/de/Auth.php +++ b/src/Language/de/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} ist kein gültiger Authentifikator.', diff --git a/src/Language/en/Auth.php b/src/Language/en/Auth.php index 1dfdfe7b1..6f34fe3ee 100644 --- a/src/Language/en/Auth.php +++ b/src/Language/en/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} is not a valid authenticator.', diff --git a/src/Language/es/Auth.php b/src/Language/es/Auth.php index 5fdd2ae0c..9f3797744 100644 --- a/src/Language/es/Auth.php +++ b/src/Language/es/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Excepciones 'unknownAuthenticator' => '{0} no es un autenticador válido.', diff --git a/src/Language/fa/Auth.php b/src/Language/fa/Auth.php index c3bf118f0..e42ae39a4 100644 --- a/src/Language/fa/Auth.php +++ b/src/Language/fa/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} احراز هویت معتبری نمی باشد.', diff --git a/src/Language/fr/Auth.php b/src/Language/fr/Auth.php index fb167b954..c6f8e4919 100644 --- a/src/Language/fr/Auth.php +++ b/src/Language/fr/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} n\'est pas un authentificateur valide.', diff --git a/src/Language/id/Auth.php b/src/Language/id/Auth.php index a2b8f6246..6910a81fd 100644 --- a/src/Language/id/Auth.php +++ b/src/Language/id/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} bukan otentikator yang sah.', diff --git a/src/Language/it/Auth.php b/src/Language/it/Auth.php index 0b4e845ac..9cafd7f48 100644 --- a/src/Language/it/Auth.php +++ b/src/Language/it/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} non è un autenticatore valido.', diff --git a/src/Language/ja/Auth.php b/src/Language/ja/Auth.php index 7823e88cb..282335160 100644 --- a/src/Language/ja/Auth.php +++ b/src/Language/ja/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} は有効なオーセンティケーターではありません。', // '{0} is not a valid authenticator.' diff --git a/src/Language/lt/Auth.php b/src/Language/lt/Auth.php index 035d80070..716f6f263 100644 --- a/src/Language/lt/Auth.php +++ b/src/Language/lt/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} nėra teisingas autentifikatorius.', diff --git a/src/Language/pt-BR/Auth.php b/src/Language/pt-BR/Auth.php index e4b479b5b..f8aa21912 100644 --- a/src/Language/pt-BR/Auth.php +++ b/src/Language/pt-BR/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} não é um autenticador válido.', diff --git a/src/Language/pt/Auth.php b/src/Language/pt/Auth.php index 765db2070..50d39b0dd 100644 --- a/src/Language/pt/Auth.php +++ b/src/Language/pt/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} não é um autenticador válido.', diff --git a/src/Language/sk/Auth.php b/src/Language/sk/Auth.php index 11579e7ba..f12c1310e 100644 --- a/src/Language/sk/Auth.php +++ b/src/Language/sk/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} nie je platný autentifikátor.', diff --git a/src/Language/sr/Auth.php b/src/Language/sr/Auth.php index 9211ba0d4..03ce96794 100644 --- a/src/Language/sr/Auth.php +++ b/src/Language/sr/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} nije validan autentikator.', diff --git a/src/Language/sv-SE/Auth.php b/src/Language/sv-SE/Auth.php index ab206d7d5..d857e7c4b 100644 --- a/src/Language/sv-SE/Auth.php +++ b/src/Language/sv-SE/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} är inte en giltig autentiseringsmetod.', diff --git a/src/Language/tr/Auth.php b/src/Language/tr/Auth.php index 2b35941d7..a433c3757 100644 --- a/src/Language/tr/Auth.php +++ b/src/Language/tr/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} geçerli bir kimlik doğrulayıcı değil.', diff --git a/src/Language/uk/Auth.php b/src/Language/uk/Auth.php index d54b30dd1..c588f1f37 100644 --- a/src/Language/uk/Auth.php +++ b/src/Language/uk/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} не є дійсним автентифікатором.', diff --git a/src/Models/BaseModel.php b/src/Models/BaseModel.php index e0db1dec1..411e32422 100644 --- a/src/Models/BaseModel.php +++ b/src/Models/BaseModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\Model; diff --git a/src/Models/CheckQueryReturnTrait.php b/src/Models/CheckQueryReturnTrait.php index 687d7da96..496db20b9 100644 --- a/src/Models/CheckQueryReturnTrait.php +++ b/src/Models/CheckQueryReturnTrait.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\Shield\Exceptions\ValidationException; diff --git a/src/Models/DatabaseException.php b/src/Models/DatabaseException.php index dd782ce1a..82d53ab35 100644 --- a/src/Models/DatabaseException.php +++ b/src/Models/DatabaseException.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\Shield\Exceptions\RuntimeException; diff --git a/src/Models/GroupModel.php b/src/Models/GroupModel.php index aa24bea12..899931400 100644 --- a/src/Models/GroupModel.php +++ b/src/Models/GroupModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\Shield\Entities\User; diff --git a/src/Models/LoginModel.php b/src/Models/LoginModel.php index 5cb59491c..9c2ff0dca 100644 --- a/src/Models/LoginModel.php +++ b/src/Models/LoginModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\I18n\Time; diff --git a/src/Models/PermissionModel.php b/src/Models/PermissionModel.php index a23db8d29..84dd28199 100644 --- a/src/Models/PermissionModel.php +++ b/src/Models/PermissionModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\Shield\Entities\User; diff --git a/src/Models/RememberModel.php b/src/Models/RememberModel.php index 76b6b11fd..68b09bda1 100644 --- a/src/Models/RememberModel.php +++ b/src/Models/RememberModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\I18n\Time; diff --git a/src/Models/TokenLoginModel.php b/src/Models/TokenLoginModel.php index 748bf4ecd..07c902d41 100644 --- a/src/Models/TokenLoginModel.php +++ b/src/Models/TokenLoginModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\I18n\Time; diff --git a/src/Models/UserIdentityModel.php b/src/Models/UserIdentityModel.php index b91c48712..9ccb029ff 100644 --- a/src/Models/UserIdentityModel.php +++ b/src/Models/UserIdentityModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\I18n\Time; diff --git a/src/Models/UserModel.php b/src/Models/UserModel.php index 3c6f5f518..73d293033 100644 --- a/src/Models/UserModel.php +++ b/src/Models/UserModel.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Models; use CodeIgniter\Database\Exceptions\DataException; diff --git a/src/Result.php b/src/Result.php index 9a3f368ca..45f75cc5f 100644 --- a/src/Result.php +++ b/src/Result.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield; use CodeIgniter\Shield\Entities\User; diff --git a/src/Test/AuthenticationTesting.php b/src/Test/AuthenticationTesting.php index b0e4822cd..437a2477a 100644 --- a/src/Test/AuthenticationTesting.php +++ b/src/Test/AuthenticationTesting.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Test; use CodeIgniter\Shield\Authentication\Authenticators\Session; diff --git a/src/Test/MockInputOutput.php b/src/Test/MockInputOutput.php index e4ce93dda..c3c2f635d 100644 --- a/src/Test/MockInputOutput.php +++ b/src/Test/MockInputOutput.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Test; use CodeIgniter\CLI\CLI; diff --git a/src/Traits/Activatable.php b/src/Traits/Activatable.php index 4294f0866..b75808076 100644 --- a/src/Traits/Activatable.php +++ b/src/Traits/Activatable.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Traits; trait Activatable diff --git a/src/Traits/Bannable.php b/src/Traits/Bannable.php index b151c1b64..739f32e14 100644 --- a/src/Traits/Bannable.php +++ b/src/Traits/Bannable.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Traits; trait Bannable diff --git a/src/Traits/Resettable.php b/src/Traits/Resettable.php index 4b1d61b8c..c68c0ba1b 100644 --- a/src/Traits/Resettable.php +++ b/src/Traits/Resettable.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Traits; use CodeIgniter\Shield\Authentication\Authenticators\Session; diff --git a/src/Traits/Viewable.php b/src/Traits/Viewable.php index d9bedf2ac..85f4df1fb 100644 --- a/src/Traits/Viewable.php +++ b/src/Traits/Viewable.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Traits; trait Viewable diff --git a/src/Validation/ValidationRules.php b/src/Validation/ValidationRules.php index 4f38a7c64..4e1284fb7 100644 --- a/src/Validation/ValidationRules.php +++ b/src/Validation/ValidationRules.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Validation; use CodeIgniter\Shield\Authentication\Passwords; diff --git a/tests/Authentication/AccessTokenTest.php b/tests/Authentication/AccessTokenTest.php index b5fd8b9d8..2103b0f9d 100644 --- a/tests/Authentication/AccessTokenTest.php +++ b/tests/Authentication/AccessTokenTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/tests/Authentication/AuthHelperTest.php b/tests/Authentication/AuthHelperTest.php index da8dff537..a0cd35505 100644 --- a/tests/Authentication/AuthHelperTest.php +++ b/tests/Authentication/AuthHelperTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Authentication\AuthenticationException; diff --git a/tests/Authentication/AuthTest.php b/tests/Authentication/AuthTest.php index 100760c7a..429184b5d 100644 --- a/tests/Authentication/AuthTest.php +++ b/tests/Authentication/AuthTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Config\Services; diff --git a/tests/Authentication/AuthenticationTest.php b/tests/Authentication/AuthenticationTest.php index 58b92ce10..27d8029cc 100644 --- a/tests/Authentication/AuthenticationTest.php +++ b/tests/Authentication/AuthenticationTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Authentication\Authentication; diff --git a/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php b/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php index 12ffadd54..7c48ac1c5 100644 --- a/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Authenticators; use CodeIgniter\I18n\Time; diff --git a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php index 96db32cd0..7c601c113 100644 --- a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Authenticators; use CodeIgniter\I18n\Time; diff --git a/tests/Authentication/Authenticators/JWTAuthenticatorTest.php b/tests/Authentication/Authenticators/JWTAuthenticatorTest.php index 3bd24070f..9d4e5d6b5 100644 --- a/tests/Authentication/Authenticators/JWTAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/JWTAuthenticatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Authenticators; use CodeIgniter\I18n\Time; diff --git a/tests/Authentication/Authenticators/SessionAuthenticatorTest.php b/tests/Authentication/Authenticators/SessionAuthenticatorTest.php index 662b32fd0..ca1a8b53e 100644 --- a/tests/Authentication/Authenticators/SessionAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/SessionAuthenticatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Authenticators; use CodeIgniter\Config\Factories; diff --git a/tests/Authentication/Filters/AbstractFilterTestCase.php b/tests/Authentication/Filters/AbstractFilterTestCase.php index d44f9e931..246fc7b93 100644 --- a/tests/Authentication/Filters/AbstractFilterTestCase.php +++ b/tests/Authentication/Filters/AbstractFilterTestCase.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Config\Factories; diff --git a/tests/Authentication/Filters/ChainFilterTest.php b/tests/Authentication/Filters/ChainFilterTest.php index c71f92dff..b1c81aad4 100644 --- a/tests/Authentication/Filters/ChainFilterTest.php +++ b/tests/Authentication/Filters/ChainFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/tests/Authentication/Filters/GroupFilterTest.php b/tests/Authentication/Filters/GroupFilterTest.php index ddfb423b1..3e0d2a905 100644 --- a/tests/Authentication/Filters/GroupFilterTest.php +++ b/tests/Authentication/Filters/GroupFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Shield\Entities\User; diff --git a/tests/Authentication/Filters/HmacFilterTest.php b/tests/Authentication/Filters/HmacFilterTest.php index 4a7acb9bc..14531a773 100644 --- a/tests/Authentication/Filters/HmacFilterTest.php +++ b/tests/Authentication/Filters/HmacFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/tests/Authentication/Filters/JWTFilterTest.php b/tests/Authentication/Filters/JWTFilterTest.php index e8f4d3b39..f26ef13fa 100644 --- a/tests/Authentication/Filters/JWTFilterTest.php +++ b/tests/Authentication/Filters/JWTFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Config\Factories; diff --git a/tests/Authentication/Filters/PermissionFilterTest.php b/tests/Authentication/Filters/PermissionFilterTest.php index d4580017b..67564fcdf 100644 --- a/tests/Authentication/Filters/PermissionFilterTest.php +++ b/tests/Authentication/Filters/PermissionFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Shield\Entities\User; diff --git a/tests/Authentication/Filters/SessionFilterTest.php b/tests/Authentication/Filters/SessionFilterTest.php index a217d7a74..e8ee1f9f4 100644 --- a/tests/Authentication/Filters/SessionFilterTest.php +++ b/tests/Authentication/Filters/SessionFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Shield\Filters\SessionAuth; diff --git a/tests/Authentication/Filters/TokenFilterTest.php b/tests/Authentication/Filters/TokenFilterTest.php index fc5337761..c080be2df 100644 --- a/tests/Authentication/Filters/TokenFilterTest.php +++ b/tests/Authentication/Filters/TokenFilterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication\Filters; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/tests/Authentication/ForcePasswordResetTest.php b/tests/Authentication/ForcePasswordResetTest.php index c677adf4b..582961f92 100644 --- a/tests/Authentication/ForcePasswordResetTest.php +++ b/tests/Authentication/ForcePasswordResetTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Entities\User; diff --git a/tests/Authentication/HasAccessTokensTest.php b/tests/Authentication/HasAccessTokensTest.php index 9612b8136..0005325d8 100644 --- a/tests/Authentication/HasAccessTokensTest.php +++ b/tests/Authentication/HasAccessTokensTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/tests/Authentication/HasHmacTokensTest.php b/tests/Authentication/HasHmacTokensTest.php index 12ebcd284..c2b0c158c 100644 --- a/tests/Authentication/HasHmacTokensTest.php +++ b/tests/Authentication/HasHmacTokensTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\Shield\Entities\AccessToken; diff --git a/tests/Authentication/MagicLinkTest.php b/tests/Authentication/MagicLinkTest.php index 63292fae6..f8426604a 100644 --- a/tests/Authentication/MagicLinkTest.php +++ b/tests/Authentication/MagicLinkTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authentication; use CodeIgniter\I18n\Time; diff --git a/tests/Authorization/AuthorizableTest.php b/tests/Authorization/AuthorizableTest.php index 1dc098abf..5f3d9ff9c 100644 --- a/tests/Authorization/AuthorizableTest.php +++ b/tests/Authorization/AuthorizableTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authorization; use CodeIgniter\I18n\Time; diff --git a/tests/Authorization/GroupTest.php b/tests/Authorization/GroupTest.php index 40cb5f039..68c190be8 100644 --- a/tests/Authorization/GroupTest.php +++ b/tests/Authorization/GroupTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authorization; use CodeIgniter\Shield\Authorization\Groups; diff --git a/tests/Authorization/GroupsTest.php b/tests/Authorization/GroupsTest.php index 219880742..b4b1ba32f 100644 --- a/tests/Authorization/GroupsTest.php +++ b/tests/Authorization/GroupsTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Authorization; use CodeIgniter\Shield\Authorization\Groups; diff --git a/tests/Collectors/AuthTest.php b/tests/Collectors/AuthTest.php index 45d7a5871..cba81aacc 100644 --- a/tests/Collectors/AuthTest.php +++ b/tests/Collectors/AuthTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Collectors; use CodeIgniter\Shield\Auth as ShieldAuth; diff --git a/tests/Commands/Setup/ContentReplacerTest.php b/tests/Commands/Setup/ContentReplacerTest.php index 9b4c8d8e1..2a6c029e3 100644 --- a/tests/Commands/Setup/ContentReplacerTest.php +++ b/tests/Commands/Setup/ContentReplacerTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Commands\Setup; use CodeIgniter\Shield\Commands\Setup\ContentReplacer; diff --git a/tests/Commands/SetupTest.php b/tests/Commands/SetupTest.php index 3401295a0..1419b5962 100644 --- a/tests/Commands/SetupTest.php +++ b/tests/Commands/SetupTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Commands; use CodeIgniter\Shield\Commands\Setup; diff --git a/tests/Commands/UserModelGeneratorTest.php b/tests/Commands/UserModelGeneratorTest.php index 7b8ebcb3e..0e9124448 100644 --- a/tests/Commands/UserModelGeneratorTest.php +++ b/tests/Commands/UserModelGeneratorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Commands; use CodeIgniter\Test\CIUnitTestCase; diff --git a/tests/Commands/UserTest.php b/tests/Commands/UserTest.php index 98a706563..76e1e3989 100644 --- a/tests/Commands/UserTest.php +++ b/tests/Commands/UserTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Commands; use CodeIgniter\Shield\Commands\User; diff --git a/tests/Controllers/ActionsTest.php b/tests/Controllers/ActionsTest.php index cb815af40..a6d9394f6 100644 --- a/tests/Controllers/ActionsTest.php +++ b/tests/Controllers/ActionsTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Controllers; use CodeIgniter\Config\Factories; diff --git a/tests/Controllers/LoginTest.php b/tests/Controllers/LoginTest.php index f4c7bc5f7..c0b6ba8bb 100644 --- a/tests/Controllers/LoginTest.php +++ b/tests/Controllers/LoginTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Controllers; use CodeIgniter\Config\Factories; diff --git a/tests/Controllers/MagicLinkTest.php b/tests/Controllers/MagicLinkTest.php index b8b1f794e..477c98248 100644 --- a/tests/Controllers/MagicLinkTest.php +++ b/tests/Controllers/MagicLinkTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Controllers; use CodeIgniter\Config\Factories; diff --git a/tests/Controllers/RegisterTest.php b/tests/Controllers/RegisterTest.php index 630c13b38..03a6587f9 100644 --- a/tests/Controllers/RegisterTest.php +++ b/tests/Controllers/RegisterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Controllers; use CodeIgniter\Config\Factories; diff --git a/tests/Language/AbstractTranslationTestCase.php b/tests/Language/AbstractTranslationTestCase.php index b3b45a21f..eabe49195 100644 --- a/tests/Language/AbstractTranslationTestCase.php +++ b/tests/Language/AbstractTranslationTestCase.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/ArabicTranslationTest.php b/tests/Language/ArabicTranslationTest.php index 22eeaf14f..fbb449d82 100644 --- a/tests/Language/ArabicTranslationTest.php +++ b/tests/Language/ArabicTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/BrazilianTranslationTest.php b/tests/Language/BrazilianTranslationTest.php index 7cf1df04c..8745961df 100644 --- a/tests/Language/BrazilianTranslationTest.php +++ b/tests/Language/BrazilianTranslationTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Language; /** diff --git a/tests/Language/BulgarianTranslationTest.php b/tests/Language/BulgarianTranslationTest.php index 1125d144e..ab26a4d5f 100644 --- a/tests/Language/BulgarianTranslationTest.php +++ b/tests/Language/BulgarianTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/FarsiTranslationTest.php b/tests/Language/FarsiTranslationTest.php index ace86cbed..ffa8942fe 100644 --- a/tests/Language/FarsiTranslationTest.php +++ b/tests/Language/FarsiTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/FrenchTranslationTest.php b/tests/Language/FrenchTranslationTest.php index df6b64bbf..2ece0ee22 100644 --- a/tests/Language/FrenchTranslationTest.php +++ b/tests/Language/FrenchTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/GermanTranslationTest.php b/tests/Language/GermanTranslationTest.php index 8bccc62d6..6c32d25ee 100644 --- a/tests/Language/GermanTranslationTest.php +++ b/tests/Language/GermanTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/IndonesianTranslationTest.php b/tests/Language/IndonesianTranslationTest.php index 31a244ca1..457b0365a 100644 --- a/tests/Language/IndonesianTranslationTest.php +++ b/tests/Language/IndonesianTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/ItalianTranslationTest.php b/tests/Language/ItalianTranslationTest.php index c00ad673d..a22e05fcb 100644 --- a/tests/Language/ItalianTranslationTest.php +++ b/tests/Language/ItalianTranslationTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Language; /** diff --git a/tests/Language/JapaneseTranslationTest.php b/tests/Language/JapaneseTranslationTest.php index 71c1e834e..4d908479e 100644 --- a/tests/Language/JapaneseTranslationTest.php +++ b/tests/Language/JapaneseTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/LithuanianTranslationTest.php b/tests/Language/LithuanianTranslationTest.php index b9a5372f0..bbaebedd1 100644 --- a/tests/Language/LithuanianTranslationTest.php +++ b/tests/Language/LithuanianTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/PortugueseTranslationTest.php b/tests/Language/PortugueseTranslationTest.php index 1b74b90ad..7e976cead 100644 --- a/tests/Language/PortugueseTranslationTest.php +++ b/tests/Language/PortugueseTranslationTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Language; /** diff --git a/tests/Language/SerbianTranslationTest.php b/tests/Language/SerbianTranslationTest.php index 5dede1cf5..df9978f82 100644 --- a/tests/Language/SerbianTranslationTest.php +++ b/tests/Language/SerbianTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/SlovakTranslationTest.php b/tests/Language/SlovakTranslationTest.php index b21914bb5..333cfaeac 100644 --- a/tests/Language/SlovakTranslationTest.php +++ b/tests/Language/SlovakTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/SpanishTranslationTest.php b/tests/Language/SpanishTranslationTest.php index 6b6365834..15bca9a43 100644 --- a/tests/Language/SpanishTranslationTest.php +++ b/tests/Language/SpanishTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/SwedishTranslationTest.php b/tests/Language/SwedishTranslationTest.php index 2c5ed0674..da1d818b9 100644 --- a/tests/Language/SwedishTranslationTest.php +++ b/tests/Language/SwedishTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/TurkishTranslationTest.php b/tests/Language/TurkishTranslationTest.php index df5afd3bc..a31afd2a3 100644 --- a/tests/Language/TurkishTranslationTest.php +++ b/tests/Language/TurkishTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Language/UkrainianTranslationTest.php b/tests/Language/UkrainianTranslationTest.php index 79bdfad01..f8bc3ff31 100644 --- a/tests/Language/UkrainianTranslationTest.php +++ b/tests/Language/UkrainianTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/Unit/AuthRoutesTest.php b/tests/Unit/AuthRoutesTest.php index e67bec994..9012b731e 100644 --- a/tests/Unit/AuthRoutesTest.php +++ b/tests/Unit/AuthRoutesTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use Tests\Support\TestCase; diff --git a/tests/Unit/Authentication/JWT/Adapters/FirebaseAdapaterTest.php b/tests/Unit/Authentication/JWT/Adapters/FirebaseAdapaterTest.php index 8385a3f00..ada3dfbbf 100644 --- a/tests/Unit/Authentication/JWT/Adapters/FirebaseAdapaterTest.php +++ b/tests/Unit/Authentication/JWT/Adapters/FirebaseAdapaterTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit\Authentication\JWT\Adapters; use CodeIgniter\I18n\Time; diff --git a/tests/Unit/Authentication/JWT/JWTManagerTest.php b/tests/Unit/Authentication/JWT/JWTManagerTest.php index 045e70633..6acd82717 100644 --- a/tests/Unit/Authentication/JWT/JWTManagerTest.php +++ b/tests/Unit/Authentication/JWT/JWTManagerTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit\Authentication\JWT; use CodeIgniter\I18n\Time; diff --git a/tests/Unit/CompositionValidatorTest.php b/tests/Unit/CompositionValidatorTest.php index 151475f62..3b3bed60b 100644 --- a/tests/Unit/CompositionValidatorTest.php +++ b/tests/Unit/CompositionValidatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Authentication\AuthenticationException; diff --git a/tests/Unit/DictionaryValidatorTest.php b/tests/Unit/DictionaryValidatorTest.php index 97fbf4072..2c5819862 100644 --- a/tests/Unit/DictionaryValidatorTest.php +++ b/tests/Unit/DictionaryValidatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Authentication\Passwords\DictionaryValidator; diff --git a/tests/Unit/EmailActivatorTest.php b/tests/Unit/EmailActivatorTest.php index daa7f79ac..15d356cc0 100644 --- a/tests/Unit/EmailActivatorTest.php +++ b/tests/Unit/EmailActivatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Authentication\Actions\EmailActivator; diff --git a/tests/Unit/FilterInCliTest.php b/tests/Unit/FilterInCliTest.php index fa9a7c77d..ad642c657 100644 --- a/tests/Unit/FilterInCliTest.php +++ b/tests/Unit/FilterInCliTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Filters\FilterInterface; diff --git a/tests/Unit/LoginModelTest.php b/tests/Unit/LoginModelTest.php index 464a2b0f5..2d77f4cfd 100644 --- a/tests/Unit/LoginModelTest.php +++ b/tests/Unit/LoginModelTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Exceptions\ValidationException; diff --git a/tests/Unit/NothingPersonalValidatorTest.php b/tests/Unit/NothingPersonalValidatorTest.php index b3e7d8e77..7fbb8fe28 100644 --- a/tests/Unit/NothingPersonalValidatorTest.php +++ b/tests/Unit/NothingPersonalValidatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Authentication\Passwords\NothingPersonalValidator; diff --git a/tests/Unit/PasswordsTest.php b/tests/Unit/PasswordsTest.php index fc892013b..80bad8ac0 100644 --- a/tests/Unit/PasswordsTest.php +++ b/tests/Unit/PasswordsTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Authentication\Passwords; diff --git a/tests/Unit/PwnedValidatorTest.php b/tests/Unit/PwnedValidatorTest.php index 1d0c7ec90..52e5b6767 100644 --- a/tests/Unit/PwnedValidatorTest.php +++ b/tests/Unit/PwnedValidatorTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\HTTP\Exceptions\HTTPException; diff --git a/tests/Unit/UserIdentityModelTest.php b/tests/Unit/UserIdentityModelTest.php index 34e4e45f0..53cbb4259 100644 --- a/tests/Unit/UserIdentityModelTest.php +++ b/tests/Unit/UserIdentityModelTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Shield\Authentication\Authenticators\Session; diff --git a/tests/Unit/UserModelTest.php b/tests/Unit/UserModelTest.php index 6cb92a0d9..77c71ea59 100644 --- a/tests/Unit/UserModelTest.php +++ b/tests/Unit/UserModelTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\Database\Exceptions\DataException; diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index f2554fa62..9c4d3ccda 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Unit; use CodeIgniter\I18n\Time; diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index 7a08e4dc7..36c680924 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * diff --git a/tests/_support/DatabaseTestCase.php b/tests/_support/DatabaseTestCase.php index 8e72928af..61f5f8d25 100644 --- a/tests/_support/DatabaseTestCase.php +++ b/tests/_support/DatabaseTestCase.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Support; use CodeIgniter\Shield\Config\Auth; diff --git a/tests/_support/FakeUser.php b/tests/_support/FakeUser.php index 6cc1fe09e..1dcb62fd8 100644 --- a/tests/_support/FakeUser.php +++ b/tests/_support/FakeUser.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Support; use CodeIgniter\Shield\Entities\User; diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php index 021fccfd9..a7af822ea 100644 --- a/tests/_support/TestCase.php +++ b/tests/_support/TestCase.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Support; use CodeIgniter\Config\Factories; From 5d1dff3eb37c927790bc29151d774d32ab9612b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:32:26 +0000 Subject: [PATCH 065/128] chore(deps-dev): update rector/rector requirement from 0.18.5 to 0.18.6 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.18.5...0.18.6) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a412e5817..aeaf21370 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "mockery/mockery": "^1.0", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-strict-rules": "^1.5", - "rector/rector": "0.18.5" + "rector/rector": "0.18.6" }, "provide": { "codeigniter4/authentication-implementation": "1.0" From 851152fadb2912e9f522e2dbfab3a09aa488c10d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 25 Oct 2023 20:45:04 +0330 Subject: [PATCH 066/128] tests: refactor test by rector 0.18.6 --- tests/Authentication/Filters/SessionFilterTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Authentication/Filters/SessionFilterTest.php b/tests/Authentication/Filters/SessionFilterTest.php index a217d7a74..8a0769e59 100644 --- a/tests/Authentication/Filters/SessionFilterTest.php +++ b/tests/Authentication/Filters/SessionFilterTest.php @@ -4,6 +4,7 @@ namespace Tests\Authentication\Filters; +use CodeIgniter\I18n\Time; use CodeIgniter\Shield\Filters\SessionAuth; use CodeIgniter\Shield\Models\UserModel; use CodeIgniter\Test\DatabaseTestTrait; @@ -43,7 +44,7 @@ public function testFilterSuccess(): void $this->assertSame($user->id, auth('session')->id()); $this->assertSame($user->id, auth('session')->user()->id); // Last Active should have been updated - $this->assertNotEmpty(auth('session')->user()->last_active); + $this->assertInstanceOf(Time::class, auth('session')->user()->last_active); } public function testRecordActiveDate(): void From f93a3bb15da978e4cfca5fc19f18bb121a9ef9c3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 26 Oct 2023 06:13:31 +0900 Subject: [PATCH 067/128] docs: improve expression --- docs/references/controller_filters.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/references/controller_filters.md b/docs/references/controller_filters.md index 7b88cc264..6afc8c4cd 100644 --- a/docs/references/controller_filters.md +++ b/docs/references/controller_filters.md @@ -4,13 +4,15 @@ !!! note - These filters are already loaded for you by the [registrar](https://codeigniter.com/user_guide/general/configuration.html#registrars) class located at **src/Config/Registrar.php**. + The filter `$aliases` that Shield provides are automatically added for you by the + [Registrar](https://codeigniter.com/user_guide/general/configuration.html#registrars) + class located at **src/Config/Registrar.php**. So you don't need to add in + your **app/Config/Filters.php**. The [Controller Filters](https://codeigniter.com/user_guide/incoming/filters.html) you can use to protect your routes Shield provides are: ```php -public $aliases = [ - // ... +$aliases = [ 'session' => \CodeIgniter\Shield\Filters\SessionAuth::class, 'tokens' => \CodeIgniter\Shield\Filters\TokenAuth::class, 'hmac' => \CodeIgniter\Shield\Filters\HmacAuth::class, From 582a6ae8b17895cc2e1bf6eb3725237046fd4b86 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 26 Oct 2023 06:16:42 +0900 Subject: [PATCH 068/128] docs: add note for filter $aliases --- docs/quick_start_guide/using_session_auth.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/quick_start_guide/using_session_auth.md b/docs/quick_start_guide/using_session_auth.md index 43e3fe80f..94af696b6 100644 --- a/docs/quick_start_guide/using_session_auth.md +++ b/docs/quick_start_guide/using_session_auth.md @@ -106,5 +106,12 @@ public $globals = [ ]; ``` +!!! note + + The filter `$aliases` that Shield provides are automatically added for you by the + [Registrar](https://codeigniter.com/user_guide/general/configuration.html#registrars) + class located at **src/Config/Registrar.php**. So you don't need to add in + your **app/Config/Filters.php**. + Check your filters with the [spark routes](https://codeigniter.com/user_guide/incoming/routing.html#spark-routes) command. From 50eaa11c15c8b7282a37d5691f88acd4449990ba Mon Sep 17 00:00:00 2001 From: Ivan <65890952+ivanBell199@users.noreply.github.com> Date: Mon, 30 Oct 2023 01:13:30 +0100 Subject: [PATCH 069/128] Update Auth.php --- src/Language/uk/Auth.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Language/uk/Auth.php b/src/Language/uk/Auth.php index d54b30dd1..3b2219b57 100644 --- a/src/Language/uk/Auth.php +++ b/src/Language/uk/Auth.php @@ -7,8 +7,8 @@ 'unknownAuthenticator' => '{0} не є дійсним автентифікатором.', 'unknownUserProvider' => 'Неможливо визначити постачальника користувача для використання.', 'invalidUser' => 'Неможливо знайти вказаного користувача.', - 'bannedUser' => 'Неможливо увійти, оскільки ви зараз забанені.', - 'logOutBannedUser' => 'Ви вийшли з системи, оскільки вас забанили.', + 'bannedUser' => 'Неможливо увійти, оскільки ви зараз заблоковані.', + 'logOutBannedUser' => 'Ви вийшли з системи, оскільки вас заблокували.', 'badAttempt' => 'Неможливо увійти. Перевірте свої облікові дані.', 'noPassword' => 'Неможливо перевірити користувача без пароля.', 'invalidPassword' => 'Неможливо увійти. Перевірте свій пароль.', @@ -16,21 +16,21 @@ 'badToken' => 'Токен доступу недійсний.', 'oldToken' => 'Термін дії токена доступу минув.', 'noUserEntity' => 'Потрібно вказати сутність користувача для підтвердження пароля.', - 'invalidEmail' => 'Неможливо перевірити, що адреса електронної пошти відповідає зареєстрованій.', + 'invalidEmail' => 'Неможливо перевірити, чи адреса електронної пошти відповідає зареєстрованій.', 'unableSendEmailToUser' => 'Вибачте, під час надсилання електронного листа виникла проблема. Не вдалося надіслати електронний лист на "{0}".', - 'throttled' => 'Забагато запитів зроблено з цієї IP-адреси. Ви можете спробувати ще раз через {0} секунд.', + 'throttled' => 'Із цієї IP-адреси зроблено забагато запитів. Ви можете спробувати ще раз через {0} секунд.', 'notEnoughPrivilege' => 'У вас немає необхідного дозволу для виконання потрібної операції.', // JWT Exceptions - 'invalidJWT' => 'Маркер недійсний.', - 'expiredJWT' => 'Термін дії маркера минув.', - 'beforeValidJWT' => 'Маркер ще не доступний.', + 'invalidJWT' => 'Токен недійсний.', + 'expiredJWT' => 'Термін дії токена минув.', + 'beforeValidJWT' => 'Токен ще не доступний.', 'email' => 'Адреса електронної пошти', 'username' => 'Ім’я користувача', 'password' => 'Пароль', 'passwordConfirm' => 'Пароль (ще раз)', 'haveAccount' => 'Вже є обліковий запис?', - 'token' => '(To be translated) Token', + 'token' => 'Токен', // Buttons 'confirm' => 'Підтвердити', @@ -44,15 +44,15 @@ // Login 'login' => 'Вхід', 'needAccount' => 'Потрібен обліковий запис?', - 'rememberMe' => 'Пам’ятай мене?', + 'rememberMe' => 'Запам’ятати мене', 'forgotPassword' => 'Забули пароль?', - 'useMagicLink' => 'Використовуйте посилання для входу', + 'useMagicLink' => 'Скористайтеся посиланням для входу', 'magicLinkSubject' => 'Ваше посилання для входу', 'magicTokenNotFound' => 'Неможливо перевірити посилання.', 'magicLinkExpired' => 'Вибачте, термін дії посилання закінчився.', 'checkYourEmail' => 'Перевірте свою електронну пошту!', 'magicLinkDetails' => 'Ми щойно надіслали вам електронний лист із посиланням для входу. Він дійсний лише протягом {0} хвилин.', - 'magicLinkDisabled' => '(To be translated) Use of MagicLink is currently not allowed.', + 'magicLinkDisabled' => 'Використання посилання для входу зараз заборонене.', 'successLogout' => 'Ви успішно вийшли.', 'backToLogin' => 'Повернутися до входу', @@ -60,13 +60,13 @@ 'errorPasswordLength' => 'Паролі повинні містити принаймні {0, числових} символів.', 'suggestPasswordLength' => 'Паролі до 255 символів створюють надійніші паролі, які легко запам’ятати.', 'errorPasswordCommon' => 'Пароль не має бути звичайним.', - 'suggestPasswordCommon' => 'Пароль перевірено на більш ніж 65 тисяч часто використовуваних паролів або паролів, які були розкриті через хакерські атаки.', + 'suggestPasswordCommon' => 'Пароль звірено із більш ніж 65 тисячами часто використовуваних паролів або паролів, які були розкриті через хакерські атаки.', 'errorPasswordPersonal' => 'Паролі не можуть містити повторно хешовану особисту інформацію.', - 'suggestPasswordPersonal' => 'Варіанти вашої адреси електронної пошти або імені користувача не повинні використовувати для паролів.', + 'suggestPasswordPersonal' => 'Варіації вашої адреси електронної пошти або імені користувача не повинні використовувати для паролів.', 'errorPasswordTooSimilar' => 'Пароль занадто схожий на ім’я користувача.', 'suggestPasswordTooSimilar' => 'Не використовуйте частини свого імені користувача в паролі.', 'errorPasswordPwned' => 'Пароль {0} було розкрито внаслідок витоку даних і було виявлено {1} разів у {2} зламаних паролів.', - 'suggestPasswordPwned' => '{0} ніколи не слід використовувати як пароль. Якщо ви використовуєте його десь, негайно змініть його.', + 'suggestPasswordPwned' => '{0} ніколи не слід використовувати як пароль. Якщо ви вже використовуєте його десь, негайно змініть його.', 'errorPasswordEmpty' => 'Необхідно ввести пароль.', 'errorPasswordTooLongBytes' => 'Довжина пароля не може перевищувати {param} байт.', 'passwordChangeSuccess' => 'Пароль успішно змінено', @@ -86,7 +86,7 @@ 'emailConfirmCode' => 'Введіть 6-значний код, який ми щойно надіслали на вашу адресу електронної пошти.', 'email2FASubject' => 'Ваш код автентифікації', 'email2FAMailBody' => 'Ваш код автентифікації:', - 'invalid2FAToken' => 'Код невірний.', + 'invalid2FAToken' => 'Код недійсний.', 'need2FA' => 'Ви повинні пройти двофакторну перевірку.', 'needVerification' => 'Перевірте свою електронну пошту, щоб завершити активацію облікового запису.', @@ -104,5 +104,5 @@ 'missingTitle' => 'Групи повинні мати назву.', // Permissions - 'unknownPermission' => '{0} не дійсний дозвіл.', + 'unknownPermission' => '{0} недійсний дозвіл.', ]; From 5852f30c50cf5b0588fe7fc8ac3746f9b1600a36 Mon Sep 17 00:00:00 2001 From: Ivan <65890952+ivanBell199@users.noreply.github.com> Date: Mon, 30 Oct 2023 01:16:05 +0100 Subject: [PATCH 070/128] Create ru/Auth.php --- src/Language/ru/Auth.php | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/Language/ru/Auth.php diff --git a/src/Language/ru/Auth.php b/src/Language/ru/Auth.php new file mode 100644 index 000000000..f7ddc2cac --- /dev/null +++ b/src/Language/ru/Auth.php @@ -0,0 +1,108 @@ + '{0} не является действительным аутентификатором.', + 'unknownUserProvider' => 'Не удалось определить поставщика пользователей.', + 'invalidUser' => 'Не удалось найти указанного пользователя.', + 'bannedUser' => 'Невозможно войти, так как вы заблокированы.', + 'logOutBannedUser' => 'Вы вышли из системы, так как вас заблокировали.', + 'badAttempt' => 'Не удалось войти. Проверьте свои учётные данные.', + 'noPassword' => 'Невозможно проверить пользователя без пароля.', + 'invalidPassword' => 'Не удалось войти. Проверьте свой пароль.', + 'noToken' => 'У каждого запроса должен быть токен носителя в заголовке {0}.', + 'badToken' => 'Токен доступа недействителен.', + 'oldToken' => 'Срок действия токена доступа истёк.', + 'noUserEntity' => 'Для проверки пароля необходимо предоставить сущность пользователя.', + 'invalidEmail' => 'Не удалось подтвердить, что адрес электронной почты соответствует зарегистрированному.', + 'unableSendEmailToUser' => 'Извините, возникла проблема с отправкой электронного письма. Не удалось отправить электронное письмо на "{0}".', + 'throttled' => 'С этого IP-адреса было сделано слишком много запросов. Вы можете попробовать снова через {0} секунд.', + 'notEnoughPrivilege' => 'У вас нет необходимых разрешений для выполнения требуемой операции.', + // JWT Exceptions + 'invalidJWT' => 'Токен недействителен.', + 'expiredJWT' => 'Срок действия токена истёк.', + 'beforeValidJWT' => 'Токен ещё не доступен.', + + 'email' => 'Адрес электронной почты', + 'username' => 'Имя пользователя', + 'password' => 'Пароль', + 'passwordConfirm' => 'Пароль (ещё раз)', + 'haveAccount' => 'Уже есть учётная запись?', + 'token' => 'Токен', + + // Buttons + 'confirm' => 'Подтвердить', + 'send' => 'Отправить', + + // Registration + 'register' => 'Зарегистрироваться', + 'registerDisabled' => 'Регистрация в настоящее время запрещена.', + 'registerSuccess' => 'Добро пожаловать на борт!', + + // Login + 'login' => 'Вход', + 'needAccount' => 'Нужна учётная запись?', + 'rememberMe' => 'Запомнить меня', + 'forgotPassword' => 'Забыли пароль?', + 'useMagicLink' => 'Воспользуйтесь ссылкой для входа', + 'magicLinkSubject' => 'Ваша ссылка для входа', + 'magicTokenNotFound' => 'Не удалось проверить ссылку.', + 'magicLinkExpired' => 'Извините, срок действия ссылки истёк.', + 'checkYourEmail' => 'Проверьте свою электронную почту!', + 'magicLinkDetails' => 'Мы только что отправили вам электронное письмо со ссылкой для входа. Она действительна только в течение {0} минут.', + 'magicLinkDisabled' => 'Использование ссылки для входа в настоящее время запрещено.', + 'successLogout' => 'Вы успешно вышли.', + 'backToLogin' => 'Вернуться ко входу', + + // Passwords + 'errorPasswordLength' => 'Пароли должны содержать не менее {0, number} символов.', + 'suggestPasswordLength' => 'Фразы длиной до 255 символов являются более надёжными паролями, которые легко запомнить.', + 'errorPasswordCommon' => 'Пароль не должен быть распространённым.', + 'suggestPasswordCommon' => 'Пароль был проверен на соответствие более чем 65 тысячам часто используемых паролей или паролей, которые были раскрыты в результате хакерских атак.', + 'errorPasswordPersonal' => 'Пароли не могут содержать повторно хешированную личную информацию.', + 'suggestPasswordPersonal' => 'Вариации вашего адреса электронной почты или имени пользователя не следует использовать для паролей.', + 'errorPasswordTooSimilar' => 'Пароль слишком похож на имя пользователя.', + 'suggestPasswordTooSimilar' => 'Не используйте части вашего имени пользователя в пароле.', + 'errorPasswordPwned' => 'Пароль {0} был раскрыт в результате утечки данных и был обнаружен {1, number} раз в {2} скомпрометированных паролях.', + 'suggestPasswordPwned' => '{0} никогда не следует использовать в качестве пароля. Если вы уже используете его где-либо, немедленно измените его.', + 'errorPasswordEmpty' => 'Требуется пароль.', + 'errorPasswordTooLongBytes' => 'Длина пароля не может превышать {param} байт.', + 'passwordChangeSuccess' => 'Пароль успешно изменён', + 'userDoesNotExist' => 'Пароль не изменён. Пользователь не существует', + 'resetTokenExpired' => 'К сожалению, срок действия вашего токена сброса истёк.', + + // Email Globals + 'emailInfo' => 'Некоторые сведения о человеке:', + 'emailIpAddress' => 'IP-адрес:', + 'emailDevice' => 'Устройство:', + 'emailDate' => 'Дата:', + + // 2FA + 'email2FATitle' => 'Двухфакторная аутентификация', + 'confirmEmailAddress' => 'Подтвердите свой адрес электронной почты.', + 'emailEnterCode' => 'Подтвердите свой Email', + 'emailConfirmCode' => 'Введите 6-значный код, который мы только что отправили на ваш адрес электронной почты.', + 'email2FASubject' => 'Ваш код аутентификации', + 'email2FAMailBody' => 'Ваш код аутентификации:', + 'invalid2FAToken' => 'Код неверный.', + 'need2FA' => 'Вы должны пройти двухфакторную проверку.', + 'needVerification' => 'Проверьте свою электронную почту, чтобы завершить активацию учётной записи.', + + // Activate + 'emailActivateTitle' => 'Активация электронной почты', + 'emailActivateBody' => 'Мы только что отправили вам электронное письмо с кодом для подтверждения вашего адреса электронной почты. Скопируйте этот код и вставьте его ниже.', + 'emailActivateSubject' => 'Ваш код активации', + 'emailActivateMailBody' => 'Пожалуйста, воспользуйтесь приведённым ниже кодом для активации учетной записи и начала работы с сайтом.', + 'invalidActivateToken' => 'Код неверный.', + 'needActivate' => 'Вы должны завершить регистрацию, подтвердив код, отправленный на ваш адрес электронной почты.', + 'activationBlocked' => 'Вы должны активировать свою учетную запись перед входом в систему.', + + // Groups + 'unknownGroup' => '{0} не является действительной группой.', + 'missingTitle' => 'Группы должны иметь название.', + + // Permissions + 'unknownPermission' => '{0} не является действительным разрешением.', +]; From d3b8bb8c053efddd4ab545d3c43c5bdfe5b11f9b Mon Sep 17 00:00:00 2001 From: Ivan <65890952+ivanBell199@users.noreply.github.com> Date: Mon, 30 Oct 2023 01:17:18 +0100 Subject: [PATCH 071/128] Create RussianTranslationTest.php --- tests/Language/RussianTranslationTest.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/Language/RussianTranslationTest.php diff --git a/tests/Language/RussianTranslationTest.php b/tests/Language/RussianTranslationTest.php new file mode 100644 index 000000000..422deb6ff --- /dev/null +++ b/tests/Language/RussianTranslationTest.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Language; + +/** + * @internal + */ +final class RussianTranslationTest extends AbstractTranslationTestCase +{ +} From 2ac8ce7bcf23d6bd1eccdfc77da46768d9211748 Mon Sep 17 00:00:00 2001 From: Ivan <65890952+ivanBell199@users.noreply.github.com> Date: Mon, 30 Oct 2023 01:17:55 +0100 Subject: [PATCH 072/128] Update AbstractTranslationTestCase.php --- tests/Language/AbstractTranslationTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Language/AbstractTranslationTestCase.php b/tests/Language/AbstractTranslationTestCase.php index b3b45a21f..0d8efe48c 100644 --- a/tests/Language/AbstractTranslationTestCase.php +++ b/tests/Language/AbstractTranslationTestCase.php @@ -68,7 +68,7 @@ abstract class AbstractTranslationTestCase extends TestCase // PolishTranslationTest::class => 'pl', PortugueseTranslationTest::class => 'pt', BrazilianTranslationTest::class => 'pt-BR', - // RussianTranslationTest::class => 'ru', + RussianTranslationTest::class => 'ru', // SinhalaTranslationTest::class => 'si', SlovakTranslationTest::class => 'sk', SerbianTranslationTest::class => 'sr', From a0fa3b82d08e28ab630759397a5b5dc805f5c626 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 1 Nov 2023 00:01:57 +0330 Subject: [PATCH 073/128] docs: fix forum link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8df491a39..d94d817b8 100644 --- a/README.md +++ b/README.md @@ -58,13 +58,13 @@ and authorization purposes in web applications. * Flexible Groups-based access control (think Roles, but more flexible) * Users can be granted additional Permissions -See the [An Official Auth Library](https://codeigniter.com/news/shield) for more Info. +See the [An Official Auth Library](https://forum.codeigniter.com/showthread.php?tid=82003) for more Info. ## Getting Started ### Prerequisites -Usage of Shield requires the following: +sage of Shield requires the following: - A [CodeIgniter 4.3.5+](https://github.com/codeigniter4/CodeIgniter4/) based project - [Composer](https://getcomposer.org/) for package management From 8e4192230e3e2c8348c75c05a03f70fd703d3f36 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 1 Nov 2023 00:07:17 +0330 Subject: [PATCH 074/128] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d94d817b8..b6f93e9a4 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ See the [An Official Auth Library](https://forum.codeigniter.com/showthread.php? ### Prerequisites -sage of Shield requires the following: +Usage of Shield requires the following: - A [CodeIgniter 4.3.5+](https://github.com/codeigniter4/CodeIgniter4/) based project - [Composer](https://getcomposer.org/) for package management From 3fb1ae7a505c93cc6ed05ab00750a0a4c5a2ebb9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 10 Nov 2023 10:43:08 +0330 Subject: [PATCH 075/128] docs: fix change-available-groups links --- src/Config/AuthGroups.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/AuthGroups.php b/src/Config/AuthGroups.php index 3b92aee82..9b30cc7e6 100644 --- a/src/Config/AuthGroups.php +++ b/src/Config/AuthGroups.php @@ -29,7 +29,7 @@ class AuthGroups extends BaseConfig * * @var array> * - * @see https://github.com/codeigniter4/shield/blob/develop/docs/quickstart.md#change-available-groups for more info + * @see https://codeigniter4.github.io/shield/quick_start_guide/using_authorization/#change-available-groups for more info */ public array $groups = [ 'superadmin' => [ From 668305ce45c8e5e671fb0eb59b988ec34298acda Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 10 Nov 2023 11:02:19 +0330 Subject: [PATCH 076/128] docs: fix protecting-pages link --- src/Config/Auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/Auth.php b/src/Config/Auth.php index 40b57c2ae..079da237a 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -154,7 +154,7 @@ class Auth extends BaseConfig * logged-in user on every page request. * This feature only works when session/tokens filter is active. * - * @see https://codeigniter4.github.io/shield/install/#protect-all-pages for set filters. + * @see https://codeigniter4.github.io/shield/quick_start_guide/using_session_auth/#protecting-pages for set filters. */ public bool $recordActiveDate = true; From 94d51cd539a7c170a53cee889dd23cd13aebbf65 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 14 Nov 2023 01:49:40 +0330 Subject: [PATCH 077/128] update rector requirement from 0.18.6 to 0.18.7 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aeaf21370..69f4d4b60 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "mockery/mockery": "^1.0", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-strict-rules": "^1.5", - "rector/rector": "0.18.6" + "rector/rector": "0.18.7" }, "provide": { "codeigniter4/authentication-implementation": "1.0" From c35a97366a9e73943c27ff67bc6b59be45c15d2e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 14 Nov 2023 01:50:23 +0330 Subject: [PATCH 078/128] chore: run rector 0.18.7 --- tests/Unit/NothingPersonalValidatorTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Unit/NothingPersonalValidatorTest.php b/tests/Unit/NothingPersonalValidatorTest.php index b3e7d8e77..9bdfeb77a 100644 --- a/tests/Unit/NothingPersonalValidatorTest.php +++ b/tests/Unit/NothingPersonalValidatorTest.php @@ -281,7 +281,8 @@ public static function provideMaxSimilarityZeroTurnsOffSimilarityCalculation(): [ 66, false, - ], [ + ], + [ 0, true, ], @@ -314,7 +315,8 @@ public static function provideCheckPasswordWithBadEmail(): iterable [ 'test', true, - ], [ + ], + [ 'test@example', true, ], From b90bdd3d06eae6b899112f00285636ebfde2d68c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 22:05:57 +0000 Subject: [PATCH 079/128] chore(deps-dev): update rector/rector requirement from 0.18.7 to 0.18.8 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.18.7...0.18.8) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 69f4d4b60..50e59bfb7 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "mockery/mockery": "^1.0", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-strict-rules": "^1.5", - "rector/rector": "0.18.7" + "rector/rector": "0.18.8" }, "provide": { "codeigniter4/authentication-implementation": "1.0" From 893524816697910ccd6920b672c1868afb29ebb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Nov 2023 14:52:52 +0000 Subject: [PATCH 080/128] chore(deps-dev): update rector/rector requirement from 0.18.8 to 0.18.10 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.18.8...0.18.10) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 50e59bfb7..f7eed49ca 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "mockery/mockery": "^1.0", "phpstan/extension-installer": "^1.3", "phpstan/phpstan-strict-rules": "^1.5", - "rector/rector": "0.18.8" + "rector/rector": "0.18.10" }, "provide": { "codeigniter4/authentication-implementation": "1.0" From 0dd23925363f4c0c30b97d568f3da26d759aed6a Mon Sep 17 00:00:00 2001 From: Vasyl Zavalko <51149485+vasylzavalko@users.noreply.github.com> Date: Sun, 19 Nov 2023 11:26:32 +0200 Subject: [PATCH 081/128] Update Auth.php Invalid message format --- src/Language/uk/Auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/uk/Auth.php b/src/Language/uk/Auth.php index 3b2219b57..98e2aa9b0 100644 --- a/src/Language/uk/Auth.php +++ b/src/Language/uk/Auth.php @@ -57,7 +57,7 @@ 'backToLogin' => 'Повернутися до входу', // Passwords - 'errorPasswordLength' => 'Паролі повинні містити принаймні {0, числових} символів.', + 'errorPasswordLength' => 'Паролі повинні містити принаймні {0, number} символів.', 'suggestPasswordLength' => 'Паролі до 255 символів створюють надійніші паролі, які легко запам’ятати.', 'errorPasswordCommon' => 'Пароль не має бути звичайним.', 'suggestPasswordCommon' => 'Пароль звірено із більш ніж 65 тисячами часто використовуваних паролів або паролів, які були розкриті через хакерські атаки.', From a76acb437abc7ae8d5fe573ad0686e3f050fcd62 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Sun, 19 Nov 2023 22:51:55 +0330 Subject: [PATCH 082/128] lang: [tr] fix param in `errorPasswordPwned` --- src/Language/tr/Auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/tr/Auth.php b/src/Language/tr/Auth.php index 2b35941d7..56c111fee 100644 --- a/src/Language/tr/Auth.php +++ b/src/Language/tr/Auth.php @@ -65,7 +65,7 @@ 'suggestPasswordPersonal' => 'E-posta adresiniz veya kullanıcı adınızdaki varyasyonlar, şifreler için kullanılmamalıdır.', 'errorPasswordTooSimilar' => 'Şifre, kullanıcı adınıza çok benziyor.', 'suggestPasswordTooSimilar' => 'Kullanıcı adınızın bazı kısımlarını şifrenizde kullanmayın.', - 'errorPasswordPwned' => '{0} şifresi, bir veri ihlali nedeniyle açığa çıktı ve güvenliği ihlal edilmiş şifrelerin {2} tanesinde {1, sayı} kez görüldü.', + 'errorPasswordPwned' => '{0} şifresi, bir veri ihlali nedeniyle açığa çıktı ve güvenliği ihlal edilmiş şifrelerin {2} tanesinde {1, number} kez görüldü.', 'suggestPasswordPwned' => '{0} asla şifre olarak kullanılmamalıdır. Herhangi bir yerde kullanıyorsanız hemen değiştirin.', 'errorPasswordEmpty' => 'Şifre gerekli.', 'errorPasswordTooLongBytes' => 'Şifre uzunluğu {param} baytı geçemez.', From b2908f9efc4706941d99435cb04b21dbaa47b7b7 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Sun, 19 Nov 2023 22:52:47 +0330 Subject: [PATCH 083/128] lang: [uk] fix param in `errorPasswordPwned` --- src/Language/uk/Auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/uk/Auth.php b/src/Language/uk/Auth.php index 98e2aa9b0..318ad1906 100644 --- a/src/Language/uk/Auth.php +++ b/src/Language/uk/Auth.php @@ -65,7 +65,7 @@ 'suggestPasswordPersonal' => 'Варіації вашої адреси електронної пошти або імені користувача не повинні використовувати для паролів.', 'errorPasswordTooSimilar' => 'Пароль занадто схожий на ім’я користувача.', 'suggestPasswordTooSimilar' => 'Не використовуйте частини свого імені користувача в паролі.', - 'errorPasswordPwned' => 'Пароль {0} було розкрито внаслідок витоку даних і було виявлено {1} разів у {2} зламаних паролів.', + 'errorPasswordPwned' => 'Пароль {0} було розкрито внаслідок витоку даних і було виявлено {1, number} разів у {2} зламаних паролів.', 'suggestPasswordPwned' => '{0} ніколи не слід використовувати як пароль. Якщо ви вже використовуєте його десь, негайно змініть його.', 'errorPasswordEmpty' => 'Необхідно ввести пароль.', 'errorPasswordTooLongBytes' => 'Довжина пароля не може перевищувати {param} байт.', From ae8ecaf99ba748c9e4df1e4fa8cafd247c02279b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Mon, 20 Nov 2023 21:24:16 +0330 Subject: [PATCH 084/128] style: fix code styling by cs-fix --- src/Language/ru/Auth.php | 9 +++++++++ tests/Language/RussianTranslationTest.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Language/ru/Auth.php b/src/Language/ru/Auth.php index f7ddc2cac..4efd5c58b 100644 --- a/src/Language/ru/Auth.php +++ b/src/Language/ru/Auth.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + return [ // Exceptions 'unknownAuthenticator' => '{0} не является действительным аутентификатором.', diff --git a/tests/Language/RussianTranslationTest.php b/tests/Language/RussianTranslationTest.php index 422deb6ff..313668214 100644 --- a/tests/Language/RussianTranslationTest.php +++ b/tests/Language/RussianTranslationTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter 4 framework. + * This file is part of CodeIgniter Shield. * * (c) CodeIgniter Foundation * From 6c7c18eb4867c01365c5b7ea8b1b2c6097c9b0e3 Mon Sep 17 00:00:00 2001 From: tswagger Date: Mon, 30 Oct 2023 15:23:22 -0500 Subject: [PATCH 085/128] Initial update to encrypt secretKey --- .../Authenticators/HmacSha256.php | 17 ++++++++- src/Config/AuthToken.php | 36 +++++++++++++++++++ src/Models/UserIdentityModel.php | 25 +++++++++++-- .../Authenticators/HmacAuthenticatorTest.php | 18 ++++++---- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/Authentication/Authenticators/HmacSha256.php b/src/Authentication/Authenticators/HmacSha256.php index 42a6cdc31..dab39be6b 100644 --- a/src/Authentication/Authenticators/HmacSha256.php +++ b/src/Authentication/Authenticators/HmacSha256.php @@ -18,12 +18,15 @@ use CodeIgniter\Shield\Authentication\AuthenticationException; use CodeIgniter\Shield\Authentication\AuthenticatorInterface; use CodeIgniter\Shield\Config\Auth; +use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Exceptions\InvalidArgumentException; use CodeIgniter\Shield\Models\TokenLoginModel; use CodeIgniter\Shield\Models\UserIdentityModel; use CodeIgniter\Shield\Models\UserModel; use CodeIgniter\Shield\Result; +use Config\Encryption; +use Config\Services; class HmacSha256 implements AuthenticatorInterface { @@ -159,8 +162,20 @@ public function check(array $credentials): Result ]); } + /** @var AuthToken $authConfig */ + $authConfig = config('AuthToken'); + $config = new Encryption(); + + $config->key = $authConfig->hmacEncryptionKey; + $config->driver = $authConfig->hmacEncryptionDriver; + $config->digest = $authConfig->hmacEncryptionDigest; + + // decrypt secret key so signature can be validated + $encrypter = Services::encrypter($config); + $secretKey = $encrypter->decrypt(hex2bin($token->secret2)); + // Check signature... - $hash = hash_hmac('sha256', $credentials['body'], $token->secret2); + $hash = hash_hmac('sha256', $credentials['body'], $secretKey); if ($hash !== $signature) { return new Result([ 'success' => false, diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 8ff13f97e..1037ef04e 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -63,4 +63,40 @@ class AuthToken extends BaseConfig * HMAC SHA256 byte size */ public int $hmacSecretKeyByteSize = 32; + + /** + * -------------------------------------------------------------------- + * HMAC encryption key + * -------------------------------------------------------------------- + * Key to be used when encrypting HMAC Secret Key for storage. + * + * @see https://codeigniter.com/user_guide/libraries/encryption.html + */ + public string $hmacEncryptionKey = ''; + + /** + * -------------------------------------------------------------------- + * HMAC encryption driver + * -------------------------------------------------------------------- + * Driver to be used when encrypting HMAC Secret Key for storage. + * + * Available drivers: + * OpenSSL + * Sodium + * + * @see https://codeigniter.com/user_guide/libraries/encryption.html + */ + public string $hmacEncryptionDriver = 'OpenSSL'; + + /** + * -------------------------------------------------------------------- + * HMAC encryption digest + * -------------------------------------------------------------------- + * Digest to be used when encrypting HMAC Secret Key for storage. + * + * e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. + * + * @see https://codeigniter.com/user_guide/libraries/encryption.html + */ + public string $hmacEncryptionDigest = 'SHA512'; } diff --git a/src/Models/UserIdentityModel.php b/src/Models/UserIdentityModel.php index 9ccb029ff..80e1ebcac 100644 --- a/src/Models/UserIdentityModel.php +++ b/src/Models/UserIdentityModel.php @@ -18,11 +18,14 @@ use CodeIgniter\Shield\Authentication\Authenticators\HmacSha256; use CodeIgniter\Shield\Authentication\Authenticators\Session; use CodeIgniter\Shield\Authentication\Passwords; +use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Entities\UserIdentity; use CodeIgniter\Shield\Exceptions\LogicException; use CodeIgniter\Shield\Exceptions\ValidationException; +use Config\Encryption; +use Config\Services; use Exception; use Faker\Generator; use ReflectionException; @@ -251,20 +254,38 @@ public function generateHmacToken(User $user, string $name, array $scopes = ['*' { $this->checkUserId($user); + /** @var AuthToken $authConfig */ + $authConfig = config('AuthToken'); + $config = new Encryption(); + + $config->key = $authConfig->hmacEncryptionKey; + $config->driver = $authConfig->hmacEncryptionDriver; + $config->digest = $authConfig->hmacEncryptionDigest; + + // Generate and encrypt secret key + $encrypter = Services::encrypter($config); + $rawSecretKey = bin2hex(random_bytes(config('AuthToken')->hmacSecretKeyByteSize)); + $secretKey = bin2hex($encrypter->encrypt($rawSecretKey)); + $return = $this->insert([ 'type' => HmacSha256::ID_TYPE_HMAC_TOKEN, 'user_id' => $user->id, 'name' => $name, 'secret' => bin2hex(random_bytes(16)), // Key - 'secret2' => bin2hex(random_bytes(config('AuthToken')->hmacSecretKeyByteSize)), // Secret Key + 'secret2' => $secretKey, 'extra' => serialize($scopes), ]); $this->checkQueryReturn($return); - return $this + /** @var AccessToken $token */ + $token = $this ->asObject(AccessToken::class) ->find($this->getInsertID()); + + $token->rawSecretKey = $rawSecretKey; + + return $token; } /** diff --git a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php index 7c601c113..c3af6f0ca 100644 --- a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php @@ -13,6 +13,7 @@ namespace Tests\Authentication\Authenticators; +use CodeIgniter\Encryption\Encryption; use CodeIgniter\I18n\Time; use CodeIgniter\Shield\Authentication\Authentication; use CodeIgniter\Shield\Authentication\AuthenticationException; @@ -37,6 +38,9 @@ protected function setUp(): void { parent::setUp(); + $authConfig = config('AuthToken'); + $authConfig->hmacEncryptionKey = Encryption::createKey(); + $config = new Auth(); $auth = new Authentication($config); $auth->setProvider(model(UserModel::class)); @@ -109,7 +113,7 @@ public function testLoginByIdWithToken(): void $user = fake(UserModel::class); $token = $user->generateHmacToken('foo'); - $rawToken = $this->generateRawHeaderToken($token->secret, $token->secret2, 'bar'); + $rawToken = $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'bar'); $this->setRequestHeader($rawToken); $this->auth->loginById($user->id); @@ -126,7 +130,7 @@ public function testLoginByIdWithMultipleTokens(): void $token1 = $user->generateHmacToken('foo'); $user->generateHmacToken('bar'); - $this->setRequestHeader($this->generateRawHeaderToken($token1->secret, $token1->secret2, 'bar')); + $this->setRequestHeader($this->generateRawHeaderToken($token1->secret, $token1->rawSecretKey, 'bar')); $this->auth->loginById($user->id); @@ -170,7 +174,7 @@ public function testCheckOldToken(): void $identities->save($token); $result = $this->auth->check([ - 'token' => $this->generateRawHeaderToken($token->secret, $token->secret2, 'bar'), + 'token' => $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'bar'), 'body' => 'bar', ]); @@ -190,7 +194,7 @@ public function testCheckSuccess(): void 'last_used_at' => null, ]); - $rawToken = $this->generateRawHeaderToken($token->secret, $token->secret2, 'bar'); + $rawToken = $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'bar'); $result = $this->auth->check([ 'token' => $rawToken, @@ -220,7 +224,7 @@ public function testCheckBadToken(): void 'last_used_at' => null, ]); - $rawToken = $this->generateRawHeaderToken($token->secret, $token->secret2, 'foobar'); + $rawToken = $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'foobar'); $result = $this->auth->check([ 'token' => $rawToken, @@ -254,7 +258,7 @@ public function testAttemptSuccess(): void /** @var User $user */ $user = fake(UserModel::class); $token = $user->generateHmacToken('foo'); - $rawToken = $this->generateRawHeaderToken($token->secret, $token->secret2, 'bar'); + $rawToken = $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'bar'); $this->setRequestHeader($rawToken); $result = $this->auth->attempt([ @@ -294,7 +298,7 @@ public function testAttemptBanned(): void $user->ban('Test ban.'); $token = $user->generateHmacToken('foo'); - $rawToken = $this->generateRawHeaderToken($token->secret, $token->secret2, 'bar'); + $rawToken = $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'bar'); $this->setRequestHeader($rawToken); $result = $this->auth->attempt([ From 6d61e6d4dd732d5aa9ff8cfab1cac6408b6ffa02 Mon Sep 17 00:00:00 2001 From: tswagger Date: Mon, 30 Oct 2023 16:40:05 -0500 Subject: [PATCH 086/128] Adjustment to test scripts to account for encryption. --- docs/guides/api_hmac_keys.md | 12 ++++++++++ docs/references/authentication/hmac.md | 11 +++++++++ .../Authentication/Filters/HmacFilterTest.php | 23 +++++++++++++------ tests/Authentication/HasHmacTokensTest.php | 5 ++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index b0a565537..c0e66b63a 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -87,6 +87,18 @@ $user->revokeHmacToken($key); $user->revokeAllHmacTokens(); ``` +## HMAC Secret Key Encryption + +The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key +`$hmacEncryptionKey` in **app/Config/AuthToken.php**. This should be set using .env and/or system environment variables. +Instructions on how to do that can be found in the +[Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) +section of the CodeIgniter 4 documentation. + +You will also be able to adjust the default Driver `$hmacEncryptionDriver` and the default Digest +`$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. + + ## Protecting Routes The first way to specify which routes are protected is to use the `hmac` controller filter. diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index c8c504453..3d59fee23 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -156,3 +156,14 @@ if ($user->hmacTokenCant('forums.manage')) { // do something.... } ``` + +## HMAC Secret Key Encryption + +The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key +`$hmacEncryptionKey` in **app/Config/AuthToken.php**. This should be set using .env and/or system environment variables. +Instructions on how to do that can be found in the +[Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) +section of the CodeIgniter 4 documentation. + +You will also be able to adjust the default Driver `$hmacEncryptionDriver` and the default Digest +`$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. diff --git a/tests/Authentication/Filters/HmacFilterTest.php b/tests/Authentication/Filters/HmacFilterTest.php index 14531a773..c88ecfbbc 100644 --- a/tests/Authentication/Filters/HmacFilterTest.php +++ b/tests/Authentication/Filters/HmacFilterTest.php @@ -13,6 +13,7 @@ namespace Tests\Authentication\Filters; +use CodeIgniter\Encryption\Encryption; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Filters\HmacAuth; @@ -30,6 +31,14 @@ final class HmacFilterTest extends AbstractFilterTestCase protected string $alias = 'hmacAuth'; protected string $classname = HmacAuth::class; + protected function setUp(): void + { + parent::setUp(); + + $authConfig = config('AuthToken'); + $authConfig->hmacEncryptionKey = Encryption::createKey(); + } + public function testFilterNotAuthorized(): void { $result = $this->call('get', 'protected-route'); @@ -47,7 +56,7 @@ public function testFilterSuccess(): void $user = fake(UserModel::class); $token = $user->generateHmacToken('foo'); - $rawToken = $this->generateRawHeaderToken($token->secret, $token->secret2, ''); + $rawToken = $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, ''); $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $rawToken]) ->get('protected-route'); @@ -68,7 +77,7 @@ public function testFilterInvalidSignature(): void $user = fake(UserModel::class); $token = $user->generateHmacToken('foo'); - $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->secret2, 'bar')]) + $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, 'bar')]) ->get('protected-route'); $result->assertStatus(401); @@ -80,7 +89,7 @@ public function testRecordActiveDate(): void $user = fake(UserModel::class); $token = $user->generateHmacToken('foo'); - $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->secret2, '')]) + $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, '')]) ->get('protected-route'); // Last Active should be greater than 'updated_at' column @@ -97,7 +106,7 @@ public function testFiltersProtectsWithScopes(): void $token2 = $user2->generateHmacToken('foo', ['users-write']); // User 1 should be able to access the route - $result1 = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token1->secret, $token1->secret2, '')]) + $result1 = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token1->secret, $token1->rawSecretKey, '')]) ->get('protected-user-route'); $result1->assertStatus(200); @@ -105,7 +114,7 @@ public function testFiltersProtectsWithScopes(): void $this->assertGreaterThan(auth('hmac')->user()->updated_at, auth('hmac')->user()->last_active); // User 2 should NOT be able to access the route - $result2 = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token2->secret, $token2->secret2, '')]) + $result2 = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token2->secret, $token2->rawSecretKey, '')]) ->get('protected-user-route'); $result2->assertStatus(401); @@ -120,7 +129,7 @@ public function testBlocksInactiveUsers(): void // Activation only required with email activation setting('Auth.actions', ['register' => null]); - $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->secret2, '')]) + $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, '')]) ->get('protected-route'); $result->assertStatus(200); @@ -129,7 +138,7 @@ public function testBlocksInactiveUsers(): void // Now require user activation and try again setting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); - $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->secret2, '')]) + $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, '')]) ->get('protected-route'); $result->assertStatus(403); diff --git a/tests/Authentication/HasHmacTokensTest.php b/tests/Authentication/HasHmacTokensTest.php index c2b0c158c..e1a59a3e0 100644 --- a/tests/Authentication/HasHmacTokensTest.php +++ b/tests/Authentication/HasHmacTokensTest.php @@ -13,6 +13,7 @@ namespace Tests\Authentication; +use CodeIgniter\Encryption\Encryption; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Models\UserIdentityModel; @@ -30,6 +31,9 @@ protected function setUp(): void { parent::setUp(); + $authConfig = config('AuthToken'); + $authConfig->hmacEncryptionKey = Encryption::createKey(); + $this->user = fake(UserModel::class); $this->db->table($this->tables['identities'])->truncate(); } @@ -43,6 +47,7 @@ public function testGenerateHmacToken(): void $this->assertIsString($token->secret); $this->assertIsString($token->secret2); + $this->assertIsString($token->rawSecretKey); // All scopes are assigned by default via wildcard $this->assertSame(['*'], $token->scopes); From 4dc28ac943cc007a3ac8c9cede397d96c40c13ec Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 31 Oct 2023 15:27:03 -0500 Subject: [PATCH 087/128] Added migration and updates to documentation --- UPGRADING.md | 22 ++++- docs/guides/api_hmac_keys.md | 8 +- docs/references/authentication/hmac.md | 10 +- .../Authenticators/HmacSha256.php | 4 +- .../2023-10-30-222755_EncryptHmacKeys.php | 93 +++++++++++++++++++ .../Authenticators/HmacAuthenticatorTest.php | 4 - .../Authentication/Filters/HmacFilterTest.php | 9 -- tests/Authentication/HasHmacTokensTest.php | 8 +- tests/_support/TestCase.php | 2 + 9 files changed, 129 insertions(+), 31 deletions(-) create mode 100644 src/Database/Migrations/2023-10-30-222755_EncryptHmacKeys.php diff --git a/UPGRADING.md b/UPGRADING.md index 6a558a894..66cf193fe 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,25 @@ # Upgrade Guide +## Version 1.0.0-beta.8 to 1.0.0-beta.9 + +### Mandatory Config Changes + +#### Config\AuthToken + +If you are using the HMAC authentication you need to update the encryption settings in **app/Config/AuthToken.php**. +You will need to update and set the encryption key `$hmacEncryptionKey`. This should be set using .env and/or system +environment variables. Instructions on how to do that can be found in the +[Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) +section of the CodeIgniter 4 documentation. + +You also may wish to adjust the default Driver `$hmacEncryptionDriver` and the default Digest `$hmacEncryptionDigest`, +these currently default to `'OpenSSL'` and `'SHA512'` respectively. + +### Database Migrations + +After updating the `$hmacEncryptionKey` value, you will need to run `php spark migrate --all` in order to encrypt any +existing HMAC tokens. + ## Version 1.0.0-beta.7 to 1.0.0-beta.8 ### Mandatory Config Changes @@ -45,7 +65,7 @@ protected function redirectToDeniedUrl(): RedirectResponse { return redirect()->to(config('Auth')->groupDeniedRedirect()) ->with('error', lang('Auth.notEnoughPrivilege')); -} +} ``` ## Version 1.0.0-beta.6 to 1.0.0-beta.7 diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index c0e66b63a..d37b09d04 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -16,8 +16,8 @@ API. When making requests using HMAC keys, the token should be included in the ` Tokens are issued with the `generateHmacToken()` method on the user. This returns a `CodeIgniter\Shield\Entities\AccessToken` instance. These shared keys are saved to the database in plain text. The -`AccessToken` object returned when you generate it will include a `secret` field which will be the `key` and a `secret2` -field that will be the `secretKey`. You should display the `secretKey` to your user once, so they have a chance to copy +`AccessToken` object returned when you generate it will include a `secret` field which will be the '_key_' and a `rawSecretKey` +field that will be the '_secretKey_'. You should display the '_secretKey_' to your user once, so they have a chance to copy it somewhere safe, as this is the only time you should reveal this key. The `generateHmacToken()` method requires a name for the token. These are free strings and are often used to identify @@ -27,7 +27,7 @@ the user/device the token was generated from/for, like 'Johns MacBook Air'. $routes->get('hmac/token', static function () { $token = auth()->user()->generateHmacToken(service('request')->getVar('token_name')); - return json_encode(['key' => $token->secret, 'secretKey' => $token->secret2]); + return json_encode(['key' => $token->secret, 'secretKey' => $token->rawSecretKey]); }); ``` @@ -62,7 +62,7 @@ token is granted all access to all scopes. This might be enough for a smaller AP ```php $token = $user->generateHmacToken('token-name', ['users-read']); -return json_encode(['key' => $token->secret, 'secretKey' => $token->secret2]); +return json_encode(['key' => $token->secret, 'secretKey' => $token->rawSecretKey]); ``` !!! note diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 3d59fee23..e319957d2 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -68,18 +68,18 @@ $token = $user->generateHmacToken('Work Laptop'); This creates the keys/tokens using a cryptographically secure random string. The keys operate as shared keys. This means they are stored as-is in the database. The method returns an instance of -`CodeIgniters\Shield\Authentication\Entities\AccessToken`. The field `secret` is the 'key' the field `secret2` is -the shared 'secretKey'. Both are required to when using this authentication method. +`CodeIgniters\Shield\Authentication\Entities\AccessToken`. The field `secret` is the '_key_' the field `rawSecretKey` is +the shared '_secretKey_'. Both are required to when using this authentication method. **The plain text version of these keys should be displayed to the user immediately, so they can copy it for -their use.** It is recommended that after that only the 'key' field is displayed to a user. If a user loses the -'secretKey', they should be required to generate a new set of keys to use. +their use.** It is recommended that after that only the '_key_' field is displayed to a user. If a user loses the +'_secretKey_', they should be required to generate a new set of keys to use. ```php $token = $user->generateHmacToken('Work Laptop'); echo 'Key: ' . $token->secret; -echo 'SecretKey: ' . $token->secret2; +echo 'SecretKey: ' . $token->rawSecretKey; ``` ## Revoking HMAC Keys diff --git a/src/Authentication/Authenticators/HmacSha256.php b/src/Authentication/Authenticators/HmacSha256.php index dab39be6b..16193e220 100644 --- a/src/Authentication/Authenticators/HmacSha256.php +++ b/src/Authentication/Authenticators/HmacSha256.php @@ -171,8 +171,8 @@ public function check(array $credentials): Result $config->digest = $authConfig->hmacEncryptionDigest; // decrypt secret key so signature can be validated - $encrypter = Services::encrypter($config); - $secretKey = $encrypter->decrypt(hex2bin($token->secret2)); + $encryptor = Services::encrypter($config); + $secretKey = $encryptor->decrypt(hex2bin($token->secret2)); // Check signature... $hash = hash_hmac('sha256', $credentials['body'], $secretKey); diff --git a/src/Database/Migrations/2023-10-30-222755_EncryptHmacKeys.php b/src/Database/Migrations/2023-10-30-222755_EncryptHmacKeys.php new file mode 100644 index 000000000..14ad18cd7 --- /dev/null +++ b/src/Database/Migrations/2023-10-30-222755_EncryptHmacKeys.php @@ -0,0 +1,93 @@ +DBGroup !== null) { + $this->DBGroup = $authConfig->DBGroup; + } + + parent::__construct($forge); + + /** @var AuthToken $authTokenConfig */ + $authTokenConfig = config('AuthToken'); + $config = new Encryption(); + + $config->key = $authTokenConfig->hmacEncryptionKey; + $config->driver = $authTokenConfig->hmacEncryptionDriver; + $config->digest = $authTokenConfig->hmacEncryptionDigest; + + // decrypt secret key so signature can be validated + $this->encryptor = Services::encrypter($config); + } + + /** + * {@inheritDoc} + */ + public function up(): void + { + $uIdModel = new UserIdentityModel(); + + $updateList = []; + $hmacIdentities = $uIdModel->where('type', 'hmac_sha256')->findAll(); + + foreach ($hmacIdentities as $identity) { + $identity->secret2 = bin2hex($this->encryptor->encrypt($identity->secret2)); + + $updateList[] = [ + 'id' => $identity->id, + 'secret2' => $identity->secret2, + ]; + } + + if ($updateList !== []) { + $uIdModel->updateBatch($updateList, 'id'); + } + } + + /** + * {@inheritDoc} + */ + public function down(): void + { + $uIdModel = new UserIdentityModel(); + + $updateList = []; + $hmacIdentities = $uIdModel->where('type', 'hmac_sha256')->findAll(); + + foreach ($hmacIdentities as $identity) { + $identity->secret2 = $this->encryptor->decrypt(hex2bin($identity->secret2)); + + $updateList[] = [ + 'id' => $identity->id, + 'secret2' => $identity->secret2, + ]; + } + + if ($updateList !== []) { + $uIdModel->updateBatch($updateList, 'id'); + } + } +} diff --git a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php index c3af6f0ca..ea553ef2c 100644 --- a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php @@ -13,7 +13,6 @@ namespace Tests\Authentication\Authenticators; -use CodeIgniter\Encryption\Encryption; use CodeIgniter\I18n\Time; use CodeIgniter\Shield\Authentication\Authentication; use CodeIgniter\Shield\Authentication\AuthenticationException; @@ -38,9 +37,6 @@ protected function setUp(): void { parent::setUp(); - $authConfig = config('AuthToken'); - $authConfig->hmacEncryptionKey = Encryption::createKey(); - $config = new Auth(); $auth = new Authentication($config); $auth->setProvider(model(UserModel::class)); diff --git a/tests/Authentication/Filters/HmacFilterTest.php b/tests/Authentication/Filters/HmacFilterTest.php index c88ecfbbc..ffb516313 100644 --- a/tests/Authentication/Filters/HmacFilterTest.php +++ b/tests/Authentication/Filters/HmacFilterTest.php @@ -13,7 +13,6 @@ namespace Tests\Authentication\Filters; -use CodeIgniter\Encryption\Encryption; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Filters\HmacAuth; @@ -31,14 +30,6 @@ final class HmacFilterTest extends AbstractFilterTestCase protected string $alias = 'hmacAuth'; protected string $classname = HmacAuth::class; - protected function setUp(): void - { - parent::setUp(); - - $authConfig = config('AuthToken'); - $authConfig->hmacEncryptionKey = Encryption::createKey(); - } - public function testFilterNotAuthorized(): void { $result = $this->call('get', 'protected-route'); diff --git a/tests/Authentication/HasHmacTokensTest.php b/tests/Authentication/HasHmacTokensTest.php index e1a59a3e0..b3b0fda17 100644 --- a/tests/Authentication/HasHmacTokensTest.php +++ b/tests/Authentication/HasHmacTokensTest.php @@ -13,7 +13,6 @@ namespace Tests\Authentication; -use CodeIgniter\Encryption\Encryption; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Models\UserIdentityModel; @@ -31,9 +30,6 @@ protected function setUp(): void { parent::setUp(); - $authConfig = config('AuthToken'); - $authConfig->hmacEncryptionKey = Encryption::createKey(); - $this->user = fake(UserModel::class); $this->db->table($this->tables['identities'])->truncate(); } @@ -61,12 +57,12 @@ public function testHmacTokens(): void // Give the user a couple of access tokens $token1 = fake( UserIdentityModel::class, - ['user_id' => $this->user->id, 'type' => 'hmac_sha256', 'secret' => 'key1', 'secret2' => 'secretKey1'] + ['user_id' => $this->user->id, 'type' => 'hmac_sha256', 'secret' => 'key1', 'secret2' => 'd862cd9ddc23e960ca6d45a3e0b64c7509f0c0ef0e5f7b64be8910a6a714c89b83fab95251bbf17f6c84b42c26cf460a28ea969591dc64b1f5c4b323f47615d2e8cbe4c62118001d3274e0f25850b0ac2617bc43119af22c99a1a83072002267177da01f9f37225435e1914be004f4d35a49869b737ed10ab232c1ed1048bb96ef6fb70979dc9c981e17134f4356a938'] ); $token2 = fake( UserIdentityModel::class, - ['user_id' => $this->user->id, 'type' => 'hmac_sha256', 'secret' => 'key2', 'secret2' => 'secretKey2'] + ['user_id' => $this->user->id, 'type' => 'hmac_sha256', 'secret' => 'key2', 'secret2' => 'd862cd9ddc23e960ca6d45a3e0b64c7509f0c0ef0e5f7b64be8910a6a714c89b83fab95251bbf17f6c84b42c26cf460a28ea969591dc64b1f5c4b323f47615d2e8cbe4c62118001d3274e0f25850b0ac2617bc43119af22c99a1a83072002267177da01f9f37225435e1914be004f4d35a49869b737ed10ab232c1ed1048bb96ef6fb70979dc9c981e17134f4356a938'] ); $tokens = $this->user->hmacTokens(); diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php index a7af822ea..1a524375a 100644 --- a/tests/_support/TestCase.php +++ b/tests/_support/TestCase.php @@ -25,6 +25,8 @@ abstract class TestCase extends CIUnitTestCase { protected function setUp(): void { + $_ENV['authtoken.hmacEncryptionKey'] = 'hex2bin:178ed94fd0b6d57dd31dd6b22fc601fab8ad191efac165a5f3f30a8ac09d813d'; + $this->resetServices(); parent::setUp(); From 9ec7b6808d49b25ed4dc377fb65c4b835d5cd1b3 Mon Sep 17 00:00:00 2001 From: tswagger Date: Wed, 1 Nov 2023 10:34:08 -0500 Subject: [PATCH 088/128] Adjustments to documentation language --- docs/guides/api_hmac_keys.md | 9 +++++---- docs/references/authentication/hmac.md | 12 ++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index d37b09d04..790322705 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -15,10 +15,11 @@ API. When making requests using HMAC keys, the token should be included in the ` setting the `$authenticatorHeader['hmac']` value in the **app/Config/AuthToken.php** config file. Tokens are issued with the `generateHmacToken()` method on the user. This returns a -`CodeIgniter\Shield\Entities\AccessToken` instance. These shared keys are saved to the database in plain text. The -`AccessToken` object returned when you generate it will include a `secret` field which will be the '_key_' and a `rawSecretKey` -field that will be the '_secretKey_'. You should display the '_secretKey_' to your user once, so they have a chance to copy -it somewhere safe, as this is the only time you should reveal this key. +`CodeIgniter\Shield\Entities\AccessToken` instance. The `AccessToken` object returned will include a `secret` field +which will be the '**key**' and a `rawSecretKey` field that will be the '**secretKey**'. You should display the +'**secretKey**' to your user immediately, so they have a chance to copy it somewhere safe, as this is the only time +you can reveal this key. The '**key**' and '**sharedKey**' are saved to the database. The '**secretKey**' is stored +encrypted. The `generateHmacToken()` method requires a name for the token. These are free strings and are often used to identify the user/device the token was generated from/for, like 'Johns MacBook Air'. diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index e319957d2..86670b047 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -7,7 +7,7 @@ access to your API. These keys typically have a very long expiration time, often These are also suitable for use with mobile applications. In this case, the user would register/sign-in with their email/password. The application would create a new access token for them, with a recognizable -name, like John's iPhone 12, and return it to the mobile application, where it is stored and used +name, like "John's iPhone 12", and return it to the mobile application, where it is stored and used in all future requests. !!! note @@ -67,13 +67,13 @@ $token = $user->generateHmacToken('Work Laptop'); ``` This creates the keys/tokens using a cryptographically secure random string. The keys operate as shared keys. -This means they are stored as-is in the database. The method returns an instance of -`CodeIgniters\Shield\Authentication\Entities\AccessToken`. The field `secret` is the '_key_' the field `rawSecretKey` is -the shared '_secretKey_'. Both are required to when using this authentication method. +The '**key**' is stored as plain text in the database, the '**secretKey**' is stored encrypted. The method returns an +instance of `CodeIgniters\Shield\Authentication\Entities\AccessToken`. The field `secret` is the '**key**' the field +`rawSecretKey` is the shared '**secretKey**'. Both are required to when using this authentication method. **The plain text version of these keys should be displayed to the user immediately, so they can copy it for -their use.** It is recommended that after that only the '_key_' field is displayed to a user. If a user loses the -'_secretKey_', they should be required to generate a new set of keys to use. +their use.** It is recommended that after that only the '**key**' field is displayed to a user. If a user loses the +'**secretKey**', they should be required to generate a new set of keys to use. ```php $token = $user->generateHmacToken('Work Laptop'); From d02ccf4406c0d23bed2709173879c92ae1618fb8 Mon Sep 17 00:00:00 2001 From: tswagger Date: Wed, 1 Nov 2023 14:30:57 -0500 Subject: [PATCH 089/128] Added HmacEncrypter class --- .../Authenticators/HmacSha256.php | 17 +--- src/Authentication/HMAC/HmacEncrypter.php | 82 +++++++++++++++++++ src/Models/UserIdentityModel.php | 19 +---- 3 files changed, 89 insertions(+), 29 deletions(-) create mode 100644 src/Authentication/HMAC/HmacEncrypter.php diff --git a/src/Authentication/Authenticators/HmacSha256.php b/src/Authentication/Authenticators/HmacSha256.php index 16193e220..940886f2b 100644 --- a/src/Authentication/Authenticators/HmacSha256.php +++ b/src/Authentication/Authenticators/HmacSha256.php @@ -17,16 +17,14 @@ use CodeIgniter\I18n\Time; use CodeIgniter\Shield\Authentication\AuthenticationException; use CodeIgniter\Shield\Authentication\AuthenticatorInterface; +use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter; use CodeIgniter\Shield\Config\Auth; -use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Exceptions\InvalidArgumentException; use CodeIgniter\Shield\Models\TokenLoginModel; use CodeIgniter\Shield\Models\UserIdentityModel; use CodeIgniter\Shield\Models\UserModel; use CodeIgniter\Shield\Result; -use Config\Encryption; -use Config\Services; class HmacSha256 implements AuthenticatorInterface { @@ -162,17 +160,8 @@ public function check(array $credentials): Result ]); } - /** @var AuthToken $authConfig */ - $authConfig = config('AuthToken'); - $config = new Encryption(); - - $config->key = $authConfig->hmacEncryptionKey; - $config->driver = $authConfig->hmacEncryptionDriver; - $config->digest = $authConfig->hmacEncryptionDigest; - - // decrypt secret key so signature can be validated - $encryptor = Services::encrypter($config); - $secretKey = $encryptor->decrypt(hex2bin($token->secret2)); + $encrypter = new HmacEncrypter(); + $secretKey = $encrypter->decrypt($token->secret2); // Check signature... $hash = hash_hmac('sha256', $credentials['body'], $secretKey); diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php new file mode 100644 index 000000000..6a0b7c28c --- /dev/null +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -0,0 +1,82 @@ +authConfig = config('AuthToken'); + $config = new Encryption(); + + $config->key = $this->authConfig->hmacEncryptionKey; + $config->driver = $this->authConfig->hmacEncryptionDriver; + $config->digest = $this->authConfig->hmacEncryptionDigest; + + // decrypt secret key so signature can be validated + $this->encrypter = Services::encrypter($config); + } + + /** + * Decrypt + * + * @param string $hexString Encrypted string in Hex format + * + * @return string Raw decrypted string + */ + public function decrypt(string $hexString): string + { + return $this->encrypter->decrypt(hex2bin($hexString)); + } + + /** + * Encrypt + * + * @param string $rawString Raw string to encrypt + * + * @return string Encrypted string in hex format + */ + public function encrypt(string $rawString): string + { + return bin2hex($this->encrypter->encrypt($rawString)); + } + + /** + * Generate Key + * + * @return string Secret Key in hexed format + * + * @throws Exception + */ + public function generateSecretKey(): string + { + return bin2hex(random_bytes($this->authConfig->hmacSecretKeyByteSize)); + } +} diff --git a/src/Models/UserIdentityModel.php b/src/Models/UserIdentityModel.php index 80e1ebcac..73b3fb831 100644 --- a/src/Models/UserIdentityModel.php +++ b/src/Models/UserIdentityModel.php @@ -17,15 +17,13 @@ use CodeIgniter\Shield\Authentication\Authenticators\AccessTokens; use CodeIgniter\Shield\Authentication\Authenticators\HmacSha256; use CodeIgniter\Shield\Authentication\Authenticators\Session; +use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter; use CodeIgniter\Shield\Authentication\Passwords; -use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Entities\UserIdentity; use CodeIgniter\Shield\Exceptions\LogicException; use CodeIgniter\Shield\Exceptions\ValidationException; -use Config\Encryption; -use Config\Services; use Exception; use Faker\Generator; use ReflectionException; @@ -254,18 +252,9 @@ public function generateHmacToken(User $user, string $name, array $scopes = ['*' { $this->checkUserId($user); - /** @var AuthToken $authConfig */ - $authConfig = config('AuthToken'); - $config = new Encryption(); - - $config->key = $authConfig->hmacEncryptionKey; - $config->driver = $authConfig->hmacEncryptionDriver; - $config->digest = $authConfig->hmacEncryptionDigest; - - // Generate and encrypt secret key - $encrypter = Services::encrypter($config); - $rawSecretKey = bin2hex(random_bytes(config('AuthToken')->hmacSecretKeyByteSize)); - $secretKey = bin2hex($encrypter->encrypt($rawSecretKey)); + $encrypter = new HmacEncrypter(); + $rawSecretKey = $encrypter->generateSecretKey(); + $secretKey = $encrypter->encrypt($rawSecretKey); $return = $this->insert([ 'type' => HmacSha256::ID_TYPE_HMAC_TOKEN, From 27fee6947ed5d8ca2f298228f26f7de576032adc Mon Sep 17 00:00:00 2001 From: tswagger Date: Wed, 1 Nov 2023 14:46:24 -0500 Subject: [PATCH 090/128] Fixed the upgrading documentation --- UPGRADING.md | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 66cf193fe..2df16fb2c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,25 +1,5 @@ # Upgrade Guide -## Version 1.0.0-beta.8 to 1.0.0-beta.9 - -### Mandatory Config Changes - -#### Config\AuthToken - -If you are using the HMAC authentication you need to update the encryption settings in **app/Config/AuthToken.php**. -You will need to update and set the encryption key `$hmacEncryptionKey`. This should be set using .env and/or system -environment variables. Instructions on how to do that can be found in the -[Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) -section of the CodeIgniter 4 documentation. - -You also may wish to adjust the default Driver `$hmacEncryptionDriver` and the default Digest `$hmacEncryptionDigest`, -these currently default to `'OpenSSL'` and `'SHA512'` respectively. - -### Database Migrations - -After updating the `$hmacEncryptionKey` value, you will need to run `php spark migrate --all` in order to encrypt any -existing HMAC tokens. - ## Version 1.0.0-beta.7 to 1.0.0-beta.8 ### Mandatory Config Changes @@ -52,6 +32,17 @@ The following items have been added. Copy the properties in **src/Config/Auth.ph - `permission_denied` and `group_denied` are added to `Config\Auth::$redirects`. - `permissionDeniedRedirect()` and `groupDeniedRedirect()` are added. +#### Config\AuthToken + +If you are using the HMAC authentication you need to update the encryption settings in **app/Config/AuthToken.php**. +You will need to update and set the encryption key `$hmacEncryptionKey`. This should be set using .env and/or system +environment variables. Instructions on how to do that can be found in the +[Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) +section of the CodeIgniter 4 documentation. + +You also may wish to adjust the default Driver `$hmacEncryptionDriver` and the default Digest `$hmacEncryptionDigest`, +these currently default to `'OpenSSL'` and `'SHA512'` respectively. + ### Fix Custom Filter If extends `AbstractAuthFilter` If you have written a custom filter that extends `AbstractAuthFilter`, now you need to add and implement the `redirectToDeniedUrl()` method to your custom filter. @@ -67,6 +58,10 @@ protected function redirectToDeniedUrl(): RedirectResponse ->with('error', lang('Auth.notEnoughPrivilege')); } ``` +### Database Migrations + +After updating the `$hmacEncryptionKey` value, you will need to run `php spark migrate --all` in order to encrypt any +existing HMAC tokens. ## Version 1.0.0-beta.6 to 1.0.0-beta.7 From 5ddf5fc23e7b2a333b90105c4418a6562fefcf73 Mon Sep 17 00:00:00 2001 From: tswagger Date: Fri, 3 Nov 2023 13:24:52 -0500 Subject: [PATCH 091/128] Migrate moved to spark command Test created for new spark command --- phpunit.xml.dist | 5 +- src/Commands/Hmac.php | 133 ++++++++++++++++++ .../2023-10-30-222755_EncryptHmacKeys.php | 93 ------------ tests/Commands/HmacTest.php | 63 +++++++++ tests/_support/TestCase.php | 2 - 5 files changed, 200 insertions(+), 96 deletions(-) create mode 100644 src/Commands/Hmac.php delete mode 100644 src/Database/Migrations/2023-10-30-222755_EncryptHmacKeys.php create mode 100644 tests/Commands/HmacTest.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index aa7040153..ba8360d59 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -93,7 +93,10 @@ - + + + + - + + + diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index 408cbe25f..7a901dd16 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -6,6 +6,7 @@ use CodeIgniter\Encryption\EncrypterInterface; use CodeIgniter\Encryption\Exceptions\EncryptionException; +use CodeIgniter\Shield\Auth; use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Exceptions\RuntimeException; use Config\Encryption; @@ -29,19 +30,31 @@ class HmacEncrypter */ private AuthToken $authConfig; + /** + * Selected Key Index + */ + private string $keyIndex; + /** * Constructor * Setup encryption configuration + * + * @param bool $deprecatedKey Use the deprecated key (useful when re-encrypting on key rotation) [default: false] */ - public function __construct() + public function __construct(bool $deprecatedKey = false) { - $this->authConfig = config('AuthToken'); - $config = new Encryption(); + /** @var AuthToken $authConfig */ + $authConfig = config('AuthToken'); + $config = new Encryption(); + + // identify which encryption key should be used + $this->keyIndex = $deprecatedKey ? $authConfig->hmacDeprecatedKeyIndex : $authConfig->hmacKeyIndex; - $config->key = $this->authConfig->hmacEncryptionKey; - $config->driver = $this->authConfig->hmacEncryptionDriver; - $config->digest = $this->authConfig->hmacEncryptionDigest; + $config->key = $authConfig->hmacEncryptionKey[$this->keyIndex]; + $config->driver = $authConfig->hmacEncryptionDriver[$this->keyIndex]; + $config->digest = $authConfig->hmacEncryptionDigest[$this->keyIndex]; + $this->authConfig = $authConfig; // decrypt secret key so signature can be validated $this->encrypter = Services::encrypter($config); } @@ -57,8 +70,8 @@ public function __construct() */ public function decrypt(string $encString): string { - // Removes `$b6$` for base64 format. - $encString = substr($encString, 4); + // Removes `$b6$keyIndex$` for base64 format. + $encString = substr($encString, strlen($this->keyIndex) + 5); return $this->encrypter->decrypt(base64_decode($encString, true)); } @@ -75,7 +88,7 @@ public function decrypt(string $encString): string */ public function encrypt(string $rawString): string { - $encryptedString = '$b6$' . base64_encode($this->encrypter->encrypt($rawString)); + $encryptedString = '$b6$' . $this->keyIndex . '$' . base64_encode($this->encrypter->encrypt($rawString)); if (strlen($encryptedString) > $this->authConfig->secret2StorageLimit) { throw new RuntimeException('Encrypted key too long. Unable to store value.'); @@ -89,7 +102,7 @@ public function encrypt(string $rawString): string */ public function isEncrypted(string $string): bool { - return str_starts_with($string, '$b6$'); + return str_starts_with($string, '$b6$' . $this->keyIndex . '$'); } /** diff --git a/src/Commands/Hmac.php b/src/Commands/Hmac.php index 711cc6fc0..3b56b338e 100644 --- a/src/Commands/Hmac.php +++ b/src/Commands/Hmac.php @@ -25,7 +25,8 @@ class Hmac extends BaseCommand * * @var string */ - protected $description = 'Encrypt/Decrypt secretKey for HMAC tokens. The encryption should only be run on existing raw secret keys (extremely rare).'; + protected $description = 'Encrypt/Decrypt secretKey for HMAC tokens. The reencrypt command should be used when + rotating the encryption keys. The encrypt command should only be run on existing raw secret keys (extremely rare).'; /** * the Command's usage @@ -34,6 +35,7 @@ class Hmac extends BaseCommand */ protected $usage = <<<'EOL' shield:hmac + shield:hmac reencrypt shield:hmac encrypt shield:hmac decrypt EOL; @@ -45,6 +47,7 @@ class Hmac extends BaseCommand */ protected $arguments = [ 'action' => <<<'EOL' + reencrypt: Re-encrypts all HMAC Secret Keys on encryption key rotation encrypt: Encrypt all raw HMAC Secret Keys decrypt: Decrypt all encrypted HMAC Secret Keys EOL, @@ -81,6 +84,10 @@ public function run(array $params): int $this->decrypt(); break; + case 'reencrypt': + $this->reEncrypt(); + break; + default: throw new BadInputException('Unrecognized Command'); } @@ -156,4 +163,37 @@ static function ($identity) use ($uIdModelSub, $encrypter, $that): void { } ); } + + /** + * Re-encrypt all encrypted HMAC Secret Keys from existing/deprecated + * encryption key to new encryption key. + * + * @throws ReflectionException + */ + public function reEncrypt(): void + { + $uIdModel = new UserIdentityModel(); + $uIdModelSub = new UserIdentityModel(); // For saving. + $decrypter = new HmacEncrypter(true); + $encrypter = $this->encrypter; + + $that = $this; + + $uIdModel->where('type', 'hmac_sha256')->chunk( + 100, + static function ($identity) use ($uIdModelSub, $decrypter, $encrypter, $that): void { + if (! $decrypter->isEncrypted($identity->secret2)) { + $that->write('id: ' . $identity->id . ', not re-encrypted, skipped.'); + + return; + } + + $identity->secret2 = $decrypter->decrypt($identity->secret2); + $identity->secret2 = $encrypter->encrypt($identity->secret2); + $uIdModelSub->save($identity); + + $that->write('id: ' . $identity->id . ', Re-encrypted.'); + } + ); + } } diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 7ab9cf89f..6d8cd90ad 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -78,9 +78,20 @@ class AuthToken extends BaseConfig * -------------------------------------------------------------------- * Key to be used when encrypting HMAC Secret Key for storage. * + * This is an array of keys which will facilitate key rotation. Valid + * keyTitles must include only [a-zA-z0-9_] and should be kept to a + * max of 8 characters. + * + * The valid and old/deprecated keys are identified using $hmacKeyIndex + * and $hmacDeprecatedKeyIndex. + * + * @param array|string $hmacEncryptionKey ['keyTitle' => 'keyValue'] + * * @see https://codeigniter.com/user_guide/libraries/encryption.html */ - public string $hmacEncryptionKey = ''; + public $hmacEncryptionKey = [ + 'k1' => '', + ]; /** * -------------------------------------------------------------------- @@ -92,9 +103,16 @@ class AuthToken extends BaseConfig * OpenSSL * Sodium * + * This is an array of drivers values. The keys MUST match and correlate + * to the $hmacEncryptionKey array keys. + * + * @param array|string $hmacEncryptionDriver ['keyTitle' => 'driverValue'] + * * @see https://codeigniter.com/user_guide/libraries/encryption.html */ - public string $hmacEncryptionDriver = 'OpenSSL'; + public $hmacEncryptionDriver = [ + 'k1' => 'OpenSSL', + ]; /** * -------------------------------------------------------------------- @@ -104,7 +122,79 @@ class AuthToken extends BaseConfig * * e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. * + * This is an array of digest values. The keys MUST match and correlate + * to the $hmacEncryptionKey array keys. + * + * @param array|string $hmacEncryptionDigest ['keyTitle' => 'digestValue'] + * * @see https://codeigniter.com/user_guide/libraries/encryption.html */ - public string $hmacEncryptionDigest = 'SHA512'; + public $hmacEncryptionDigest = [ + 'k1' => 'SHA512', + ]; + + /** + * -------------------------------------------------------------------- + * HMAC encryption key selector + * -------------------------------------------------------------------- + * This identifies which encryption key {$hmacEncryptionKey} is active + * and valid. + */ + public string $hmacKeyIndex = 'k1'; + + /** + * -------------------------------------------------------------------- + * HMAC encryption key deprecated selector + * -------------------------------------------------------------------- + * This identifies which encryption key {$hmacEncryptionKey} is + * recently deprecated. This is required and used when rotating keys. + * Effectively, this is the index selector for the old key. + */ + public string $hmacDeprecatedKeyIndex = ''; + + public function __construct() + { + parent::__construct(); + + if (is_string($this->hmacEncryptionKey)) { + $array = json_decode($this->hmacEncryptionKey, true); + if (is_array($array)) { + $this->hmacEncryptionKey = $array; + } + } + if (is_string($this->hmacEncryptionDriver)) { + $array = json_decode($this->hmacEncryptionDriver, true); + if (is_array($array)) { + $this->hmacEncryptionDriver = $array; + } + } + if (is_string($this->hmacEncryptionDigest)) { + $array = json_decode($this->hmacEncryptionDigest, true); + if (is_array($array)) { + $this->hmacEncryptionDigest = $array; + } + } + } + + /** + * Override parent initEnvValue() to allow for direct setting to array properties values from ENV + * + * In order to set array properties via ENV vars we need to set the property to a string value first. + * + * @param mixed $property + */ + protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void + { + switch ($name) { + case 'hmacEncryptionKey': + case 'hmacEncryptionDriver': + case 'hmacEncryptionDigest': + // if attempting to set property from ENV, first set to empty string + if ((bool) $this->getEnvValue($name, $prefix, $shortPrefix)) { + $property = ''; + } + } + + parent::initEnvValue($property, $name, $prefix, $shortPrefix); + } } diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 707c7c2ff..f782357ff 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -5,9 +5,12 @@ namespace Tests\Commands; use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter; +use CodeIgniter\Shield\Commands\Hmac; +use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Models\UserIdentityModel; use CodeIgniter\Shield\Models\UserModel; +use CodeIgniter\Shield\Test\MockInputOutput; use Tests\Support\DatabaseTestCase; /** @@ -15,6 +18,8 @@ */ final class HmacTest extends DatabaseTestCase { + private ?MockInputOutput $io = null; + public function testEncrypt(): void { $idModel = new UserIdentityModel(); @@ -60,4 +65,58 @@ public function testDecrypt(): void $this->assertSame($rawSecretKey, $tokenCheck->secret2); } + + public function testReEncrypt(): void + { + $idModel = new UserIdentityModel(); + + // generate first token + /** @var User $user */ + $user = fake(UserModel::class); + $token1 = $user->generateHmacToken('foo'); + + // update config, rotate keys + /** @var AuthToken $config */ + $config = config('AuthToken'); + + $config->hmacKeyIndex = 'k2'; + $config->hmacDeprecatedKeyIndex = 'k1'; + + // new key generated with updated encryption + $token2 = $user->generateHmacToken('bar'); + + $this->setMockIo([]); + $this->assertNotFalse(command('shield:hmac reencrypt')); + + $resultsString = $this->io->getOutputs(); + $results = explode("\n", trim($resultsString)); + + // verify that only 1 key needed to be re-encrypted + $this->assertCount(2, $results); + $this->assertSame('id: 1, Re-encrypted.', $results[0]); + $this->assertSame('id: 2, not re-encrypted, skipped.', $results[1]); + + $encrypter = new HmacEncrypter(); + + $tokenCheck1 = $idModel->find($token1->id); + $descryptSecretKey1 = $encrypter->decrypt($tokenCheck1->secret2); + $this->assertSame($token1->rawSecretKey, $descryptSecretKey1); + + $tokenCheck2 = $idModel->find($token2->id); + $descryptSecretKey2 = $encrypter->decrypt($tokenCheck2->secret2); + $this->assertSame($token2->rawSecretKey, $descryptSecretKey2); + } + + /** + * Set MockInputOutput and user inputs. + * + * @param array $inputs User inputs + * @phpstan-param list $inputs + */ + private function setMockIo(array $inputs): void + { + $this->io = new MockInputOutput(); + $this->io->setInputs($inputs); + Hmac::setInputOutput($this->io); + } } From 20bc9f9fee7892f9590a1d9f8c49196c548198a7 Mon Sep 17 00:00:00 2001 From: tswagger Date: Sat, 11 Nov 2023 19:40:46 -0600 Subject: [PATCH 095/128] Updated documentation to reflect encryption key updates. --- UPGRADING.md | 2 +- docs/guides/api_hmac_keys.md | 10 ++-- docs/references/authentication/hmac.md | 63 +++++++++++++++++++++++++- src/Config/AuthToken.php | 3 ++ 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 9da5cb05f..4e157eb07 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -56,7 +56,7 @@ If you are using the HMAC authentication you need to update the encryption setti You will need to update and set the encryption key `$hmacEncryptionKey`. This should be set using **.env** and/or system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) -section of the CodeIgniter 4 documentation. +section of the CodeIgniter 4 documentation and in [HMAC SHA256 Token Authenticator](./docs/references/authentication/hmac.md#hmac-secret-key-encryption). You also may wish to adjust the default Driver `$hmacEncryptionDriver` and the default Digest `$hmacEncryptionDigest`, these currently default to `'OpenSSL'` and `'SHA512'` respectively. diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index 512918dfd..48b0a3027 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -99,9 +99,13 @@ section of the CodeIgniter 4 documentation. You will also be able to adjust the default Driver `$hmacEncryptionDriver` and the default Digest `$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. -Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to -exceed the database column character limit of 255 characters. If this happens, creation of a new HMAC identity will -throw a `RuntimeException`. +See [HMAC SHA256 Token Authenticator](../references/authentication/hmac.md#hmac-secret-key-encryption) for additional +details on setting these values. + +### Encryption Key Rotation + +See [HMAC SHA256 Token Authenticator](../references/authentication/hmac.md#hmac-secret-key-encryption) for information on +how to set, rotate encryption keys and re-encrypt existing HMAC `'secretKey'` values. ## Protecting Routes diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 86670b047..bff57dec7 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -166,4 +166,65 @@ Instructions on how to do that can be found in the section of the CodeIgniter 4 documentation. You will also be able to adjust the default Driver `$hmacEncryptionDriver` and the default Digest -`$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. +`$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. All three properties (`$hmacEncryptionKey`, +`$hmacEncryptionDriver`, and `$hmacEncryptionDigest`) are set in array format (see below). + +```php +public $hmacEncryptionKey = [ + 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', +]; + +public $hmacEncryptionDriver = [ + 'k1' => 'OpenSSL', +]; + +public $hmacEncryptionDigest = [ + 'k1' => 'SHA512', +]; + +public string $hmacKeyIndex = 'k1'; +``` + +When it is time to update your encryption keys you will need to add an additional key to the above arrays. Then adjust +the `$hmacKeyIndex` to point at the new key and adjust `$hmacDeprecatedKeyIndex` to point at the old key. After the new +encryption key is in place, run `php spark shield:hmac reencrypt` to re-encrypt all existing keys with the new encryption +key. + +```php +public $hmacEncryptionKey = [ + 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', + 'k2' => 'hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0', +]; + +public $hmacEncryptionDriver = [ + 'k1' => 'OpenSSL', + 'k2' => 'OpenSSL', +]; + +public $hmacEncryptionDigest = [ + 'k1' => 'SHA512', + 'k2' => 'SHA512', +]; + +public string $hmacKeyIndex = 'k2'; +public string $hmacDeprecatedKeyIndex = 'k1'; +``` + +```shell +php spark shield:hmac reencrypt +``` + +You can (and should) set these values using environment variable and/or the `.env` file. To do this you will need to set +the values as JSON strings: + +```dotenv +authtoken.hmacEncryptionKey = '{"k1":"hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7","k2":"hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0"}' +authtoken.hmacEncryptionDriver = '{"k1":"OpenSSL","k2":"OpenSSL"}' +authtoken.hmacEncryptionDigest = '{"k1":"SHA512","k2":"SHA512"}' +authtoken.hmacKeyIndex = k2 +authtoken.hmacDeprecatedKeyIndex = k1 +``` + +Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to +exceed the database column character limit of 255 characters. If this happens, creation of a new HMAC identity will +throw a `RuntimeException`. diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 6d8cd90ad..8092fce9c 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -152,6 +152,9 @@ class AuthToken extends BaseConfig */ public string $hmacDeprecatedKeyIndex = ''; + /** + * AuthToken Config Constructor + */ public function __construct() { parent::__construct(); From 280c4e3a20a9ccde7c82557c6643302213e86700 Mon Sep 17 00:00:00 2001 From: tswagger Date: Mon, 13 Nov 2023 12:35:59 -0600 Subject: [PATCH 096/128] Rework of HMAC Encryption config properties. Improved tests Fixed bug with isEncrypted check Cleaned up Documentation to reflect above changes --- UPGRADING.md | 6 +- docs/guides/api_hmac_keys.md | 6 +- docs/references/authentication/hmac.md | 75 +++++++------- phpunit.xml.dist | 6 +- src/Authentication/HMAC/HmacEncrypter.php | 26 ++++- src/Commands/Hmac.php | 12 ++- src/Config/AuthToken.php | 121 +++++++--------------- tests/Commands/HmacTest.php | 44 +++++++- 8 files changed, 153 insertions(+), 143 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 4e157eb07..0a79d9f86 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -53,17 +53,17 @@ protected function redirectToDeniedUrl(): RedirectResponse #### Config\AuthToken If you are using the HMAC authentication you need to update the encryption settings in **app/Config/AuthToken.php**. -You will need to update and set the encryption key `$hmacEncryptionKey`. This should be set using **.env** and/or system +You will need to update and set the encryption key `$hmacEncryption['key']`. This should be set using **.env** and/or system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation and in [HMAC SHA256 Token Authenticator](./docs/references/authentication/hmac.md#hmac-secret-key-encryption). -You also may wish to adjust the default Driver `$hmacEncryptionDriver` and the default Digest `$hmacEncryptionDigest`, +You also may wish to adjust the default Driver `$hmacEncryption['driver']` and the default Digest `$hmacEncryption['digest']`, these currently default to `'OpenSSL'` and `'SHA512'` respectively. #### Encrypt Existing Keys -After updating the `$hmacEncryptionKey` value, you will need to run `php spark shield:hmac encrypt` in order to encrypt +After updating the `$hmacEncryption['key']` value, you will need to run `php spark shield:hmac encrypt` in order to encrypt any existing HMAC tokens. This only needs to be run if you have existing unencrypted HMAC secretKeys in stored in the database. diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index 48b0a3027..4417143af 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -91,13 +91,13 @@ $user->revokeAllHmacTokens(); ## HMAC Secret Key Encryption The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key -`$hmacEncryptionKey` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system environment variables. +`$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation. -You will also be able to adjust the default Driver `$hmacEncryptionDriver` and the default Digest -`$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. +You will also be able to adjust the default Driver `$hmacEncryption['driver']` and the default Digest +`$hmacEncryption['digest']`, these default to `'OpenSSL'` and `'SHA512'` respectively. See [HMAC SHA256 Token Authenticator](../references/authentication/hmac.md#hmac-secret-key-encryption) for additional details on setting these values. diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index bff57dec7..c264a2cc4 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -160,54 +160,49 @@ if ($user->hmacTokenCant('forums.manage')) { ## HMAC Secret Key Encryption The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key -`$hmacEncryptionKey` in **app/Config/AuthToken.php**. This should be set using .env and/or system environment variables. +`$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using .env and/or system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation. -You will also be able to adjust the default Driver `$hmacEncryptionDriver` and the default Digest -`$hmacEncryptionDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. All three properties (`$hmacEncryptionKey`, -`$hmacEncryptionDriver`, and `$hmacEncryptionDigest`) are set in array format (see below). +You will also be able to adjust the default Driver `$hmacEncryption['driver']` and the default Digest +`$hmacEncryption['digest']`, these default to `'OpenSSL'` and `'SHA512'` respectively. All three properties (`$hmacEncryption['key']`, +`$hmacEncryption['driver']`, and `$hmacEncryption['digest']`) are set in array format (see below). ```php -public $hmacEncryptionKey = [ - 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', +public array $hmacEncryption [ + 'key' => [ + 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', + ], + 'driver' => ['k1' => 'OpenSSL'], + 'digest' => ['k1' => 'SHA512'], + 'currentKey' => 'k1', + 'deprecatedKey' => null ]; - -public $hmacEncryptionDriver = [ - 'k1' => 'OpenSSL', -]; - -public $hmacEncryptionDigest = [ - 'k1' => 'SHA512', -]; - -public string $hmacKeyIndex = 'k1'; ``` When it is time to update your encryption keys you will need to add an additional key to the above arrays. Then adjust -the `$hmacKeyIndex` to point at the new key and adjust `$hmacDeprecatedKeyIndex` to point at the old key. After the new -encryption key is in place, run `php spark shield:hmac reencrypt` to re-encrypt all existing keys with the new encryption -key. +the `$hmacEncryption['currentKey']` to point at the new key and adjust `$hmacEncryption['deprecatedKey']` to point at the +old key. After the new encryption key is in place, run `php spark shield:hmac reencrypt` to re-encrypt all existing keys +with the new encryption key. ```php -public $hmacEncryptionKey = [ - 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', - 'k2' => 'hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0', +public array $hmacEncryption [ + 'key' => [ + 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', + 'k2' => 'hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0', + ], + 'driver' => [ + 'k1' => 'OpenSSL', + 'k2' => 'OpenSSL', + ], + 'digest' => [ + 'k1' => 'SHA512', + 'k2' => 'SHA512' + ], + 'currentKey' => 'k2', + 'deprecatedKey' => 'k1' ]; - -public $hmacEncryptionDriver = [ - 'k1' => 'OpenSSL', - 'k2' => 'OpenSSL', -]; - -public $hmacEncryptionDigest = [ - 'k1' => 'SHA512', - 'k2' => 'SHA512', -]; - -public string $hmacKeyIndex = 'k2'; -public string $hmacDeprecatedKeyIndex = 'k1'; ``` ```shell @@ -218,11 +213,11 @@ You can (and should) set these values using environment variable and/or the `.en the values as JSON strings: ```dotenv -authtoken.hmacEncryptionKey = '{"k1":"hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7","k2":"hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0"}' -authtoken.hmacEncryptionDriver = '{"k1":"OpenSSL","k2":"OpenSSL"}' -authtoken.hmacEncryptionDigest = '{"k1":"SHA512","k2":"SHA512"}' -authtoken.hmacKeyIndex = k2 -authtoken.hmacDeprecatedKeyIndex = k1 +authtoken.hmacEncryption.key = '{"k1":"hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7","k2":"hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0"}' +authtoken.hmacEncryption.driver = '{"k1":"OpenSSL","k2":"OpenSSL"}' +authtoken.hmacEncryption.digest = '{"k1":"SHA512","k2":"SHA512"}' +authtoken.hmacEncryption.currentKey = k2 +authtoken.hmacEncryption.deprecatedKey = k1 ``` Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 19da266ac..6a37a2ce6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -94,9 +94,9 @@ - - - + + + diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index 7a901dd16..63132eb5a 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -47,12 +47,19 @@ public function __construct(bool $deprecatedKey = false) $authConfig = config('AuthToken'); $config = new Encryption(); + // // identify which encryption key should be used + // $this->keyIndex = $deprecatedKey ? $authConfig->hmacDeprecatedKeyIndex : $authConfig->hmacKeyIndex; + // + // $config->key = $authConfig->hmacEncryptionKey[$this->keyIndex]; + // $config->driver = $authConfig->hmacEncryptionDriver[$this->keyIndex]; + // $config->digest = $authConfig->hmacEncryptionDigest[$this->keyIndex]; + // identify which encryption key should be used - $this->keyIndex = $deprecatedKey ? $authConfig->hmacDeprecatedKeyIndex : $authConfig->hmacKeyIndex; + $this->keyIndex = $deprecatedKey ? $authConfig->hmacEncryption['deprecatedKey'] : $authConfig->hmacEncryption['currentKey']; - $config->key = $authConfig->hmacEncryptionKey[$this->keyIndex]; - $config->driver = $authConfig->hmacEncryptionDriver[$this->keyIndex]; - $config->digest = $authConfig->hmacEncryptionDigest[$this->keyIndex]; + $config->key = $authConfig->hmacEncryption['key'][$this->keyIndex]; + $config->driver = $authConfig->hmacEncryption['driver'][$this->keyIndex]; + $config->digest = $authConfig->hmacEncryption['digest'][$this->keyIndex]; $this->authConfig = $authConfig; // decrypt secret key so signature can be validated @@ -102,7 +109,16 @@ public function encrypt(string $rawString): string */ public function isEncrypted(string $string): bool { - return str_starts_with($string, '$b6$' . $this->keyIndex . '$'); + return (bool) preg_match('/^\$b6\$/', $string); + } + + /** + * Check if the string already encrypted + */ + public function isEncryptedWithSetKey(string $string): bool + { + return (bool) preg_match('/^\$b6\$' . $this->keyIndex . '\$/', $string); + // return str_starts_with($string, '$b6$' . $this->keyIndex . '$'); } /** diff --git a/src/Commands/Hmac.php b/src/Commands/Hmac.php index 3b56b338e..907dc94af 100644 --- a/src/Commands/Hmac.php +++ b/src/Commands/Hmac.php @@ -25,8 +25,7 @@ class Hmac extends BaseCommand * * @var string */ - protected $description = 'Encrypt/Decrypt secretKey for HMAC tokens. The reencrypt command should be used when - rotating the encryption keys. The encrypt command should only be run on existing raw secret keys (extremely rare).'; + protected $description = 'Encrypt/Decrypt secretKey for HMAC tokens.'; /** * the Command's usage @@ -38,6 +37,9 @@ class Hmac extends BaseCommand shield:hmac reencrypt shield:hmac encrypt shield:hmac decrypt + + The reencrypt command should be used when rotating the encryption keys. + The encrypt command should only be run on existing raw secret keys (extremely rare). EOL; /** @@ -147,7 +149,7 @@ public function decrypt(): void $that = $this; - $uIdModel->where('type', 'hmac_sha256')->chunk( + $uIdModel->where('type', 'hmac_sha256')->orderBy('id')->chunk( 100, static function ($identity) use ($uIdModelSub, $encrypter, $that): void { if (! $encrypter->isEncrypted($identity->secret2)) { @@ -179,10 +181,10 @@ public function reEncrypt(): void $that = $this; - $uIdModel->where('type', 'hmac_sha256')->chunk( + $uIdModel->where('type', 'hmac_sha256')->orderBy('id')->chunk( 100, static function ($identity) use ($uIdModelSub, $decrypter, $encrypter, $that): void { - if (! $decrypter->isEncrypted($identity->secret2)) { + if (! $decrypter->isEncryptedWithSetKey($identity->secret2)) { $that->write('id: ' . $identity->id . ', not re-encrypted, skipped.'); return; diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 8092fce9c..9e4241378 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -74,84 +74,45 @@ class AuthToken extends BaseConfig /** * -------------------------------------------------------------------- - * HMAC encryption key + * HMAC encryption Keys * -------------------------------------------------------------------- - * Key to be used when encrypting HMAC Secret Key for storage. + * This sets the key to be used when encrypting a user's HMAC Secret Key. * - * This is an array of keys which will facilitate key rotation. Valid + * 'key' is an array of keys which will facilitate key rotation. Valid * keyTitles must include only [a-zA-z0-9_] and should be kept to a * max of 8 characters. * - * The valid and old/deprecated keys are identified using $hmacKeyIndex - * and $hmacDeprecatedKeyIndex. - * - * @param array|string $hmacEncryptionKey ['keyTitle' => 'keyValue'] - * - * @see https://codeigniter.com/user_guide/libraries/encryption.html - */ - public $hmacEncryptionKey = [ - 'k1' => '', - ]; - - /** - * -------------------------------------------------------------------- - * HMAC encryption driver - * -------------------------------------------------------------------- - * Driver to be used when encrypting HMAC Secret Key for storage. - * - * Available drivers: - * OpenSSL - * Sodium + * 'driver' is used when encrypting HMAC Secret Key for storage. + * Available drivers: + * - OpenSSL + * - Sodium * * This is an array of drivers values. The keys MUST match and correlate - * to the $hmacEncryptionKey array keys. - * - * @param array|string $hmacEncryptionDriver ['keyTitle' => 'driverValue'] + * to the 'key' array keys. * - * @see https://codeigniter.com/user_guide/libraries/encryption.html - */ - public $hmacEncryptionDriver = [ - 'k1' => 'OpenSSL', - ]; - - /** - * -------------------------------------------------------------------- - * HMAC encryption digest - * -------------------------------------------------------------------- - * Digest to be used when encrypting HMAC Secret Key for storage. - * - * e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. + * 'digest' is used when encrypting HMAC Secret Key for storage. + * e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. * * This is an array of digest values. The keys MUST match and correlate - * to the $hmacEncryptionKey array keys. + * to the 'key' array keys. + * + * The valid and old/deprecated keys are identified using 'currentKey' + * and 'deprecatedKey'. * - * @param array|string $hmacEncryptionDigest ['keyTitle' => 'digestValue'] + * 'deprecatedKey' reflects which 'key' is recently deprecated. This + * is required and used when rotating keys. Effectively, this is the + * index selector for the old key. * * @see https://codeigniter.com/user_guide/libraries/encryption.html */ - public $hmacEncryptionDigest = [ - 'k1' => 'SHA512', + public array $hmacEncryption = [ + 'key' => ['k1' => ''], + 'driver' => ['k1' => 'OpenSSL'], + 'digest' => ['k1' => 'SHA512'], + 'currentKey' => 'k1', + 'deprecatedKey' => '', ]; - /** - * -------------------------------------------------------------------- - * HMAC encryption key selector - * -------------------------------------------------------------------- - * This identifies which encryption key {$hmacEncryptionKey} is active - * and valid. - */ - public string $hmacKeyIndex = 'k1'; - - /** - * -------------------------------------------------------------------- - * HMAC encryption key deprecated selector - * -------------------------------------------------------------------- - * This identifies which encryption key {$hmacEncryptionKey} is - * recently deprecated. This is required and used when rotating keys. - * Effectively, this is the index selector for the old key. - */ - public string $hmacDeprecatedKeyIndex = ''; - /** * AuthToken Config Constructor */ @@ -159,22 +120,18 @@ public function __construct() { parent::__construct(); - if (is_string($this->hmacEncryptionKey)) { - $array = json_decode($this->hmacEncryptionKey, true); - if (is_array($array)) { - $this->hmacEncryptionKey = $array; - } - } - if (is_string($this->hmacEncryptionDriver)) { - $array = json_decode($this->hmacEncryptionDriver, true); - if (is_array($array)) { - $this->hmacEncryptionDriver = $array; - } - } - if (is_string($this->hmacEncryptionDigest)) { - $array = json_decode($this->hmacEncryptionDigest, true); - if (is_array($array)) { - $this->hmacEncryptionDigest = $array; + $overwriteHmacEncryptionFields = [ + 'key', + 'driver', + 'digest', + ]; + + foreach ($overwriteHmacEncryptionFields as $fieldName) { + if (is_string($this->hmacEncryption[$fieldName])) { + $array = json_decode($this->hmacEncryption[$fieldName], true); + if (is_array($array)) { + $this->hmacEncryption[$fieldName] = $array; + } } } } @@ -189,12 +146,12 @@ public function __construct() protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void { switch ($name) { - case 'hmacEncryptionKey': - case 'hmacEncryptionDriver': - case 'hmacEncryptionDigest': + case 'hmacEncryption.key': + case 'hmacEncryption.driver': + case 'hmacEncryption.digest': // if attempting to set property from ENV, first set to empty string if ((bool) $this->getEnvValue($name, $prefix, $shortPrefix)) { - $property = ''; + $property = null; } } diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index f782357ff..6e267f383 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -44,6 +44,13 @@ public function testEncrypt(): void $decryptedKey = $encrypter->decrypt($tokenCheck->secret2); $this->assertSame($rawSecretKey, $decryptedKey); + + // verify that encryption can only happen once + $this->setMockIo([]); + $this->assertNotFalse(command('shield:hmac encrypt')); + + $resultsString = trim($this->io->getOutputs()); + $this->assertSame('id: 1, already encrypted, skipped.', $resultsString); } public function testDecrypt(): void @@ -64,6 +71,13 @@ public function testDecrypt(): void $tokenCheck = $idModel->find($token->id); $this->assertSame($rawSecretKey, $tokenCheck->secret2); + + // verify that decryption does not run on fields already decrypted + $this->setMockIo([]); + $this->assertNotFalse(command('shield:hmac decrypt')); + + $resultsString = trim($this->io->getOutputs()); + $this->assertSame('id: 1, not encrypted, skipped.', $resultsString); } public function testReEncrypt(): void @@ -79,8 +93,8 @@ public function testReEncrypt(): void /** @var AuthToken $config */ $config = config('AuthToken'); - $config->hmacKeyIndex = 'k2'; - $config->hmacDeprecatedKeyIndex = 'k1'; + $config->hmacEncryption['currentKey'] = 'k2'; + $config->hmacEncryption['deprecatedKey'] = 'k1'; // new key generated with updated encryption $token2 = $user->generateHmacToken('bar'); @@ -107,6 +121,16 @@ public function testReEncrypt(): void $this->assertSame($token2->rawSecretKey, $descryptSecretKey2); } + public function testBadCommand(): void + { + $this->setMockIo([]); + $this->assertNotFalse(command('shield:hmac badcommand')); + + $resultsString = $this->stripRedColorCode(trim($this->io->getOutputs())); + + $this->assertSame('Unrecognized Command', $resultsString); + } + /** * Set MockInputOutput and user inputs. * @@ -119,4 +143,20 @@ private function setMockIo(array $inputs): void $this->io->setInputs($inputs); Hmac::setInputOutput($this->io); } + + /** + * Strip color from output code + * + * @param mixed $output + */ + private function stripRedColorCode($output): string + { + $output = str_replace(["\033[0;31m", "\033[0m"], '', $output); + + if (is_windows()) { + $output = str_replace("\r\n", "\n", $output); + } + + return $output; + } } From 76fc1fede3c3c0c6f78c4b0be9f56d750b00ac61 Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Mon, 13 Nov 2023 19:27:21 -0600 Subject: [PATCH 097/128] Update docs/references/authentication/hmac.md Co-authored-by: kenjis --- docs/references/authentication/hmac.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index c264a2cc4..0ecc5c1d1 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -187,7 +187,7 @@ old key. After the new encryption key is in place, run `php spark shield:hmac r with the new encryption key. ```php -public array $hmacEncryption [ +public array $hmacEncryption = [ 'key' => [ 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', 'k2' => 'hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0', @@ -198,10 +198,10 @@ public array $hmacEncryption [ ], 'digest' => [ 'k1' => 'SHA512', - 'k2' => 'SHA512' + 'k2' => 'SHA512', ], - 'currentKey' => 'k2', - 'deprecatedKey' => 'k1' + 'currentKey' => 'k2', + 'deprecatedKey' => 'k1', ]; ``` From 303082b0dc9af81f40dd1b3774f59bd3a663853d Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Mon, 13 Nov 2023 19:27:44 -0600 Subject: [PATCH 098/128] Update docs/references/authentication/hmac.md Co-authored-by: kenjis --- docs/references/authentication/hmac.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 0ecc5c1d1..1f7bdbbaf 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -170,14 +170,14 @@ You will also be able to adjust the default Driver `$hmacEncryption['driver']` a `$hmacEncryption['driver']`, and `$hmacEncryption['digest']`) are set in array format (see below). ```php -public array $hmacEncryption [ +public array $hmacEncryption = [ 'key' => [ 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', ], - 'driver' => ['k1' => 'OpenSSL'], - 'digest' => ['k1' => 'SHA512'], - 'currentKey' => 'k1', - 'deprecatedKey' => null + 'driver' => ['k1' => 'OpenSSL'], + 'digest' => ['k1' => 'SHA512'], + 'currentKey' => 'k1', + 'deprecatedKey' => null, ]; ``` From 493ebc670dae163e37980ab1c23b6c322414ed86 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 14 Nov 2023 10:05:56 -0600 Subject: [PATCH 099/128] Removed old code --- src/Authentication/HMAC/HmacEncrypter.php | 10 +--------- src/Config/AuthToken.php | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index 63132eb5a..fb78fa2b8 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -47,13 +47,6 @@ public function __construct(bool $deprecatedKey = false) $authConfig = config('AuthToken'); $config = new Encryption(); - // // identify which encryption key should be used - // $this->keyIndex = $deprecatedKey ? $authConfig->hmacDeprecatedKeyIndex : $authConfig->hmacKeyIndex; - // - // $config->key = $authConfig->hmacEncryptionKey[$this->keyIndex]; - // $config->driver = $authConfig->hmacEncryptionDriver[$this->keyIndex]; - // $config->digest = $authConfig->hmacEncryptionDigest[$this->keyIndex]; - // identify which encryption key should be used $this->keyIndex = $deprecatedKey ? $authConfig->hmacEncryption['deprecatedKey'] : $authConfig->hmacEncryption['currentKey']; @@ -117,8 +110,7 @@ public function isEncrypted(string $string): bool */ public function isEncryptedWithSetKey(string $string): bool { - return (bool) preg_match('/^\$b6\$' . $this->keyIndex . '\$/', $string); - // return str_starts_with($string, '$b6$' . $this->keyIndex . '$'); + return preg_match('/^\$b6\$' . $this->keyIndex . '\$/', $string) === 1; } /** diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 9e4241378..ae74edaa7 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -150,8 +150,8 @@ protected function initEnvValue(&$property, string $name, string $prefix, string case 'hmacEncryption.driver': case 'hmacEncryption.digest': // if attempting to set property from ENV, first set to empty string - if ((bool) $this->getEnvValue($name, $prefix, $shortPrefix)) { - $property = null; + if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { + $property = ''; } } From e5d81e423389e890eb405d3ab725f540393c4348 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 14 Nov 2023 15:38:28 -0600 Subject: [PATCH 100/128] Rework of encrypter so it can decrypt all old keys. Added parent config to AuthToken.php. Update documentation to reflect change. --- docs/references/authentication/hmac.md | 9 +-- src/Authentication/HMAC/HmacEncrypter.php | 77 ++++++++++++++--------- src/Commands/Hmac.php | 7 +-- src/Commands/Setup.php | 5 +- src/Config/AuthToken.php | 69 +++----------------- src/Config/BaseAuthToken.php | 57 +++++++++++++++++ tests/Commands/HmacTest.php | 3 +- 7 files changed, 123 insertions(+), 104 deletions(-) create mode 100644 src/Config/BaseAuthToken.php diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 1f7bdbbaf..d8bb30394 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -177,14 +177,13 @@ public array $hmacEncryption = [ 'driver' => ['k1' => 'OpenSSL'], 'digest' => ['k1' => 'SHA512'], 'currentKey' => 'k1', - 'deprecatedKey' => null, ]; ``` When it is time to update your encryption keys you will need to add an additional key to the above arrays. Then adjust -the `$hmacEncryption['currentKey']` to point at the new key and adjust `$hmacEncryption['deprecatedKey']` to point at the -old key. After the new encryption key is in place, run `php spark shield:hmac reencrypt` to re-encrypt all existing keys -with the new encryption key. +the `$hmacEncryption['currentKey']` to point at the new key. After the new encryption key is in place, run +`php spark shield:hmac reencrypt` to re-encrypt all existing keys with the new encryption key. You will need to leave +the old key in the array as it will be used read the existing keys during re-encryption. ```php public array $hmacEncryption = [ @@ -201,7 +200,6 @@ public array $hmacEncryption = [ 'k2' => 'SHA512', ], 'currentKey' => 'k2', - 'deprecatedKey' => 'k1', ]; ``` @@ -217,7 +215,6 @@ authtoken.hmacEncryption.key = '{"k1":"hex2bin:923dfab5ddca0c7784c2c388a848a704f authtoken.hmacEncryption.driver = '{"k1":"OpenSSL","k2":"OpenSSL"}' authtoken.hmacEncryption.digest = '{"k1":"SHA512","k2":"SHA512"}' authtoken.hmacEncryption.currentKey = k2 -authtoken.hmacEncryption.deprecatedKey = k1 ``` Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index fb78fa2b8..bb5f00610 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -22,41 +22,25 @@ class HmacEncrypter { /** * Codeigniter Encrypter + * + * @var array */ - private EncrypterInterface $encrypter; + private array $encrypter; /** * Auth Token config */ private AuthToken $authConfig; - /** - * Selected Key Index - */ - private string $keyIndex; - /** * Constructor * Setup encryption configuration - * - * @param bool $deprecatedKey Use the deprecated key (useful when re-encrypting on key rotation) [default: false] */ - public function __construct(bool $deprecatedKey = false) + public function __construct() { - /** @var AuthToken $authConfig */ - $authConfig = config('AuthToken'); - $config = new Encryption(); - - // identify which encryption key should be used - $this->keyIndex = $deprecatedKey ? $authConfig->hmacEncryption['deprecatedKey'] : $authConfig->hmacEncryption['currentKey']; + $this->authConfig = config('AuthToken'); - $config->key = $authConfig->hmacEncryption['key'][$this->keyIndex]; - $config->driver = $authConfig->hmacEncryption['driver'][$this->keyIndex]; - $config->digest = $authConfig->hmacEncryption['digest'][$this->keyIndex]; - - $this->authConfig = $authConfig; - // decrypt secret key so signature can be validated - $this->encrypter = Services::encrypter($config); + $this->getEncrypter($this->authConfig->hmacEncryption['currentKey']); } /** @@ -70,10 +54,15 @@ public function __construct(bool $deprecatedKey = false) */ public function decrypt(string $encString): string { - // Removes `$b6$keyIndex$` for base64 format. - $encString = substr($encString, strlen($this->keyIndex) + 5); + $matches = []; + // check for a match + if (preg_match('/^\$b6\$(\w+?)\$(.+)$/', $encString, $matches) !== 1) { + throw new EncryptionException('Unable to decrypt string'); + } + + $encrypter = $this->getEncrypter($matches[1]); - return $this->encrypter->decrypt(base64_decode($encString, true)); + return $encrypter->decrypt(base64_decode($matches[2], true)); } /** @@ -88,7 +77,9 @@ public function decrypt(string $encString): string */ public function encrypt(string $rawString): string { - $encryptedString = '$b6$' . $this->keyIndex . '$' . base64_encode($this->encrypter->encrypt($rawString)); + $currentKey = $this->authConfig->hmacEncryption['currentKey']; + + $encryptedString = '$b6$' . $currentKey . '$' . base64_encode($this->encrypter[$currentKey]->encrypt($rawString)); if (strlen($encryptedString) > $this->authConfig->secret2StorageLimit) { throw new RuntimeException('Encrypted key too long. Unable to store value.'); @@ -102,15 +93,17 @@ public function encrypt(string $rawString): string */ public function isEncrypted(string $string): bool { - return (bool) preg_match('/^\$b6\$/', $string); + return preg_match('/^\$b6\$/', $string) === 1; } /** - * Check if the string already encrypted + * Check if the string already encrypted with the Current Set Key */ - public function isEncryptedWithSetKey(string $string): bool + public function isEncryptedWithCurrentKey(string $string): bool { - return preg_match('/^\$b6\$' . $this->keyIndex . '\$/', $string) === 1; + $currentKey = $this->authConfig->hmacEncryption['currentKey']; + + return preg_match('/^\$b6\$' . $currentKey . '\$/', $string) === 1; } /** @@ -124,4 +117,28 @@ public function generateSecretKey(): string { return base64_encode(random_bytes($this->authConfig->hmacSecretKeyByteSize)); } + + /** + * Retrieve encrypter for selected key + * + * @param string $encrypterKey Index Key for selected Encrypter + */ + private function getEncrypter(string $encrypterKey): EncrypterInterface + { + if (! isset($this->encrypter[$encrypterKey])) { + if (! isset($this->authConfig->hmacEncryption['key'][$encrypterKey])) { + throw new RuntimeException('Encryption key does not exist.'); + } + + $config = new Encryption(); + + $config->key = $this->authConfig->hmacEncryption['key'][$encrypterKey]; + $config->driver = $this->authConfig->hmacEncryption['driver'][$encrypterKey]; + $config->digest = $this->authConfig->hmacEncryption['digest'][$encrypterKey]; + + $this->encrypter[$encrypterKey] = Services::encrypter($config); + } + + return $this->encrypter[$encrypterKey]; + } } diff --git a/src/Commands/Hmac.php b/src/Commands/Hmac.php index 907dc94af..fd78a779e 100644 --- a/src/Commands/Hmac.php +++ b/src/Commands/Hmac.php @@ -176,21 +176,20 @@ public function reEncrypt(): void { $uIdModel = new UserIdentityModel(); $uIdModelSub = new UserIdentityModel(); // For saving. - $decrypter = new HmacEncrypter(true); $encrypter = $this->encrypter; $that = $this; $uIdModel->where('type', 'hmac_sha256')->orderBy('id')->chunk( 100, - static function ($identity) use ($uIdModelSub, $decrypter, $encrypter, $that): void { - if (! $decrypter->isEncryptedWithSetKey($identity->secret2)) { + static function ($identity) use ($uIdModelSub, $encrypter, $that): void { + if ($encrypter->isEncryptedWithCurrentKey($identity->secret2)) { $that->write('id: ' . $identity->id . ', not re-encrypted, skipped.'); return; } - $identity->secret2 = $decrypter->decrypt($identity->secret2); + $identity->secret2 = $encrypter->decrypt($identity->secret2); $identity->secret2 = $encrypter->encrypt($identity->secret2); $uIdModelSub->save($identity); diff --git a/src/Commands/Setup.php b/src/Commands/Setup.php index 0f14a6e26..45b105e47 100644 --- a/src/Commands/Setup.php +++ b/src/Commands/Setup.php @@ -140,9 +140,8 @@ private function publishConfigAuthToken(): void { $file = 'Config/AuthToken.php'; $replaces = [ - 'namespace CodeIgniter\Shield\Config' => 'namespace Config', - 'use CodeIgniter\\Config\\BaseConfig;' => 'use CodeIgniter\\Shield\\Config\\AuthToken as ShieldAuthToken;', - 'extends BaseConfig' => 'extends ShieldAuthToken', + 'namespace CodeIgniter\Shield\Config;' => "namespace Config;\n\nuse CodeIgniter\\Shield\\Config\\AuthToken as ShieldAuthToken;", + 'extends BaseAuthToken' => 'extends ShieldAuthToken', ]; $this->copyAndReplace($file, $replaces); diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index ae74edaa7..829737632 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -13,12 +13,10 @@ namespace CodeIgniter\Shield\Config; -use CodeIgniter\Config\BaseConfig; - /** * Configuration for Token Auth and HMAC Auth */ -class AuthToken extends BaseConfig +class AuthToken extends BaseAuthToken { /** * -------------------------------------------------------------------- @@ -79,7 +77,7 @@ class AuthToken extends BaseConfig * This sets the key to be used when encrypting a user's HMAC Secret Key. * * 'key' is an array of keys which will facilitate key rotation. Valid - * keyTitles must include only [a-zA-z0-9_] and should be kept to a + * keyTitles must include only [a-zA-Z0-9_] and should be kept to a * max of 8 characters. * * 'driver' is used when encrypting HMAC Secret Key for storage. @@ -96,65 +94,18 @@ class AuthToken extends BaseConfig * This is an array of digest values. The keys MUST match and correlate * to the 'key' array keys. * - * The valid and old/deprecated keys are identified using 'currentKey' - * and 'deprecatedKey'. + * The valid/current key is identified using 'currentKey' * - * 'deprecatedKey' reflects which 'key' is recently deprecated. This - * is required and used when rotating keys. Effectively, this is the - * index selector for the old key. + * Old keys will are used to decrypt existing Secret Keys. It is encouraged + * to run 'php spark shield:hmac reencrypt' to update existing Secret + * Key encryptions. * * @see https://codeigniter.com/user_guide/libraries/encryption.html */ public array $hmacEncryption = [ - 'key' => ['k1' => ''], - 'driver' => ['k1' => 'OpenSSL'], - 'digest' => ['k1' => 'SHA512'], - 'currentKey' => 'k1', - 'deprecatedKey' => '', + 'key' => ['k1' => ''], + 'driver' => ['k1' => 'OpenSSL'], + 'digest' => ['k1' => 'SHA512'], + 'currentKey' => 'k1', ]; - - /** - * AuthToken Config Constructor - */ - public function __construct() - { - parent::__construct(); - - $overwriteHmacEncryptionFields = [ - 'key', - 'driver', - 'digest', - ]; - - foreach ($overwriteHmacEncryptionFields as $fieldName) { - if (is_string($this->hmacEncryption[$fieldName])) { - $array = json_decode($this->hmacEncryption[$fieldName], true); - if (is_array($array)) { - $this->hmacEncryption[$fieldName] = $array; - } - } - } - } - - /** - * Override parent initEnvValue() to allow for direct setting to array properties values from ENV - * - * In order to set array properties via ENV vars we need to set the property to a string value first. - * - * @param mixed $property - */ - protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void - { - switch ($name) { - case 'hmacEncryption.key': - case 'hmacEncryption.driver': - case 'hmacEncryption.digest': - // if attempting to set property from ENV, first set to empty string - if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { - $property = ''; - } - } - - parent::initEnvValue($property, $name, $prefix, $shortPrefix); - } } diff --git a/src/Config/BaseAuthToken.php b/src/Config/BaseAuthToken.php new file mode 100644 index 000000000..73ac438f4 --- /dev/null +++ b/src/Config/BaseAuthToken.php @@ -0,0 +1,57 @@ +hmacEncryption[$fieldName])) { + $array = json_decode($this->hmacEncryption[$fieldName], true); + if (is_array($array)) { + $this->hmacEncryption[$fieldName] = $array; + } + } + } + } + + /** + * Override parent initEnvValue() to allow for direct setting to array properties values from ENV + * + * In order to set array properties via ENV vars we need to set the property to a string value first. + * + * @param mixed $property + */ + protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void + { + switch ($name) { + case 'hmacEncryption.key': + case 'hmacEncryption.driver': + case 'hmacEncryption.digest': + // if attempting to set property from ENV, first set to empty string + if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { + $property = ''; + } + } + + parent::initEnvValue($property, $name, $prefix, $shortPrefix); + } +} diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 6e267f383..1c923284b 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -93,8 +93,7 @@ public function testReEncrypt(): void /** @var AuthToken $config */ $config = config('AuthToken'); - $config->hmacEncryption['currentKey'] = 'k2'; - $config->hmacEncryption['deprecatedKey'] = 'k1'; + $config->hmacEncryption['currentKey'] = 'k2'; // new key generated with updated encryption $token2 = $user->generateHmacToken('bar'); From c20031da6db9b58cee0b31c697028475157a40d7 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 14 Nov 2023 15:44:42 -0600 Subject: [PATCH 101/128] Minor update to text output --- src/Commands/Hmac.php | 2 +- tests/Commands/HmacTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Commands/Hmac.php b/src/Commands/Hmac.php index fd78a779e..e15c57f2b 100644 --- a/src/Commands/Hmac.php +++ b/src/Commands/Hmac.php @@ -184,7 +184,7 @@ public function reEncrypt(): void 100, static function ($identity) use ($uIdModelSub, $encrypter, $that): void { if ($encrypter->isEncryptedWithCurrentKey($identity->secret2)) { - $that->write('id: ' . $identity->id . ', not re-encrypted, skipped.'); + $that->write('id: ' . $identity->id . ', already encrypted with current key, skipped.'); return; } diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 1c923284b..a38fb8923 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -107,7 +107,7 @@ public function testReEncrypt(): void // verify that only 1 key needed to be re-encrypted $this->assertCount(2, $results); $this->assertSame('id: 1, Re-encrypted.', $results[0]); - $this->assertSame('id: 2, not re-encrypted, skipped.', $results[1]); + $this->assertSame('id: 2, already encrypted with current key, skipped.', $results[1]); $encrypter = new HmacEncrypter(); From a3e4219cd3afbb208c577225ff5a22c368da518f Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 14 Nov 2023 16:02:28 -0600 Subject: [PATCH 102/128] Documentation text clarification --- docs/references/authentication/hmac.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index d8bb30394..e0092f4f1 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -183,7 +183,7 @@ public array $hmacEncryption = [ When it is time to update your encryption keys you will need to add an additional key to the above arrays. Then adjust the `$hmacEncryption['currentKey']` to point at the new key. After the new encryption key is in place, run `php spark shield:hmac reencrypt` to re-encrypt all existing keys with the new encryption key. You will need to leave -the old key in the array as it will be used read the existing keys during re-encryption. +the old key in the array as it will be used read the existing 'Secret Keys' during re-encryption. ```php public array $hmacEncryption = [ From 3d1077c458c3f916f4a5fb796d104a60fab6468f Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Tue, 14 Nov 2023 20:42:44 -0600 Subject: [PATCH 103/128] Update tests/Commands/HmacTest.php Co-authored-by: kenjis --- tests/Commands/HmacTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index a38fb8923..5d1243f86 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -148,7 +148,7 @@ private function setMockIo(array $inputs): void * * @param mixed $output */ - private function stripRedColorCode($output): string + private function stripRedColorCode(string $output): string { $output = str_replace(["\033[0;31m", "\033[0m"], '', $output); From 0c8ef4ccf83e3e738229dd24171d75d4142a0a70 Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Tue, 14 Nov 2023 20:44:21 -0600 Subject: [PATCH 104/128] Update tests/Commands/HmacTest.php Co-authored-by: kenjis --- tests/Commands/HmacTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 5d1243f86..8ee8a926f 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -133,8 +133,7 @@ public function testBadCommand(): void /** * Set MockInputOutput and user inputs. * - * @param array $inputs User inputs - * @phpstan-param list $inputs + * @param list $inputs User inputs */ private function setMockIo(array $inputs): void { From 8dca06dbc52e8e193277b3d9e366e41845526aa0 Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Tue, 14 Nov 2023 20:47:53 -0600 Subject: [PATCH 105/128] Update tests/Commands/HmacTest.php Co-authored-by: kenjis --- tests/Commands/HmacTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 8ee8a926f..8b15252ef 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -144,8 +144,6 @@ private function setMockIo(array $inputs): void /** * Strip color from output code - * - * @param mixed $output */ private function stripRedColorCode(string $output): string { From f2552cd450cac9eb5ea63224dd1a0ba2982cba60 Mon Sep 17 00:00:00 2001 From: tswagger Date: Wed, 15 Nov 2023 08:52:04 -0600 Subject: [PATCH 106/128] Replaced $ in regex --- src/Authentication/HMAC/HmacEncrypter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index bb5f00610..fa5c2f9ef 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -56,7 +56,7 @@ public function decrypt(string $encString): string { $matches = []; // check for a match - if (preg_match('/^\$b6\$(\w+?)\$(.+)$/', $encString, $matches) !== 1) { + if (preg_match('/^\$b6\$(\w+?)\$(.+)\z/', $encString, $matches) !== 1) { throw new EncryptionException('Unable to decrypt string'); } From bcad7328cc057cc51e7f7bb55997236e4794b715 Mon Sep 17 00:00:00 2001 From: tswagger Date: Fri, 17 Nov 2023 12:48:55 -0600 Subject: [PATCH 107/128] Removed double-spaces between sentences. --- UPGRADING.md | 2 +- docs/guides/api_hmac_keys.md | 2 +- docs/references/authentication/hmac.md | 10 +++++----- src/Config/AuthToken.php | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 0a79d9f86..a64d1fa07 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -64,7 +64,7 @@ these currently default to `'OpenSSL'` and `'SHA512'` respectively. #### Encrypt Existing Keys After updating the `$hmacEncryption['key']` value, you will need to run `php spark shield:hmac encrypt` in order to encrypt -any existing HMAC tokens. This only needs to be run if you have existing unencrypted HMAC secretKeys in stored in the +any existing HMAC tokens. This only needs to be run if you have existing unencrypted HMAC secretKeys in stored in the database. ## Version 1.0.0-beta.6 to 1.0.0-beta.7 diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index 4417143af..50dd1d994 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -90,7 +90,7 @@ $user->revokeAllHmacTokens(); ## HMAC Secret Key Encryption -The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key +The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key `$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index e0092f4f1..d552d70f7 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -72,7 +72,7 @@ instance of `CodeIgniters\Shield\Authentication\Entities\AccessToken`. The field `rawSecretKey` is the shared '**secretKey**'. Both are required to when using this authentication method. **The plain text version of these keys should be displayed to the user immediately, so they can copy it for -their use.** It is recommended that after that only the '**key**' field is displayed to a user. If a user loses the +their use.** It is recommended that after that only the '**key**' field is displayed to a user. If a user loses the '**secretKey**', they should be required to generate a new set of keys to use. ```php @@ -159,8 +159,8 @@ if ($user->hmacTokenCant('forums.manage')) { ## HMAC Secret Key Encryption -The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key -`$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using .env and/or system environment variables. +The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key +`$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation. @@ -210,7 +210,7 @@ php spark shield:hmac reencrypt You can (and should) set these values using environment variable and/or the `.env` file. To do this you will need to set the values as JSON strings: -```dotenv +```text authtoken.hmacEncryption.key = '{"k1":"hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7","k2":"hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0"}' authtoken.hmacEncryption.driver = '{"k1":"OpenSSL","k2":"OpenSSL"}' authtoken.hmacEncryption.digest = '{"k1":"SHA512","k2":"SHA512"}' @@ -218,5 +218,5 @@ authtoken.hmacEncryption.currentKey = k2 ``` Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to -exceed the database column character limit of 255 characters. If this happens, creation of a new HMAC identity will +exceed the database column character limit of 255 characters. If this happens, creation of a new HMAC identity will throw a `RuntimeException`. diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 829737632..c948025a5 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -85,18 +85,18 @@ class AuthToken extends BaseAuthToken * - OpenSSL * - Sodium * - * This is an array of drivers values. The keys MUST match and correlate + * This is an array of drivers values. The keys MUST match and correlate * to the 'key' array keys. * * 'digest' is used when encrypting HMAC Secret Key for storage. * e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. * - * This is an array of digest values. The keys MUST match and correlate + * This is an array of digest values. The keys MUST match and correlate * to the 'key' array keys. * * The valid/current key is identified using 'currentKey' * - * Old keys will are used to decrypt existing Secret Keys. It is encouraged + * Old keys will are used to decrypt existing Secret Keys. It is encouraged * to run 'php spark shield:hmac reencrypt' to update existing Secret * Key encryptions. * From aa0d7f56f75cc64274e1298d19d1912ec537b9d2 Mon Sep 17 00:00:00 2001 From: tswagger Date: Fri, 17 Nov 2023 15:48:40 -0600 Subject: [PATCH 108/128] Trim of test output for Windows machines --- tests/Commands/HmacTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 8b15252ef..b8f899a95 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -106,8 +106,8 @@ public function testReEncrypt(): void // verify that only 1 key needed to be re-encrypted $this->assertCount(2, $results); - $this->assertSame('id: 1, Re-encrypted.', $results[0]); - $this->assertSame('id: 2, already encrypted with current key, skipped.', $results[1]); + $this->assertSame('id: 1, Re-encrypted.', trim($results[0])); + $this->assertSame('id: 2, already encrypted with current key, skipped.', trim($results[1])); $encrypter = new HmacEncrypter(); From 5acf382a0cef4a09d8468cb035dbbc3679e80ef6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 21 Nov 2023 05:59:09 +0900 Subject: [PATCH 109/128] docs: fix markdown Co-authored-by: Pooya Parsa --- docs/references/authentication/hmac.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index d552d70f7..c64b19f69 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -203,7 +203,7 @@ public array $hmacEncryption = [ ]; ``` -```shell +```console php spark shield:hmac reencrypt ``` From 795a21477edac62f75b38a9979ba239c418850d3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 21 Nov 2023 05:59:26 +0900 Subject: [PATCH 110/128] docs: fix text decoration Co-authored-by: Pooya Parsa --- docs/references/authentication/hmac.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index c64b19f69..0a3caa083 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -207,7 +207,7 @@ public array $hmacEncryption = [ php spark shield:hmac reencrypt ``` -You can (and should) set these values using environment variable and/or the `.env` file. To do this you will need to set +You can (and should) set these values using environment variable and/or the **.env** file. To do this you will need to set the values as JSON strings: ```text From 2570a7cf4a7255c999e73908a05bdd9f7aca7618 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 21 Nov 2023 10:57:01 -0600 Subject: [PATCH 111/128] Update of hmac encryption config values --- UPGRADING.md | 14 +++--- docs/guides/api_hmac_keys.md | 8 +-- docs/references/authentication/hmac.md | 61 +++++++++++------------ phpunit.xml.dist | 4 +- src/Authentication/HMAC/HmacEncrypter.php | 14 +++--- src/Config/AuthToken.php | 61 +++++++++++++++-------- src/Config/BaseAuthToken.php | 27 ++++------ tests/Commands/HmacTest.php | 2 +- 8 files changed, 101 insertions(+), 90 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index a64d1fa07..e004c9d2c 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -53,19 +53,19 @@ protected function redirectToDeniedUrl(): RedirectResponse #### Config\AuthToken If you are using the HMAC authentication you need to update the encryption settings in **app/Config/AuthToken.php**. -You will need to update and set the encryption key `$hmacEncryption['key']`. This should be set using **.env** and/or system -environment variables. Instructions on how to do that can be found in the +You will need to update and set the encryption key in `$hmacEncryptionKeys`. This should be set using **.env** and/or +system environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation and in [HMAC SHA256 Token Authenticator](./docs/references/authentication/hmac.md#hmac-secret-key-encryption). -You also may wish to adjust the default Driver `$hmacEncryption['driver']` and the default Digest `$hmacEncryption['digest']`, -these currently default to `'OpenSSL'` and `'SHA512'` respectively. +You also may wish to adjust the default Driver `$hmacEncryptionDefaultDriver` and the default Digest +`$hmacEncryptionDefaultDigest`, these currently default to `'OpenSSL'` and `'SHA512'` respectively. #### Encrypt Existing Keys -After updating the `$hmacEncryption['key']` value, you will need to run `php spark shield:hmac encrypt` in order to encrypt -any existing HMAC tokens. This only needs to be run if you have existing unencrypted HMAC secretKeys in stored in the -database. +After updating the key in `$hmacEncryptionKeys` value, you will need to run `php spark shield:hmac encrypt` in order +to encrypt any existing HMAC tokens. This only needs to be run if you have existing unencrypted HMAC secretKeys in +stored in the database. ## Version 1.0.0-beta.6 to 1.0.0-beta.7 diff --git a/docs/guides/api_hmac_keys.md b/docs/guides/api_hmac_keys.md index 50dd1d994..eec6a0651 100644 --- a/docs/guides/api_hmac_keys.md +++ b/docs/guides/api_hmac_keys.md @@ -91,13 +91,13 @@ $user->revokeAllHmacTokens(); ## HMAC Secret Key Encryption The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key -`$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system environment variables. -Instructions on how to do that can be found in the +in `$hmacEncryptionKeys` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system +environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation. -You will also be able to adjust the default Driver `$hmacEncryption['driver']` and the default Digest -`$hmacEncryption['digest']`, these default to `'OpenSSL'` and `'SHA512'` respectively. +You will also be able to adjust the default Driver `$hmacEncryptionDefaultDriver` and the default Digest +`$hmacEncryptionDefaultDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. See [HMAC SHA256 Token Authenticator](../references/authentication/hmac.md#hmac-secret-key-encryption) for additional details on setting these values. diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 0a3caa083..9e4f75ae4 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -160,47 +160,48 @@ if ($user->hmacTokenCant('forums.manage')) { ## HMAC Secret Key Encryption The HMAC Secret Key is stored encrypted. Before you start using HMAC, you will need to set/override the encryption key -`$hmacEncryption['key']` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system environment variables. -Instructions on how to do that can be found in the +in `$hmacEncryptionKeys` in **app/Config/AuthToken.php**. This should be set using **.env** and/or system +environment variables. Instructions on how to do that can be found in the [Setting Your Encryption Key](https://codeigniter.com/user_guide/libraries/encryption.html#setting-your-encryption-key) section of the CodeIgniter 4 documentation. -You will also be able to adjust the default Driver `$hmacEncryption['driver']` and the default Digest -`$hmacEncryption['digest']`, these default to `'OpenSSL'` and `'SHA512'` respectively. All three properties (`$hmacEncryption['key']`, -`$hmacEncryption['driver']`, and `$hmacEncryption['digest']`) are set in array format (see below). +You will also be able to adjust the default Driver `$hmacEncryptionDefaultDriver` and the default Digest +`$hmacEncryptionDefaultDigest`, these default to `'OpenSSL'` and `'SHA512'` respectively. These can also be +overridden for an individual key by including them in the keys array. ```php -public array $hmacEncryption = [ - 'key' => [ - 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', +public array $hmacEncryptionKeys = [ + 'k1' => [ + 'key' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', ], - 'driver' => ['k1' => 'OpenSSL'], - 'digest' => ['k1' => 'SHA512'], - 'currentKey' => 'k1', ]; + +public string $hmacEncryptionCurrentKey = 'k1'; +public string $hmacEncryptionDefaultDriver = 'OpenSSL'; +public string $hmacEncryptionDefaultDigest = 'SHA512'; ``` -When it is time to update your encryption keys you will need to add an additional key to the above arrays. Then adjust -the `$hmacEncryption['currentKey']` to point at the new key. After the new encryption key is in place, run -`php spark shield:hmac reencrypt` to re-encrypt all existing keys with the new encryption key. You will need to leave -the old key in the array as it will be used read the existing 'Secret Keys' during re-encryption. +When it is time to update your encryption keys you will need to add an additional key to the above +`$hmacEncryptionKeys` array. Then adjust the `$hmacEncryptionCurrentKey` to point at the new key. After the new +encryption key is in place, run `php spark shield:hmac reencrypt` to re-encrypt all existing keys with the new +encryption key. You will need to leave the old key in the array as it will be used read the existing 'Secret Keys' +during re-encryption. ```php -public array $hmacEncryption = [ - 'key' => [ - 'k1' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', - 'k2' => 'hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0', - ], - 'driver' => [ - 'k1' => 'OpenSSL', - 'k2' => 'OpenSSL', +public array $hmacEncryptionKeys = [ + 'k1' => [ + 'key' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', ], - 'digest' => [ - 'k1' => 'SHA512', - 'k2' => 'SHA512', + 'k2' => [ + 'key' => 'hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0', + 'digest' => 'SHA256', ], - 'currentKey' => 'k2', ]; + +public string $hmacEncryptionCurrentKey = 'k2'; +public string $hmacEncryptionDefaultDriver = 'OpenSSL'; +public string $hmacEncryptionDefaultDigest = 'SHA512'; + ``` ```console @@ -211,10 +212,8 @@ You can (and should) set these values using environment variable and/or the **.e the values as JSON strings: ```text -authtoken.hmacEncryption.key = '{"k1":"hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7","k2":"hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0"}' -authtoken.hmacEncryption.driver = '{"k1":"OpenSSL","k2":"OpenSSL"}' -authtoken.hmacEncryption.digest = '{"k1":"SHA512","k2":"SHA512"}' -authtoken.hmacEncryption.currentKey = k2 +authtoken.hmacEncryptionKeys = '{"k1":{"key":"hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7"},"k2":{"key":"hex2bin:451df599363b19be1434605fff8556a0bbfc50bede1bb33793dcde4d97fce4b0"}}' +authtoken.hmacEncryptionCurrentKey = k2 ``` Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6a37a2ce6..af444e0a1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -94,9 +94,7 @@ - - - + diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index fa5c2f9ef..744d061d6 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -40,7 +40,7 @@ public function __construct() { $this->authConfig = config('AuthToken'); - $this->getEncrypter($this->authConfig->hmacEncryption['currentKey']); + $this->getEncrypter($this->authConfig->hmacEncryptionCurrentKey); } /** @@ -77,7 +77,7 @@ public function decrypt(string $encString): string */ public function encrypt(string $rawString): string { - $currentKey = $this->authConfig->hmacEncryption['currentKey']; + $currentKey = $this->authConfig->hmacEncryptionCurrentKey; $encryptedString = '$b6$' . $currentKey . '$' . base64_encode($this->encrypter[$currentKey]->encrypt($rawString)); @@ -101,7 +101,7 @@ public function isEncrypted(string $string): bool */ public function isEncryptedWithCurrentKey(string $string): bool { - $currentKey = $this->authConfig->hmacEncryption['currentKey']; + $currentKey = $this->authConfig->hmacEncryptionCurrentKey; return preg_match('/^\$b6\$' . $currentKey . '\$/', $string) === 1; } @@ -126,15 +126,15 @@ public function generateSecretKey(): string private function getEncrypter(string $encrypterKey): EncrypterInterface { if (! isset($this->encrypter[$encrypterKey])) { - if (! isset($this->authConfig->hmacEncryption['key'][$encrypterKey])) { + if (! isset($this->authConfig->hmacEncryptionKeys[$encrypterKey]['key'])) { throw new RuntimeException('Encryption key does not exist.'); } $config = new Encryption(); - $config->key = $this->authConfig->hmacEncryption['key'][$encrypterKey]; - $config->driver = $this->authConfig->hmacEncryption['driver'][$encrypterKey]; - $config->digest = $this->authConfig->hmacEncryption['digest'][$encrypterKey]; + $config->key = $this->authConfig->hmacEncryptionKeys[$encrypterKey]['key']; + $config->driver = $this->authConfig->hmacEncryptionKeys[$encrypterKey]['driver'] ?? $this->authConfig->hmacEncryptionDefaultDriver; + $config->digest = $this->authConfig->hmacEncryptionKeys[$encrypterKey]['digest'] ?? $this->authConfig->hmacEncryptionDefaultDigest; $this->encrypter[$encrypterKey] = Services::encrypter($config); } diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index c948025a5..2d16713de 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -76,36 +76,55 @@ class AuthToken extends BaseAuthToken * -------------------------------------------------------------------- * This sets the key to be used when encrypting a user's HMAC Secret Key. * - * 'key' is an array of keys which will facilitate key rotation. Valid + * 'keys' is an array of keys which will facilitate key rotation. Valid * keyTitles must include only [a-zA-Z0-9_] and should be kept to a * max of 8 characters. * - * 'driver' is used when encrypting HMAC Secret Key for storage. - * Available drivers: - * - OpenSSL - * - Sodium - * - * This is an array of drivers values. The keys MUST match and correlate - * to the 'key' array keys. - * - * 'digest' is used when encrypting HMAC Secret Key for storage. - * e.g. 'SHA512' or 'SHA256'. Default value is 'SHA512'. - * - * This is an array of digest values. The keys MUST match and correlate - * to the 'key' array keys. - * - * The valid/current key is identified using 'currentKey' + * Each keyTitle is an associative array containing the required 'key' + * value, and the optional 'driver' and 'digest' values. If the + * 'driver' and 'digest' values are not specified, the default 'driver' + * and 'digest' values will be used. * * Old keys will are used to decrypt existing Secret Keys. It is encouraged * to run 'php spark shield:hmac reencrypt' to update existing Secret * Key encryptions. * * @see https://codeigniter.com/user_guide/libraries/encryption.html + * + * @var array|string */ - public array $hmacEncryption = [ - 'key' => ['k1' => ''], - 'driver' => ['k1' => 'OpenSSL'], - 'digest' => ['k1' => 'SHA512'], - 'currentKey' => 'k1', + public $hmacEncryptionKeys = [ + 'k1' => [ + 'key' => '', + ], ]; + + /** + * -------------------------------------------------------------------- + * HMAC Current Encryption Key Selector + * -------------------------------------------------------------------- + * This specifies which of the encryption keys should be used. + */ + public string $hmacEncryptionCurrentKey = 'k1'; + + /** + * -------------------------------------------------------------------- + * HMAC Encryption Key Driver + * -------------------------------------------------------------------- + * This specifies which of the encryption drivers should be used. + * + * Available drivers: + * - OpenSSL + * - Sodium + */ + public string $hmacEncryptionDefaultDriver = 'OpenSSL'; + + /** + * -------------------------------------------------------------------- + * HMAC Encryption Key Driver + * -------------------------------------------------------------------- + * THis specifies the type of encryption to be used. + * e.g. 'SHA512' or 'SHA256'. + */ + public string $hmacEncryptionDefaultDigest = 'SHA512'; } diff --git a/src/Config/BaseAuthToken.php b/src/Config/BaseAuthToken.php index 73ac438f4..4a732eb70 100644 --- a/src/Config/BaseAuthToken.php +++ b/src/Config/BaseAuthToken.php @@ -8,7 +8,12 @@ class BaseAuthToken extends BaseConfig { - public array $hmacEncryption; + /** + * List of HMAC Encryption Keys + * + * @var array|string + */ + public $hmacEncryptionKeys; /** * AuthToken Config Constructor @@ -17,18 +22,10 @@ public function __construct() { parent::__construct(); - $overwriteHmacEncryptionFields = [ - 'key', - 'driver', - 'digest', - ]; - - foreach ($overwriteHmacEncryptionFields as $fieldName) { - if (is_string($this->hmacEncryption[$fieldName])) { - $array = json_decode($this->hmacEncryption[$fieldName], true); - if (is_array($array)) { - $this->hmacEncryption[$fieldName] = $array; - } + if (is_string($this->hmacEncryptionKeys)) { + $array = json_decode($this->hmacEncryptionKeys, true); + if (is_array($array)) { + $this->hmacEncryptionKeys = $array; } } } @@ -43,9 +40,7 @@ public function __construct() protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void { switch ($name) { - case 'hmacEncryption.key': - case 'hmacEncryption.driver': - case 'hmacEncryption.digest': + case 'hmacEncryptionKeys': // if attempting to set property from ENV, first set to empty string if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { $property = ''; diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index b8f899a95..7b7c87ade 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -93,7 +93,7 @@ public function testReEncrypt(): void /** @var AuthToken $config */ $config = config('AuthToken'); - $config->hmacEncryption['currentKey'] = 'k2'; + $config->hmacEncryptionCurrentKey = 'k2'; // new key generated with updated encryption $token2 = $user->generateHmacToken('bar'); From ee6785cb1c03569743829198d5da9cb4dbf32099 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 21 Nov 2023 11:02:32 -0600 Subject: [PATCH 112/128] Clean up of switch statement. --- src/Config/BaseAuthToken.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Config/BaseAuthToken.php b/src/Config/BaseAuthToken.php index 4a732eb70..4bbe92fe3 100644 --- a/src/Config/BaseAuthToken.php +++ b/src/Config/BaseAuthToken.php @@ -39,12 +39,11 @@ public function __construct() */ protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void { - switch ($name) { - case 'hmacEncryptionKeys': - // if attempting to set property from ENV, first set to empty string - if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { - $property = ''; - } + if ($name === 'hmacEncryptionKeys') { + // if attempting to set property from ENV, first set to empty string + if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { + $property = ''; + } } parent::initEnvValue($property, $name, $prefix, $shortPrefix); From a11bc0dabd0f7ee7796aeb0c14b5bab056ad0ee1 Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Tue, 21 Nov 2023 15:41:15 -0600 Subject: [PATCH 113/128] Update src/Config/AuthToken.php Co-authored-by: kenjis --- src/Config/AuthToken.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 2d16713de..9e5a93028 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -91,7 +91,12 @@ class AuthToken extends BaseAuthToken * * @see https://codeigniter.com/user_guide/libraries/encryption.html * - * @var array|string + * @var array>|string Temporarily becomes a + * string when setting value + * as JSON from environment + * variable. + * + * [key_name => ['key' => key_value]] */ public $hmacEncryptionKeys = [ 'k1' => [ From eb73c3180e33fc969d09bc4115f4cd3a8312d483 Mon Sep 17 00:00:00 2001 From: Tim Swagger Date: Tue, 21 Nov 2023 16:26:16 -0600 Subject: [PATCH 114/128] Update src/Config/AuthToken.php Co-authored-by: kenjis --- src/Config/AuthToken.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index 9e5a93028..a94488512 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -91,12 +91,13 @@ class AuthToken extends BaseAuthToken * * @see https://codeigniter.com/user_guide/libraries/encryption.html * - * @var array>|string Temporarily becomes a - * string when setting value - * as JSON from environment - * variable. + * @var array|string + * + * NOTE: The value becomes temporarily a string when setting value as JSON + * from environment variable. * * [key_name => ['key' => key_value]] + * or [key_name => ['key' => key_value, 'driver' => driver, 'digest' => digest]] */ public $hmacEncryptionKeys = [ 'k1' => [ From dcd9aa92119825600b5f417455eb0008018b3017 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 21 Nov 2023 17:08:07 -0600 Subject: [PATCH 115/128] Cleanup of AuthToken Var statements --- docs/references/authentication/hmac.md | 4 ++-- src/Config/BaseAuthToken.php | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 9e4f75ae4..52c274f12 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -170,7 +170,7 @@ You will also be able to adjust the default Driver `$hmacEncryptionDefaultDriver overridden for an individual key by including them in the keys array. ```php -public array $hmacEncryptionKeys = [ +public $hmacEncryptionKeys = [ 'k1' => [ 'key' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', ], @@ -188,7 +188,7 @@ encryption key. You will need to leave the old key in the array as it will be u during re-encryption. ```php -public array $hmacEncryptionKeys = [ +public $hmacEncryptionKeys = [ 'k1' => [ 'key' => 'hex2bin:923dfab5ddca0c7784c2c388a848a704f5e048736c1a852c862959da62ade8c7', ], diff --git a/src/Config/BaseAuthToken.php b/src/Config/BaseAuthToken.php index 4bbe92fe3..edbc58655 100644 --- a/src/Config/BaseAuthToken.php +++ b/src/Config/BaseAuthToken.php @@ -11,7 +11,7 @@ class BaseAuthToken extends BaseConfig /** * List of HMAC Encryption Keys * - * @var array|string + * @var array|string */ public $hmacEncryptionKeys; @@ -39,11 +39,9 @@ public function __construct() */ protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void { - if ($name === 'hmacEncryptionKeys') { - // if attempting to set property from ENV, first set to empty string - if ($this->getEnvValue($name, $prefix, $shortPrefix) !== null) { - $property = ''; - } + // if attempting to set property from ENV, first set to empty string + if ($name === 'hmacEncryptionKeys' && $this->getEnvValue($name, $prefix, $shortPrefix) !== null) { + $property = ''; } parent::initEnvValue($property, $name, $prefix, $shortPrefix); From c34aebc377cd9788c65f81911c5c28eac1f57284 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 21 Nov 2023 17:11:27 -0600 Subject: [PATCH 116/128] Adjustment to test output --- tests/Commands/HmacTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 7b7c87ade..809764163 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -36,6 +36,7 @@ public function testEncrypt(): void $this->assertSame($rawSecretKey, $tokenCheck->secret2); + $this->setMockIo([]); $this->assertNotFalse(command('shield:hmac encrypt')); $tokenCheck = $idModel->find($token->id); @@ -63,6 +64,7 @@ public function testDecrypt(): void $rawSecretKey = $token->rawSecretKey; + $this->setMockIo([]); $this->assertNotFalse(command('shield:hmac decrypt')); $token->secret2 = $rawSecretKey; From 363183dbf9298629a773464f01c23fd241f9a556 Mon Sep 17 00:00:00 2001 From: tswagger Date: Tue, 21 Nov 2023 19:04:44 -0600 Subject: [PATCH 117/128] cs-fix updates --- src/Authentication/HMAC/HmacEncrypter.php | 9 +++++++++ src/Commands/Hmac.php | 9 +++++++++ src/Config/BaseAuthToken.php | 9 +++++++++ tests/Commands/HmacTest.php | 9 +++++++++ 4 files changed, 36 insertions(+) diff --git a/src/Authentication/HMAC/HmacEncrypter.php b/src/Authentication/HMAC/HmacEncrypter.php index 744d061d6..db0db64c6 100644 --- a/src/Authentication/HMAC/HmacEncrypter.php +++ b/src/Authentication/HMAC/HmacEncrypter.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Authentication\HMAC; use CodeIgniter\Encryption\EncrypterInterface; diff --git a/src/Commands/Hmac.php b/src/Commands/Hmac.php index e15c57f2b..2071790f5 100644 --- a/src/Commands/Hmac.php +++ b/src/Commands/Hmac.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Commands; use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter; diff --git a/src/Config/BaseAuthToken.php b/src/Config/BaseAuthToken.php index edbc58655..be8dcdfe9 100644 --- a/src/Config/BaseAuthToken.php +++ b/src/Config/BaseAuthToken.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace CodeIgniter\Shield\Config; use CodeIgniter\Config\BaseConfig; diff --git a/tests/Commands/HmacTest.php b/tests/Commands/HmacTest.php index 809764163..9027599f3 100644 --- a/tests/Commands/HmacTest.php +++ b/tests/Commands/HmacTest.php @@ -2,6 +2,15 @@ declare(strict_types=1); +/** + * This file is part of CodeIgniter Shield. + * + * (c) CodeIgniter Foundation + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + namespace Tests\Commands; use CodeIgniter\Shield\Authentication\HMAC\HmacEncrypter; From 0405d31637f28ca7630a3c87966992a2c5877e0d Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 19 Oct 2023 12:17:21 +0900 Subject: [PATCH 118/128] fix: Access Token Authenticator raw tokens are logged --- .../Authenticators/AccessTokens.php | 11 +++---- .../AccessTokenAuthenticatorTest.php | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Authentication/Authenticators/AccessTokens.php b/src/Authentication/Authenticators/AccessTokens.php index 86824ed61..46ff20188 100644 --- a/src/Authentication/Authenticators/AccessTokens.php +++ b/src/Authentication/Authenticators/AccessTokens.php @@ -77,14 +77,15 @@ public function attempt(array $credentials): Result return $result; } - $user = $result->extraInfo(); + $user = $result->extraInfo(); + $token = $user->getAccessToken($this->getBearerToken()); if ($user->isBanned()) { if ($config->recordLoginAttempt >= Auth::RECORD_LOGIN_ATTEMPT_FAILURE) { // Record a banned login attempt. $this->loginModel->recordLoginAttempt( self::ID_TYPE_ACCESS_TOKEN, - $credentials['token'] ?? '', + $token->name ?? '', false, $ipAddress, $userAgent, @@ -100,9 +101,7 @@ public function attempt(array $credentials): Result ]); } - $user = $user->setAccessToken( - $user->getAccessToken($this->getBearerToken()) - ); + $user = $user->setAccessToken($token); $this->login($user); @@ -110,7 +109,7 @@ public function attempt(array $credentials): Result // Record a successful login attempt. $this->loginModel->recordLoginAttempt( self::ID_TYPE_ACCESS_TOKEN, - $credentials['token'] ?? '', + $token->name ?? '', true, $ipAddress, $userAgent, diff --git a/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php b/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php index 7c48ac1c5..937f34778 100644 --- a/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php @@ -17,6 +17,7 @@ use CodeIgniter\Shield\Authentication\Authentication; use CodeIgniter\Shield\Authentication\Authenticators\AccessTokens; use CodeIgniter\Shield\Config\Auth; +use CodeIgniter\Shield\Config\AuthToken; use CodeIgniter\Shield\Entities\AccessToken; use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Models\UserIdentityModel; @@ -222,6 +223,38 @@ public function testAttemptSuccess(): void ]); } + public function testAttemptSuccessLog(): void + { + // Change $recordLoginAttempt in Config. + /** @var AuthToken $config */ + $config = config('AuthToken'); + $config->recordLoginAttempt = Auth::RECORD_LOGIN_ATTEMPT_ALL; + + /** @var User $user */ + $user = fake(UserModel::class); + $token = $user->generateAccessToken('foo'); + $this->setRequestHeader($token->raw_token); + + $result = $this->auth->attempt([ + 'token' => $token->raw_token, + ]); + + $this->assertInstanceOf(Result::class, $result); + $this->assertTrue($result->isOK()); + + $foundUser = $result->extraInfo(); + $this->assertInstanceOf(User::class, $foundUser); + $this->assertSame($user->id, $foundUser->id); + $this->assertInstanceOf(AccessToken::class, $foundUser->currentAccessToken()); + $this->assertSame($token->token, $foundUser->currentAccessToken()->token); + + $this->seeInDatabase($this->tables['token_logins'], [ + 'id_type' => AccessTokens::ID_TYPE_ACCESS_TOKEN, + 'identifier' => 'foo', + 'success' => 1, + ]); + } + protected function setRequestHeader(string $token): void { $request = service('request'); From b0b10b61103d43f2ef2b70e917f587f323be8bc3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 19 Oct 2023 12:20:36 +0900 Subject: [PATCH 119/128] fix: HMAC Token Authenticator raw tokens are logged --- src/Authentication/Authenticators/HmacSha256.php | 11 +++++------ .../Authenticators/HmacAuthenticatorTest.php | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Authentication/Authenticators/HmacSha256.php b/src/Authentication/Authenticators/HmacSha256.php index 940886f2b..2f37ba669 100644 --- a/src/Authentication/Authenticators/HmacSha256.php +++ b/src/Authentication/Authenticators/HmacSha256.php @@ -78,14 +78,15 @@ public function attempt(array $credentials): Result return $result; } - $user = $result->extraInfo(); + $user = $result->extraInfo(); + $token = $user->getHmacToken($this->getHmacKeyFromToken()); if ($user->isBanned()) { if ($config->recordLoginAttempt >= Auth::RECORD_LOGIN_ATTEMPT_FAILURE) { // Record a banned login attempt. $this->loginModel->recordLoginAttempt( self::ID_TYPE_HMAC_TOKEN, - $credentials['token'] ?? '', + $token->name ?? '', false, $ipAddress, $userAgent, @@ -101,9 +102,7 @@ public function attempt(array $credentials): Result ]); } - $user = $user->setHmacToken( - $user->getHmacToken($this->getHmacKeyFromToken()) - ); + $user = $user->setHmacToken($token); $this->login($user); @@ -111,7 +110,7 @@ public function attempt(array $credentials): Result // Record a successful login attempt. $this->loginModel->recordLoginAttempt( self::ID_TYPE_HMAC_TOKEN, - $credentials['token'] ?? '', + $token->name ?? '', true, $ipAddress, $userAgent, diff --git a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php index ea553ef2c..da0ac2b94 100644 --- a/tests/Authentication/Authenticators/HmacAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/HmacAuthenticatorTest.php @@ -273,7 +273,7 @@ public function testAttemptSuccess(): void // A login attempt should have been recorded $this->seeInDatabase($this->tables['token_logins'], [ 'id_type' => HmacSha256::ID_TYPE_HMAC_TOKEN, - 'identifier' => $rawToken, + 'identifier' => 'foo', 'success' => 1, ]); @@ -310,7 +310,7 @@ public function testAttemptBanned(): void // A login attempt should have been recorded $this->seeInDatabase($this->tables['token_logins'], [ 'id_type' => HmacSha256::ID_TYPE_HMAC_TOKEN, - 'identifier' => $rawToken, + 'identifier' => 'foo', 'success' => 0, ]); } From 3e48895f91f99f5f08da54cfed87df1c94bd3e33 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 19 Oct 2023 12:21:13 +0900 Subject: [PATCH 120/128] fix: JWT Authenticator raw tokens are logged --- src/Authentication/Authenticators/JWT.php | 4 ++-- tests/Authentication/Authenticators/JWTAuthenticatorTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Authentication/Authenticators/JWT.php b/src/Authentication/Authenticators/JWT.php index d962f86f2..84efc2fb5 100644 --- a/src/Authentication/Authenticators/JWT.php +++ b/src/Authentication/Authenticators/JWT.php @@ -103,7 +103,7 @@ public function attempt(array $credentials): Result // Record a banned login attempt. $this->tokenLoginModel->recordLoginAttempt( self::ID_TYPE_JWT, - $credentials['token'] ?? '', + 'sha256:' . hash('sha256', $credentials['token'] ?? ''), false, $ipAddress, $userAgent, @@ -125,7 +125,7 @@ public function attempt(array $credentials): Result // Record a successful login attempt. $this->tokenLoginModel->recordLoginAttempt( self::ID_TYPE_JWT, - $credentials['token'] ?? '', + 'sha256:' . hash('sha256', $credentials['token']), true, $ipAddress, $userAgent, diff --git a/tests/Authentication/Authenticators/JWTAuthenticatorTest.php b/tests/Authentication/Authenticators/JWTAuthenticatorTest.php index 9d4e5d6b5..d4ee37f90 100644 --- a/tests/Authentication/Authenticators/JWTAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/JWTAuthenticatorTest.php @@ -226,7 +226,7 @@ public function testAttemptBannedUser(): void // The login attempt should have been recorded $this->seeInDatabase('auth_token_logins', [ 'id_type' => JWT::ID_TYPE_JWT, - 'identifier' => $token, + 'identifier' => 'sha256:' . hash('sha256', $token), 'success' => 0, 'user_id' => $this->user->id, ]); @@ -256,7 +256,7 @@ public function testAttemptSuccess(): void // A login attempt should have been recorded $this->seeInDatabase('auth_token_logins', [ 'id_type' => JWT::ID_TYPE_JWT, - 'identifier' => $token, + 'identifier' => 'sha256:' . hash('sha256', $token), 'success' => 1, ]); } From 2424f13b6db848a479c283cfd73359a1a4f836df Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 19 Oct 2023 13:21:25 +0900 Subject: [PATCH 121/128] test: remove unneeded assertions The return type is typed. --- phpstan-baseline.php | 5 ----- .../Authenticators/AccessTokenAuthenticatorTest.php | 4 ---- 2 files changed, 9 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index f66ecb7d9..a261d48ba 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -361,11 +361,6 @@ 'count' => 1, 'path' => __DIR__ . '/src/Models/UserModel.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with \'CodeIgniter\\\\\\\\Shield\\\\\\\\Result\' and CodeIgniter\\\\Shield\\\\Result will always evaluate to true\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with \'CodeIgniter\\\\\\\\Shield\\\\\\\\Result\' and CodeIgniter\\\\Shield\\\\Result will always evaluate to true\\.$#', 'count' => 3, diff --git a/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php b/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php index 937f34778..43a6d7173 100644 --- a/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/AccessTokenAuthenticatorTest.php @@ -22,7 +22,6 @@ use CodeIgniter\Shield\Entities\User; use CodeIgniter\Shield\Models\UserIdentityModel; use CodeIgniter\Shield\Models\UserModel; -use CodeIgniter\Shield\Result; use CodeIgniter\Test\Mock\MockEvents; use Config\Services; use Tests\Support\DatabaseTestCase; @@ -183,7 +182,6 @@ public function testAttemptCannotFindUser(): void 'token' => 'abc123', ]); - $this->assertInstanceOf(Result::class, $result); $this->assertFalse($result->isOK()); $this->assertSame(lang('Auth.badToken'), $result->reason()); @@ -206,7 +204,6 @@ public function testAttemptSuccess(): void 'token' => $token->raw_token, ]); - $this->assertInstanceOf(Result::class, $result); $this->assertTrue($result->isOK()); $foundUser = $result->extraInfo(); @@ -239,7 +236,6 @@ public function testAttemptSuccessLog(): void 'token' => $token->raw_token, ]); - $this->assertInstanceOf(Result::class, $result); $this->assertTrue($result->isOK()); $foundUser = $result->extraInfo(); From 02f5020838deb842e8e35e090efe24a09840da91 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 21 Oct 2023 06:49:03 +0900 Subject: [PATCH 122/128] docs: add description for logging --- docs/addons/jwt.md | 28 +++++++++++- docs/references/authentication/hmac.md | 55 ++++++++++++++++++------ docs/references/authentication/tokens.md | 27 ++++++++++++ 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/docs/addons/jwt.md b/docs/addons/jwt.md index ae48a35dd..f9ff4b83a 100644 --- a/docs/addons/jwt.md +++ b/docs/addons/jwt.md @@ -34,9 +34,9 @@ To use JWT Authentication, you need additional setup and configuration. ```php getHmacTokenById($id); $tokens = $user->hmacTokens(); ``` -## HMAC Keys Lifetime - -HMAC Keys/Tokens will expire after a specified amount of time has passed since they have been used. -This uses the same configuration value as AccessTokens. - -By default, this is set to 1 year. You can change this value by setting the `$unusedTokenLifetime` -value in the **app/Config/AuthToken.php** config file. This is in seconds so that you can use the -[time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants) -that CodeIgniter provides. - -```php -public $unusedTokenLifetime = YEAR; -``` - ## HMAC Keys Scopes Each token (set of keys) can be given one or more scopes they can be used within. These can be thought of as @@ -219,3 +205,44 @@ authtoken.hmacEncryptionCurrentKey = k2 Depending on the set length of the Secret Key and the type of encryption used, it is possible for the encrypted value to exceed the database column character limit of 255 characters. If this happens, creation of a new HMAC identity will throw a `RuntimeException`. + +## Configuration + +### HMAC Keys Lifetime + +HMAC Keys/Tokens will expire after a specified amount of time has passed since they have been used. +This uses the same configuration value as AccessTokens. + +By default, this is set to 1 year. You can change this value by setting the `$unusedTokenLifetime` +value in the **app/Config/AuthToken.php** config file. This is in seconds so that you can use the +[time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants) +that CodeIgniter provides. + +```php +public $unusedTokenLifetime = YEAR; +``` + +### Login Attempt Logging + +By default, only failed login attempts are recorded in the `auth_token_logins` table. +This can be modified in the **app/Config/AuthToken.php** config file. + +```php +public int $recordLoginAttempt = Auth::RECORD_LOGIN_ATTEMPT_FAILURE; +``` + +If you don't want any logs, set it to `Auth::RECORD_LOGIN_ATTEMPT_NONE`. + +If you want to log all login attempts, set it to `Auth::RECORD_LOGIN_ATTEMPT_ALL`. +It means you log all requests. + +## Logging + +Login attempts are recorded in the `auth_token_logins` table, according to the +configuration above. + +When a failed login attempt is logged, the raw token value sent is saved in +the `identifier` column. + +When a successful login attempt is logged, the token name is saved in the +`identifier` column. diff --git a/docs/references/authentication/tokens.md b/docs/references/authentication/tokens.md index b97cb6769..c7da99984 100644 --- a/docs/references/authentication/tokens.md +++ b/docs/references/authentication/tokens.md @@ -125,3 +125,30 @@ if ($user->tokenCant('forums.manage')) { // do something.... } ``` + +## Configuration + +### Login Attempt Logging + +By default, only failed login attempts are recorded in the `auth_token_logins` table. +This can be modified in the **app/Config/AuthToken.php** config file. + +```php +public int $recordLoginAttempt = Auth::RECORD_LOGIN_ATTEMPT_FAILURE; +``` + +If you don't want any logs, set it to `Auth::RECORD_LOGIN_ATTEMPT_NONE`. + +If you want to log all login attempts, set it to `Auth::RECORD_LOGIN_ATTEMPT_ALL`. +It means you log all requests. + +## Logging + +Login attempts are recorded in the `auth_token_logins` table, according to the +configuration above. + +When a failed login attempt is logged, the raw token value sent is saved in +the `identifier` column. + +When a successful login attempt is logged, the token name is saved in the +`identifier` column. From 26558aaef88b82f7016a3bfff1a5e2ad2f0ba186 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 08:58:52 +0900 Subject: [PATCH 123/128] docs: move "Access Token Lifetime" into "Configuration" --- docs/references/authentication/tokens.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/references/authentication/tokens.md b/docs/references/authentication/tokens.md index c7da99984..0dfbaf52c 100644 --- a/docs/references/authentication/tokens.md +++ b/docs/references/authentication/tokens.md @@ -83,18 +83,6 @@ $token = $user->getAccessTokenById($id); $tokens = $user->accessTokens(); ``` -## Access Token Lifetime - -Tokens will expire after a specified amount of time has passed since they have been used. -By default, this is set to 1 year. You can change this value by setting the `$unusedTokenLifetime` -value in the **app/Config/AuthToken.php** config file. This is in seconds so that you can use the -[time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants) -that CodeIgniter provides. - -```php -public $unusedTokenLifetime = YEAR; -``` - ## Access Token Scopes Each token can be given one or more scopes they can be used within. These can be thought of as @@ -128,6 +116,18 @@ if ($user->tokenCant('forums.manage')) { ## Configuration +### Access Token Lifetime + +Tokens will expire after a specified amount of time has passed since they have been used. +By default, this is set to 1 year. You can change this value by setting the `$unusedTokenLifetime` +value in the **app/Config/AuthToken.php** config file. This is in seconds so that you can use the +[time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants) +that CodeIgniter provides. + +```php +public $unusedTokenLifetime = YEAR; +``` + ### Login Attempt Logging By default, only failed login attempts are recorded in the `auth_token_logins` table. From eddc976bb31332c372f27407b33af46432f2ae91 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 09:16:21 +0900 Subject: [PATCH 124/128] docs: add doc comment --- src/Config/AuthToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/AuthToken.php b/src/Config/AuthToken.php index a94488512..7c52a9684 100644 --- a/src/Config/AuthToken.php +++ b/src/Config/AuthToken.php @@ -46,7 +46,7 @@ class AuthToken extends BaseAuthToken /** * -------------------------------------------------------------------- - * Unused Token Lifetime + * Unused Token Lifetime for Token Auth and HMAC Auth * -------------------------------------------------------------------- * Determines the amount of time, in seconds, that an unused token can * be used. From 651902dab7e78095278d89302c9124c46a474c80 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 09:17:19 +0900 Subject: [PATCH 125/128] docs: add note for app/Config/AuthToken.php --- docs/references/authentication/hmac.md | 12 +++++++++--- docs/references/authentication/tokens.md | 16 +++++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/references/authentication/hmac.md b/docs/references/authentication/hmac.md index 8bd107064..fed1f0bb7 100644 --- a/docs/references/authentication/hmac.md +++ b/docs/references/authentication/hmac.md @@ -208,13 +208,19 @@ throw a `RuntimeException`. ## Configuration +Configure **app/Config/AuthToken.php** for your needs. + +!!! note + + Shield does not expect you use the Access Token Authenticator and HMAC Authenticator + at the same time. Therefore, some Config items are common. + ### HMAC Keys Lifetime HMAC Keys/Tokens will expire after a specified amount of time has passed since they have been used. -This uses the same configuration value as AccessTokens. By default, this is set to 1 year. You can change this value by setting the `$unusedTokenLifetime` -value in the **app/Config/AuthToken.php** config file. This is in seconds so that you can use the +value. This is in seconds so that you can use the [time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants) that CodeIgniter provides. @@ -225,7 +231,7 @@ public $unusedTokenLifetime = YEAR; ### Login Attempt Logging By default, only failed login attempts are recorded in the `auth_token_logins` table. -This can be modified in the **app/Config/AuthToken.php** config file. +This can be modified by changing the `$recordLoginAttempt` value. ```php public int $recordLoginAttempt = Auth::RECORD_LOGIN_ATTEMPT_FAILURE; diff --git a/docs/references/authentication/tokens.md b/docs/references/authentication/tokens.md index 0dfbaf52c..11b03afcd 100644 --- a/docs/references/authentication/tokens.md +++ b/docs/references/authentication/tokens.md @@ -116,11 +116,20 @@ if ($user->tokenCant('forums.manage')) { ## Configuration +Configure **app/Config/AuthToken.php** for your needs. + +!!! note + + Shield does not expect you use the Access Token Authenticator and HMAC Authenticator + at the same time. Therefore, some Config items are common. + ### Access Token Lifetime Tokens will expire after a specified amount of time has passed since they have been used. -By default, this is set to 1 year. You can change this value by setting the `$unusedTokenLifetime` -value in the **app/Config/AuthToken.php** config file. This is in seconds so that you can use the + +By default, this is set to 1 year. +You can change this value by setting the `$unusedTokenLifetime` value. This is +in seconds so that you can use the [time constants](https://codeigniter.com/user_guide/general/common_functions.html#time-constants) that CodeIgniter provides. @@ -131,7 +140,8 @@ public $unusedTokenLifetime = YEAR; ### Login Attempt Logging By default, only failed login attempts are recorded in the `auth_token_logins` table. -This can be modified in the **app/Config/AuthToken.php** config file. + +This can be modified by changing the `$recordLoginAttempt` value. ```php public int $recordLoginAttempt = Auth::RECORD_LOGIN_ATTEMPT_FAILURE; From 393ec3b9f0288891cf392ab776ab424b74ceda9a Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 09:25:01 +0900 Subject: [PATCH 126/128] docs: add links to reference pages --- docs/getting_started/configuration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/getting_started/configuration.md b/docs/getting_started/configuration.md index 7d621fcb0..a73f5a636 100644 --- a/docs/getting_started/configuration.md +++ b/docs/getting_started/configuration.md @@ -8,9 +8,9 @@ If you have completed the setup according to this documentation, you will have the following configuration files: - **app/Config/Auth.php** -- **app/Config/AuthGroups.php** - For Authorization -- **app/Config/AuthToken.php** - For AccessTokens and HmacSha256 Authentication -- **app/Config/AuthJWT.php** - For JWT Authentication +- **app/Config/AuthGroups.php** - For [Authorization](../references/authorization.md) +- **app/Config/AuthToken.php** - For [AccessTokens](../references/authentication/tokens.md#configuration) and [HmacSha256](../references/authentication/hmac.md#configuration) Authentication +- **app/Config/AuthJWT.php** - For [JWT Authentication](../addons/jwt.md#configuration) Note that you do not need to have configuration files for features you do not use. From 725baaa6486c6d6ee8e923f7dc9287eb0ba006a8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 09:25:18 +0900 Subject: [PATCH 127/128] docs: remove duplicated description --- docs/getting_started/configuration.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docs/getting_started/configuration.md b/docs/getting_started/configuration.md index a73f5a636..246cf99b9 100644 --- a/docs/getting_started/configuration.md +++ b/docs/getting_started/configuration.md @@ -13,15 +13,3 @@ the following configuration files: - **app/Config/AuthJWT.php** - For [JWT Authentication](../addons/jwt.md#configuration) Note that you do not need to have configuration files for features you do not use. - -This section describes the major Config items that are not described elsewhere. - -## AccessTokens Authenticator - -### Access Token Lifetime - -By default, Access Tokens can be used for 1 year since the last use. This can be easily modified in the **app/Config/AuthToken.php** config file. - -```php -public int $unusedTokenLifetime = YEAR; -``` From 0fdd64f87629f499fc95be32a927e2d2e36a8370 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 23 Nov 2023 08:37:44 +0900 Subject: [PATCH 128/128] Prep for release-1.0.0-beta.8 release --- src/Auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth.php b/src/Auth.php index 6a84c5cd7..f64e7cbaa 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -41,7 +41,7 @@ class Auth /** * The current version of CodeIgniter Shield */ - public const SHIELD_VERSION = '1.0.0-beta.7'; + public const SHIELD_VERSION = '1.0.0-beta.8'; protected AuthConfig $config; protected ?Authentication $authenticate = null;