Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/twofactor_totp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2016-06-04 14:16:18 +0300
committerChristoph Wurst <christoph@winzerhof-wurst.at>2016-06-04 14:16:18 +0300
commited7d8759dbc637e121c732bfeb3cfc2042d818ff (patch)
treeb1c7fc438a4464f85b6cdb1f4e7026556dfbf5e9
parentb6943ad9d26b7e70b47ed644114a6a4e0b2fa30b (diff)
first working version
-rw-r--r--appinfo/database.xml41
-rw-r--r--appinfo/info.xml2
-rw-r--r--lib/Db/TotpSecret.php40
-rw-r--r--lib/Db/TotpSecretMapper.php57
-rw-r--r--lib/Exception/NoTotpSecretFoundException.php28
-rw-r--r--lib/Exception/TotpSecretAlreadySet.php28
-rw-r--r--lib/Provider/TotpProvider.php (renamed from lib/Provider/SmsProvider.php)26
-rw-r--r--lib/Service/ITotp.php46
-rw-r--r--lib/Service/Totp.php88
-rw-r--r--templates/challenge.php8
10 files changed, 350 insertions, 14 deletions
diff --git a/appinfo/database.xml b/appinfo/database.xml
new file mode 100644
index 0000000..b4daaa4
--- /dev/null
+++ b/appinfo/database.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<database>
+ <name>*dbname*</name>
+ <create>true</create>
+ <overwrite>false</overwrite>
+ <charset>utf8</charset>
+ <table>
+ <name>*dbprefix*twofactor_totp_secrets</name>
+ <declaration>
+ <field>
+ <name>id</name>
+ <type>integer</type>
+ <autoincrement>1</autoincrement>
+ <default>0</default>
+ <notnull>true</notnull>
+ <length>4</length>
+ </field>
+ <field>
+ <name>user_id</name>
+ <type>text</type>
+ <default></default>
+ <notnull>true</notnull>
+ <length>64</length>
+ </field>
+ <field>
+ <name>secret</name>
+ <type>clob</type>
+ <notnull>true</notnull>
+ </field>
+
+ <index>
+ <name>totp_secrets_user_id</name>
+ <unique>true</unique>
+ <field>
+ <name>user_id</name>
+ <sorting>ascending</sorting>
+ </field>
+ </index>
+ </declaration>
+ </table>
+</database>
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 7f9cbd8..44d1105 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -5,7 +5,7 @@
<description>A Two-Factor-Auth Provider for TOTP (e.g. Google Authenticator) for ownCloud 9.1</description>
<licence>AGPL</licence>
<author>Christoph Wurst</author>
- <version>0.0.1</version>
+ <version>0.0.2</version>
<namespace>TwoFactorTotp</namespace>
<category>other</category>
<types>
diff --git a/lib/Db/TotpSecret.php b/lib/Db/TotpSecret.php
new file mode 100644
index 0000000..75b06bb
--- /dev/null
+++ b/lib/Db/TotpSecret.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Two-factor TOTP
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorTotp\Db;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * @method string getUserId()
+ * @method void setUserId(string $userId)
+ * @method string getSecret()
+ * @method void setSecret(string $secret)
+ */
+class TotpSecret extends Entity {
+
+ /** @var string */
+ protected $userId;
+
+ /** @var string */
+ protected $secret;
+
+}
diff --git a/lib/Db/TotpSecretMapper.php b/lib/Db/TotpSecretMapper.php
new file mode 100644
index 0000000..5a3c847
--- /dev/null
+++ b/lib/Db/TotpSecretMapper.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Two-factor TOTP
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorTotp\Db;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\Mapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDb;
+use OCP\IUser;
+
+class TotpSecretMapper extends Mapper {
+
+ public function __construct(IDb $db) {
+ parent::__construct($db, 'twofactor_totp_secrets');
+ }
+
+ /**
+ * @param IUser $user
+ * @throws DoesNotExistException
+ * @return TotpSecret
+ */
+ public function getSecret(IUser $user) {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+
+ $qb->select('id', 'user_id', 'secret')
+ ->from('twofactor_totp_secrets')
+ ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($user->getUID())));
+ $result = $qb->execute();
+
+ $row = $result->fetch();
+ if ($row === false) {
+ throw new DoesNotExistException();
+ }
+ return TotpSecret::fromRow($row);
+ }
+
+}
diff --git a/lib/Exception/NoTotpSecretFoundException.php b/lib/Exception/NoTotpSecretFoundException.php
new file mode 100644
index 0000000..d8d09a0
--- /dev/null
+++ b/lib/Exception/NoTotpSecretFoundException.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Two-factor TOTP
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorTotp\Exception;
+
+use Exception;
+
+class NoTotpSecretFoundException extends Exception {
+
+}
diff --git a/lib/Exception/TotpSecretAlreadySet.php b/lib/Exception/TotpSecretAlreadySet.php
new file mode 100644
index 0000000..b79f33a
--- /dev/null
+++ b/lib/Exception/TotpSecretAlreadySet.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Two-factor TOTP
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorTotp\Exception;
+
+use Exception;
+
+class TotpSecretAlreadySet extends Exception {
+
+}
diff --git a/lib/Provider/SmsProvider.php b/lib/Provider/TotpProvider.php
index 68d4760..4cb8eec 100644
--- a/lib/Provider/SmsProvider.php
+++ b/lib/Provider/TotpProvider.php
@@ -21,15 +21,21 @@
namespace OCA\TwoFactorTotp\Provider;
-use Base32\Base32;
+use OCA\TwoFactorTotp\Exception\NoTotpSecretFoundException;
+use OCA\TwoFactorTotp\Service\Totp;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\IUser;
use OCP\Template;
-use Otp\GoogleAuthenticator;
-use Otp\Otp;
class TotpProvider implements IProvider {
+ /** @var Totp */
+ private $totp;
+
+ public function __construct(Totp $totp) {
+ $this->totp = $totp;
+ }
+
/**
* Get unique identifier of this 2FA provider
*
@@ -76,13 +82,14 @@ class TotpProvider implements IProvider {
* @return Template
*/
public function getTemplate(IUser $user) {
- $otp = new Otp();
- //$secret = $this->random->generate(16);
- $secret = GoogleAuthenticator::generateRandom();
- $totp = $otp->totp(Base32::decode($secret));
+ try {
+ $this->totp->getSecret($user);
+ } catch (NoTotpSecretFoundException $ex) {
+ $qr = $this->totp->createSecret($user);
+ }
$tmpl = new Template('twofactor_totp', 'challenge');
- $tmpl->assign('secret', $totp);
+ $tmpl->assign('qr', $qr);
return $tmpl;
}
@@ -95,8 +102,7 @@ class TotpProvider implements IProvider {
* @param string $challenge
*/
public function verifyChallenge(IUser $user, $challenge) {
- $otp = new Otp();
- return $otp->checkTotp(Base32::decode($secret), $challenge);
+ return $this->totp->validateSecret($user, $challenge);
}
/**
diff --git a/lib/Service/ITotp.php b/lib/Service/ITotp.php
new file mode 100644
index 0000000..601a2d4
--- /dev/null
+++ b/lib/Service/ITotp.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Two-factor TOTP
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorTotp\Service;
+
+use OCA\TwoFactorTotp\Exception\TotpSecretAlreadySet;
+use OCP\IUser;
+
+interface ITotp {
+
+ /**
+ * @param IUser $user
+ */
+ public function getSecret(IUser $user);
+
+ /**
+ * @param IUser $user
+ * @throws TotpSecretAlreadySet
+ */
+ public function createSecret(IUser $user);
+
+ /**
+ * @param IUser $user
+ * @param string $key
+ */
+ public function validateSecret(IUser $user, $key);
+
+}
diff --git a/lib/Service/Totp.php b/lib/Service/Totp.php
new file mode 100644
index 0000000..4d94365
--- /dev/null
+++ b/lib/Service/Totp.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * ownCloud - Two-factor TOTP
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorTotp\Service;
+
+use Base32\Base32;
+use OCA\TwoFactorTotp\Db\TotpSecret;
+use OCA\TwoFactorTotp\Db\TotpSecretMapper;
+use OCA\TwoFactorTotp\Exception\NoTotpSecretFoundException;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\IUser;
+use OCP\Security\ICrypto;
+use Otp\GoogleAuthenticator;
+use Otp\Otp;
+
+class Totp implements ITotp {
+
+ /** @var TotpSecretMapper */
+ private $secretMapper;
+
+ /** @var ICrypto */
+ private $crypto;
+
+ public function __construct(TotpSecretMapper $secretMapper, ICrypto $crypto) {
+ $this->secretMapper = $secretMapper;
+ $this->crypto = $crypto;
+ }
+
+ public function getSecret(IUser $user) {
+ try {
+ $secret = $this->secretMapper->getSecret($user);
+ } catch (DoesNotExistException $ex) {
+ throw new NoTotpSecretFoundException();
+ }
+
+ $encryptedSecret = $secret->getSecret();
+ return $this->crypto->decrypt($encryptedSecret);
+ }
+
+ /**
+ * @todo prevent duplicates
+ *
+ * @param IUser $user
+ */
+ public function createSecret(IUser $user) {
+ $secret = GoogleAuthenticator::generateRandom();
+
+ $dbSecret = new TotpSecret();
+ $dbSecret->setUserId($user->getUID());
+ $dbSecret->setSecret($this->crypto->encrypt($secret));
+
+ $this->secretMapper->insert($dbSecret);
+
+ return GoogleAuthenticator::getQrCodeUrl('totp', 'ownCloud TOTP', $secret);
+ }
+
+ public function validateSecret(IUser $user, $key) {
+ try {
+ $dbSecret = $this->secretMapper->getSecret($user);
+ } catch (DoesNotExistException $ex) {
+ throw new NoTotpSecretFoundException();
+ }
+
+ $secret = $this->crypto->decrypt($dbSecret->getSecret());
+
+ $otp = new Otp();
+ return $otp->checkTotp(Base32::decode($secret), $key, 3);
+ }
+
+}
diff --git a/templates/challenge.php b/templates/challenge.php
index 59fdf73..ca462e9 100644
--- a/templates/challenge.php
+++ b/templates/challenge.php
@@ -1,6 +1,8 @@
-<p>TOTP: <?php p($_['secret']); ?></p>
+<?php if (isset($_['qr'])): ?>
+<a href="<?php echo $_['qr']; ?>" target="_blank">Scan QR Code</a>
+<?php endif; ?>
<form method="POST">
- <input type="text" name="challenge" required="required">
- <input type="submit" class="button" value="Verify">
+ <input type="text" name="challenge" required="required">
+ <input type="submit" class="button" value="Verify">
</form>