diff --git a/README.md b/README.md index 02d3d58c3..3d68a94bc 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,9 @@ Usage of Shield requires the following: ### Installation Installation is done through Composer. - - > composer require codeigniter4/shield +```console +composer require codeigniter4/shield +``` See the [docs](docs/index.md) for more specific instructions on installation and usage recommendations. diff --git a/docs/concepts.md b/docs/concepts.md index 7069db417..3eda4ed27 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -25,7 +25,7 @@ on the standard Config class if nothing is found in the database. ## User Providers You can use your own models to handle user persistence. Shield calls this the "User Provider" class. A default model -is provided for you at `CodeIgniter\Shield\Models\UserModel`. You can change this in the `Config\Auth->userProvider` setting. +is provided for you at `CodeIgniter\Shield\Models\UserModel`. You can change this in the `Config\Auth::$userProvider` setting. The only requirement is that your new class MUST extend the provided `UserModel`. ```php @@ -57,13 +57,13 @@ systems that are appropriate for your application. The following Validators are like ensuring it contained a symbol, a number, etc. According to the current [NIST recommendations](https://pages.nist.gov/800-63-3/sp800-63b.html) this only enforces a minimum length on the password. You can define the minimum length in - `Config\Auth->public $minimumPasswordLength;` This is enabled by default. The default minimum + `Config\Auth::$minimumPasswordLength` This is enabled by default. The default minimum value is `8`. - **NothingPersonalValidator** will compare the password against any fields that have been specified - in `Config\Auth->personalFields`, like first or last names, etc. Additionally, it compares it + in `Config\Auth::$personalFields`, like first or last names, etc. Additionally, it compares it against a few simple variations of the username. If the given password too closely matches any of the personal information, it will be rejected. The similarity value is defined in - `Config\Auth->maxSimilarity`. The default value is 50, but see the docblock in the config + `Config\Auth::$maxSimilarity`. The default value is 50, but see the docblock in the config file for more details. This is enabled by default. - **DictionaryValidator** will compare the password against a provided file with about 600,000 frequently used passwords that have been seen in various data dumps over the years. If the @@ -76,7 +76,7 @@ systems that are appropriate for your application. The following Validators are find acceptable. You should use either this validator or the `DictionaryValidator`, not both. This is disabled by default. -You can choose which validators are used in `Config\Auth->passwordValidators`: +You can choose which validators are used in `Config\Auth::$passwordValidators`: ```php public $passwordValidators = [ diff --git a/docs/install.md b/docs/install.md index f9e3574b7..d18d89f4b 100644 --- a/docs/install.md +++ b/docs/install.md @@ -25,8 +25,8 @@ These instructions assume that you have already [installed the CodeIgniter 4 app Installation is done through [Composer](https://getcomposer.org). The example assumes you have it installed globally. If you have it installed as a phar, or otherwise you will need to adjust the way you call composer itself. -``` -> composer require codeigniter4/shield +```console +composer require codeigniter4/shield ``` ### Troubleshooting @@ -35,29 +35,29 @@ If you have it installed as a phar, or otherwise you will need to adjust the way If you get the following error: -``` - Could not find a version of package codeigniter4/shield matching your minimum-stability (stable). - Require it with an explicit version constraint allowing its desired stability. +```console +Could not find a version of package codeigniter4/shield matching your minimum-stability (stable). +Require it with an explicit version constraint allowing its desired stability. ``` 1. Add the following to change your [minimum-stability](https://getcomposer.org/doc/articles/versions.md#minimum-stability) in your project `composer.json`: ```json - "minimum-stability": "dev", - "prefer-stable": true, + "minimum-stability": "dev", + "prefer-stable": true, ``` 2. Or specify an explicit version: ```console - > composer require codeigniter4/shield:dev-develop + composer require codeigniter4/shield:dev-develop ``` The above specifies `develop` branch. See https://getcomposer.org/doc/articles/versions.md#branches ```console - > composer require codeigniter4/shield:^1.0.0-beta + composer require codeigniter4/shield:^1.0.0-beta ``` The above specifies `v1.0.0-beta` or later and before `v2.0.0`. @@ -70,7 +70,7 @@ If you get the following error: 1. Run the following command. This command handles steps 1-5 of *Manual Setup* and runs the migrations. ```console - > php spark shield:setup + php spark shield:setup ``` ### Manual Setup @@ -120,7 +120,7 @@ your project. 5. **Migration** Run the migrations. ```console - > php spark migrate --all + php spark migrate --all ``` #### Note: migration error diff --git a/src/Auth.php b/src/Auth.php index 1b063f4ee..fae81dff3 100644 --- a/src/Auth.php +++ b/src/Auth.php @@ -129,6 +129,7 @@ public function getProvider(): UserModel return $this->userProvider; } + /** @var \CodeIgniter\Shield\Config\Auth $config */ $config = config('Auth'); if (! property_exists($config, 'userProvider')) { diff --git a/src/Authentication/Passwords/CompositionValidator.php b/src/Authentication/Passwords/CompositionValidator.php index 5e85abbdb..dec8f34af 100644 --- a/src/Authentication/Passwords/CompositionValidator.php +++ b/src/Authentication/Passwords/CompositionValidator.php @@ -32,7 +32,7 @@ public function check(string $password, ?User $user = null): Result throw AuthenticationException::forUnsetPasswordLength(); } - $passed = strlen($password) >= $this->config->minimumPasswordLength; + $passed = mb_strlen($password, 'UTF-8') >= $this->config->minimumPasswordLength; if (! $passed) { return new Result([ diff --git a/src/Config/Auth.php b/src/Config/Auth.php index 7d40bf424..7ef2cd9bf 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -278,41 +278,34 @@ class Auth extends BaseConfig /** * -------------------------------------------------------------------- - * Encryption Algorithm to use + * Hashing Algorithm to use * -------------------------------------------------------------------- * Valid values are * - PASSWORD_DEFAULT (default) * - PASSWORD_BCRYPT * - PASSWORD_ARGON2I - As of PHP 7.2 only if compiled with support for it * - PASSWORD_ARGON2ID - As of PHP 7.3 only if compiled with support for it - * - * If you choose to use any ARGON algorithm, then you might want to - * uncomment the "ARGON2i/D Algorithm" options to suit your needs */ public string $hashAlgorithm = PASSWORD_DEFAULT; /** * -------------------------------------------------------------------- - * ARGON2i/D Algorithm options + * ARGON2I/ARGON2ID Algorithm options * -------------------------------------------------------------------- - * The ARGON2I method of encryption allows you to define the "memory_cost", + * The ARGON2I method of hashing allows you to define the "memory_cost", * the "time_cost" and the number of "threads", whenever a password hash is * created. - * This defaults to a value of 10 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. */ - public int $hashMemoryCost = 2048; // PASSWORD_ARGON2_DEFAULT_MEMORY_COST; + public int $hashMemoryCost = 65536; // PASSWORD_ARGON2_DEFAULT_MEMORY_COST; - public int $hashTimeCost = 4; // PASSWORD_ARGON2_DEFAULT_TIME_COST; - public int $hashThreads = 4; // PASSWORD_ARGON2_DEFAULT_THREADS; + public int $hashTimeCost = 4; // PASSWORD_ARGON2_DEFAULT_TIME_COST; + public int $hashThreads = 1; // PASSWORD_ARGON2_DEFAULT_THREADS; /** * -------------------------------------------------------------------- - * Password Hashing Cost + * BCRYPT Algorithm options * -------------------------------------------------------------------- - * The BCRYPT method of encryption allows you to define the "cost" + * 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. * However, depending on the security needs of your application diff --git a/src/Config/AuthGroups.php b/src/Config/AuthGroups.php index 95309f1b0..1fef9e312 100644 --- a/src/Config/AuthGroups.php +++ b/src/Config/AuthGroups.php @@ -20,10 +20,15 @@ class AuthGroups extends BaseConfig * -------------------------------------------------------------------- * Groups * -------------------------------------------------------------------- - * The available authentication systems, listed - * with alias and class name. These can be referenced - * by alias in the auth helper: - * auth('api')->attempt($credentials); + * An associative array of the available groups in the system, where the keys are + * the group names and the values are arrays of the group info. + * + * Whatever value you assign as the key will be used to refer to the group when using functions such as: + * $user->addGroup('superadmin'); + * + * @var array> + * + * @see https://github.com/codeigniter4/shield/blob/develop/docs/quickstart.md#change-available-groups for more info */ public array $groups = [ 'superadmin' => [ diff --git a/src/Entities/User.php b/src/Entities/User.php index 7f104cd31..e7e394e19 100644 --- a/src/Entities/User.php +++ b/src/Entities/User.php @@ -14,10 +14,12 @@ /** * @property string|null $email + * @property int|string|null $id * @property UserIdentity[]|null $identities * @property Time|null $last_active * @property string|null $password * @property string|null $password_hash + * @property string|null $username */ class User extends Entity { diff --git a/src/Models/UserModel.php b/src/Models/UserModel.php index 6992f2a2c..f9f9b3c50 100644 --- a/src/Models/UserModel.php +++ b/src/Models/UserModel.php @@ -14,6 +14,9 @@ use CodeIgniter\Shield\Exceptions\ValidationException; use Faker\Generator; +/** + * @phpstan-consistent-constructor + */ class UserModel extends Model { use CheckQueryReturnTrait; diff --git a/tests/Unit/CompositionValidatorTest.php b/tests/Unit/CompositionValidatorTest.php index a44e6306a..d1a9fbe1d 100644 --- a/tests/Unit/CompositionValidatorTest.php +++ b/tests/Unit/CompositionValidatorTest.php @@ -45,7 +45,23 @@ public function testCheckFalse(): void $result = $this->validator->check($password); $this->assertFalse($result->isOK()); - $this->assertSame(lang('Auth.errorPasswordLength', [$this->config->minimumPasswordLength]), $result->reason()); + $this->assertSame( + lang('Auth.errorPasswordLength', [$this->config->minimumPasswordLength]), + $result->reason() + ); + } + + public function testCheckFalseMultibyte(): void + { + $password = '🍣😀'; + + $result = $this->validator->check($password); + + $this->assertFalse($result->isOK()); + $this->assertSame( + lang('Auth.errorPasswordLength', [$this->config->minimumPasswordLength]), + $result->reason() + ); } public function testCheckTrue(): void diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index 182a50671..5258da8e6 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -24,6 +24,8 @@ class Registrar * DB config array for testing purposes. * * @var array + * + * @psalm-suppress RedundantCondition */ protected static $dbConfig = [ 'MySQLi' => [