From 6d814566fba8ac45b5cba6993e7b98223b259256 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Thu, 9 Mar 2017 21:24:04 -0500 Subject: Render QR code for TwoFactor authentication without Google Chart API --- ChangeLog | 5 + app/Controller/TwoFactorController.php | 31 ++++-- .../PostAuthenticationProviderInterface.php | 9 -- app/Template/twofactor/show.php | 7 +- composer.json | 3 +- composer.lock | 113 +++++++++++++++------ tests/units/Auth/TotpAuthTest.php | 5 - 7 files changed, 114 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index a8a69648..92846544 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,11 +7,16 @@ New features: Improvements: +* Render QR code for TwoFactor authentication without Google Chart API * Add toggle button to show/hide subtasks in task list view * Display tags in task list view * Change users list layout * Project priority is always rendered now +Breaking Changes: + +* Remove method getQrCodeUrl() from PostAuthenticationProviderInterface + Version 1.0.40 (Feb 24 2017) ---------------------------- diff --git a/app/Controller/TwoFactorController.php b/app/Controller/TwoFactorController.php index d02c8950..73060c44 100644 --- a/app/Controller/TwoFactorController.php +++ b/app/Controller/TwoFactorController.php @@ -3,6 +3,7 @@ namespace Kanboard\Controller; use Kanboard\Core\Controller\AccessForbiddenException; +use PHPQRCode; /** * Two Factor Auth controller @@ -65,9 +66,8 @@ class TwoFactorController extends UserViewController } $this->response->html($this->helper->layout->user('twofactor/show', array( - 'user' => $user, - 'secret' => $this->sessionStorage->twoFactorSecret, - 'qrcode_url' => $provider->getQrCodeUrl($label), + 'user' => $user, + 'secret' => $this->sessionStorage->twoFactorSecret, 'key_url' => $provider->getKeyUrl($label), ))); } @@ -192,11 +192,28 @@ class TwoFactorController extends UserViewController 'twofactor_secret' => '', )); - return $this->response->redirect($this->helper->url->to('UserViewController', 'show', array('user_id' => $user['id']))); + $this->response->redirect($this->helper->url->to('UserViewController', 'show', array('user_id' => $user['id']))); + } else { + $this->response->html($this->helper->layout->user('twofactor/disable', array( + 'user' => $user, + ))); } + } - return $this->response->html($this->helper->layout->user('twofactor/disable', array( - 'user' => $user, - ))); + /** + * Render QR Code image + */ + public function qrcode() + { + if (isset($this->sessionStorage->twoFactorSecret)) { + $user = $this->getUser(); + $provider = $this->authenticationManager->getPostAuthenticationProvider(); + $provider->setSecret($this->sessionStorage->twoFactorSecret); + $url = $provider->getKeyUrl($user['email'] ?: $user['username']); + + if (! empty($url)) { + PHPQRCode\QRcode::png($url, false, 'L', 6, 0); + } + } } } diff --git a/app/Core/Security/PostAuthenticationProviderInterface.php b/app/Core/Security/PostAuthenticationProviderInterface.php index 3f628bb0..27b7b5cf 100644 --- a/app/Core/Security/PostAuthenticationProviderInterface.php +++ b/app/Core/Security/PostAuthenticationProviderInterface.php @@ -49,15 +49,6 @@ interface PostAuthenticationProviderInterface extends AuthenticationProviderInte */ public function getSecret(); - /** - * Get QR code url (empty if no QR can be provided) - * - * @access public - * @param string $label - * @return string - */ - public function getQrCodeUrl($label); - /** * Get key url (empty if no url can be provided) * diff --git a/app/Template/twofactor/show.php b/app/Template/twofactor/show.php index a5bdeccb..412077b9 100644 --- a/app/Template/twofactor/show.php +++ b/app/Template/twofactor/show.php @@ -2,17 +2,14 @@

- +

text->e($secret) ?>

- -




- - +

text->e($key_url) ?>

diff --git a/composer.json b/composer.json index ca25d3a2..28db1676 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,8 @@ "swiftmailer/swiftmailer" : "5.4.5", "symfony/console" : "2.8.7", "symfony/event-dispatcher" : "2.7.14", - "gregwar/captcha": "1.1.1" + "gregwar/captcha": "1.1.1", + "aferrandini/phpqrcode": "1.0.1" }, "autoload" : { "classmap" : ["app/"], diff --git a/composer.lock b/composer.lock index a327c2aa..9aba396a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,53 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "3d24ad1182c0460eda5791bd7fc68984", - "content-hash": "67d44f262438806c115a362c9912b669", + "hash": "9da4e56dd10c23d4c3ea7e4949d18b24", + "content-hash": "6fded72f90b9a69e404ea9a2410339ad", "packages": [ + { + "name": "aferrandini/phpqrcode", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/aferrandini/PHPQRCode.git", + "reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aferrandini/PHPQRCode/zipball/3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46", + "reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "PHPQRCode": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ariel Ferrandini", + "email": "arielferrandini@gmail.com", + "homepage": "http://www.ferrandini.com/", + "role": "Developer" + } + ], + "description": "PHPQRCode porting and changed for PHP 5.3 compatibility", + "homepage": "https://github.com/aferrandini/PHPQRCode", + "keywords": [ + "barcode", + "php", + "qrcode" + ], + "time": "2013-07-08 09:39:08" + }, { "name": "christian-riesen/base32", "version": "1.3.1", @@ -1072,27 +1116,27 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", + "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", @@ -1131,7 +1175,7 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2017-03-02 20:05:34" }, { "name": "phpunit/php-code-coverage", @@ -1285,25 +1329,30 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1325,20 +1374,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2017-02-26 11:10:40" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "1.4.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { @@ -1374,7 +1423,7 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2017-02-27 10:12:30" }, { "name": "phpunit/phpunit", @@ -1570,16 +1619,16 @@ }, { "name": "sebastian/comparator", - "version": "1.2.2", + "version": "1.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", - "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { @@ -1630,7 +1679,7 @@ "compare", "equality" ], - "time": "2016-11-19 09:18:40" + "time": "2017-01-29 09:50:25" }, { "name": "sebastian/diff", @@ -1854,16 +1903,16 @@ }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", "shasum": "" }, "require": { @@ -1903,7 +1952,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-10-03 07:41:43" }, { "name": "sebastian/version", diff --git a/tests/units/Auth/TotpAuthTest.php b/tests/units/Auth/TotpAuthTest.php index 3a82c01c..d799259b 100644 --- a/tests/units/Auth/TotpAuthTest.php +++ b/tests/units/Auth/TotpAuthTest.php @@ -40,11 +40,6 @@ class TotpAuthTest extends Base $this->assertEmpty($provider->getKeyUrl('me')); $provider->setSecret('mySecret'); - $this->assertEquals( - 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chld=M|0&chl=otpauth%3A%2F%2Ftotp%2Fme%3Fsecret%3DmySecret%26issuer%3DKanboard', - $provider->getQrCodeUrl('me') - ); - $this->assertEquals('otpauth://totp/me?secret=mySecret&issuer=Kanboard', $provider->getKeyUrl('me')); } -- cgit v1.2.3