public function testCreateSecretGeneratesDesiredAmountOfEntropy() { $rng = new TestRNGProvider(true); $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); $this->assertEquals('A', $tfa->createSecret(5)); $this->assertEquals('AB', $tfa->createSecret(6)); $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128)); $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160)); $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320)); $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321)); }
/** * Configure the Two-factor Authentication. * * @return \Cake\Network\Response|void */ public function configure() { $this->loadModel('Users'); $user = $this->Users->find()->contain(['UsersTwoFactorAuth'])->where(['Users.id' => $this->Auth->user('id')])->select(['Users.id', 'Users.username', 'Users.two_factor_auth_enabled', 'UsersTwoFactorAuth.id', 'UsersTwoFactorAuth.user_id', 'UsersTwoFactorAuth.secret', 'UsersTwoFactorAuth.username'])->first(); if ($user->two_factor_auth_enabled == true) { $this->Flash->error(__('You have already set-up the Two-factor authentication.')); return $this->redirect(['controller' => 'users', 'action' => 'security']); } $tfa = new TwoFactorAuth('Xeta'); if (!is_null($user->users_two_factor_auth)) { $secret = $user->users_two_factor_auth->secret; } else { $this->loadModel('UsersTwoFactorAuth'); $secret = $tfa->createSecret(); $data = ['user_id' => $this->Auth->user('id'), 'secret' => $secret, 'username' => $user->username]; $entity = $this->UsersTwoFactorAuth->newEntity($data); $this->UsersTwoFactorAuth->save($entity); } $imgSrc = $tfa->getQRCodeImageAsDataUri($user->username, $secret); $secretCode = chunk_split($secret, 4, ' '); $this->set(compact('imgSrc', 'secretCode')); }
<!doctype html> <html> <head> <title>Demo</title> </head> <body> <ol> <?php require_once 'loader.php'; Loader::register('../lib', 'RobThree\\Auth'); use RobThree\Auth\TwoFactorAuth; $tfa = new TwoFactorAuth('MyApp'); echo '<li>First create a secret and associate it with a user'; $secret = $tfa->createSecret(); echo '<li>Next create a QR code and let the user scan it:<br><img src="' . $tfa->getQRCodeImageAsDataUri('My label', $secret) . '"><br>...or display the secret to the user for manual entry: ' . chunk_split($secret, 4, ' '); $code = $tfa->getCode($secret); echo '<li>Next, have the user verify the code; at this time the code displayed by a 2FA-app would be: <span style="color:#00c">' . $code . '</span> (but that changes periodically)'; echo '<li>When the code checks out, 2FA can be / is enabled; store (encrypted?) secret with user and have the user verify a code each time a new session is started.'; echo '<li>When aforementioned code (' . $code . ') was entered, the result would be: ' . ($tfa->verifyCode($secret, $code) === true ? '<span style="color:#0c0">OK</span>' : '<span style="color:#c00">FAIL</span>'); ?> </ol> <p>Note: Make sure your server-time is <a href="http://en.wikipedia.org/wiki/Network_Time_Protocol">NTP-synced</a>! Depending on the $discrepancy allowed your time cannot drift too much from the users' time!</p> </body> </html>
/** * createSecret * @return base32 shared secret stored in users table */ public function createSecret() { return $this->tfa->createSecret(); }