diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1ce7f5..d21794c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['8.1', '8.2'] + php-version: ['8.2', '8.3'] db-type: [sqlite, mysql, pgsql] prefer-lowest: [''] @@ -57,7 +57,7 @@ jobs: fi - name: Setup problem matchers for PHPUnit - if: matrix.php-version == '8.1' && matrix.db-type == 'mysql' + if: matrix.php-version == '8.2' && matrix.db-type == 'mysql' run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Run PHPUnit @@ -65,14 +65,14 @@ jobs: if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi - if [[ ${{ matrix.php-version }} == '8.1' ]]; then + if [[ ${{ matrix.php-version }} == '8.2' ]]; then export CODECOVERAGE=1 && vendor/bin/phpunit --coverage-clover=coverage.xml else vendor/bin/phpunit fi - name: Submit code coverage - if: matrix.php-version == '8.1' + if: matrix.php-version == '8.2' uses: codecov/codecov-action@v1 cs-stan: @@ -85,7 +85,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.2' extensions: mbstring, intl, apcu, memcached, redis tools: cs2pr coverage: none diff --git a/Docs/Documentation/TwoFactor.md b/Docs/Documentation/TwoFactor.md index 1cdf50c..0c85cff 100644 --- a/Docs/Documentation/TwoFactor.md +++ b/Docs/Documentation/TwoFactor.md @@ -8,6 +8,14 @@ Configuration Processors defined as Configure storage with key `TwoFactorProcessors` +By default `\RobThree\Auth\Providers\Qr\EndroidQrCodeProvider` is used. + +You can disable it by adding this to any config file: + +`OneTimePasswordAuthenticator.qrcodeprovider` => `YOUR QR CODE PROVIDER` + +To get a list of available providers please visit [RobThree/TwoFactorAuth](https://robthree.github.io/TwoFactorAuth/qr-codes.html) documentation. + Processors ------------- diff --git a/composer.json b/composer.json index a076a42..86ca966 100644 --- a/composer.json +++ b/composer.json @@ -26,18 +26,19 @@ "source": "https://github.com/CakeDC/auth" }, "require": { - "php": ">=8.1.0", + "php": ">=8.2.0", "cakephp/cakephp": "^5.0" }, "require-dev": { "phpunit/phpunit": "^10.0", + "endroid/qr-code": "^6.0", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", "league/oauth2-google": "@stable", "league/oauth2-linkedin": "@stable", "luchianenco/oauth2-amazon": "^1.1", "google/recaptcha": "@stable", - "robthree/twofactorauth": "^2.0", + "robthree/twofactorauth": "^3.0", "league/oauth1-client": "^1.7", "cakephp/authorization": "^3.0", "cakephp/cakephp-codesniffer": "^5.0", diff --git a/config/auth.php b/config/auth.php index aa16c36..2dafc60 100644 --- a/config/auth.php +++ b/config/auth.php @@ -108,7 +108,7 @@ // The algorithm used 'algorithm' => \RobThree\Auth\Algorithm::Sha1, // QR-code provider (more on this later) - 'qrcodeprovider' => null, + 'qrcodeprovider' => new \RobThree\Auth\Providers\Qr\EndroidQrCodeProvider(), // Random Number Generator provider (more on this later) 'rngprovider' => null ], diff --git a/src/Authenticator/OneTimeTokenAuthenticator.php b/src/Authenticator/OneTimeTokenAuthenticator.php new file mode 100644 index 0000000..1813862 --- /dev/null +++ b/src/Authenticator/OneTimeTokenAuthenticator.php @@ -0,0 +1,41 @@ +getQuery('token') ?: $request->getData('token'); + if (is_array($token)) { + $token = join($token); + } + + if (!$token) { + return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); + } + + $usersTable = TableRegistry::getTableLocator()->get(Configure::read('Users.table')); + + $user = $usersTable->loginWithToken($token); + + if (!$user) { + return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); + } + + return new Result($user, Result::SUCCESS); + } +} diff --git a/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php index 7de5b64..d3df4fe 100644 --- a/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php +++ b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php @@ -41,11 +41,11 @@ public function initialize(array $config): void if (Configure::read('OneTimePasswordAuthenticator.login')) { $this->tfa = new TwoFactorAuth( + Configure::read('OneTimePasswordAuthenticator.qrcodeprovider'), Configure::read('OneTimePasswordAuthenticator.issuer'), Configure::read('OneTimePasswordAuthenticator.digits'), Configure::read('OneTimePasswordAuthenticator.period'), Configure::read('OneTimePasswordAuthenticator.algorithm'), - Configure::read('OneTimePasswordAuthenticator.qrcodeprovider'), Configure::read('OneTimePasswordAuthenticator.rngprovider') ); } diff --git a/src/Exception/InvalidProviderException.php b/src/Exception/InvalidProviderException.php index b6d50de..ed0d1c7 100644 --- a/src/Exception/InvalidProviderException.php +++ b/src/Exception/InvalidProviderException.php @@ -32,7 +32,7 @@ class InvalidProviderException extends CakeException * @param int $code code * @param null $previous previous */ - public function __construct(array|string $message, int $code = 500, $previous = null) + public function __construct(array|string $message, int $code = 500, null $previous = null) { parent::__construct($message, $code, $previous); } diff --git a/src/Exception/InvalidSettingsException.php b/src/Exception/InvalidSettingsException.php index dab28d3..e66757d 100644 --- a/src/Exception/InvalidSettingsException.php +++ b/src/Exception/InvalidSettingsException.php @@ -32,7 +32,7 @@ class InvalidSettingsException extends CakeException * @param int $code code * @param null $previous previous */ - public function __construct(array|string $message, int $code = 500, $previous = null) + public function __construct(array|string $message, int $code = 500, null $previous = null) { parent::__construct($message, $code, $previous); }