Skip to content

Commit

Permalink
Added backup codes
Browse files Browse the repository at this point in the history
  • Loading branch information
mystralkk committed Dec 14, 2017
1 parent 8a5cb1a commit a3923e4
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 19 deletions.
4 changes: 2 additions & 2 deletions language/english.php
Expand Up @@ -438,15 +438,15 @@
'tfa_help1' => 'Make sure to install "Google Authenticator" application on your mobile device before you enable Two Factor Authentication.',
'tfa_help2' => 'Enable Two Factor Authentication.',
'tfa_help3' => 'Run "Google Authenticator", tap on the plus icon and scan the QR code.',
'tfa_help4' => 'Hit the "Save" button at the bottom of the screen.',
'tfa_help4' => 'Print or download the codes below in case you cannot use your mobile device you installed the Google Authenticator. Each code is valid only one-time. If you generate a new set of codes, then the current set will be invalid.',
'tfa_help5' => 'Hit the "Save" button at the bottom of the screen.',
'tfa_enter_code' => 'Enter the %d-digit code your Google Authenticator app is showing',
'tfa_code' => 'Google Authenticator Code',
'tfa_qrcode' => 'QR Code',
'tfa_show_qrcode' => 'Show QR code',
'tfa_hide_qrcode' => 'Hide QR code',
'tfa_do_not_require_tfa_again' => 'Don\'t require Two Factor Authentication again on this device',
'tfa_backup_code' => 'Backup Codes',
'tfa_backup_code_desc' => 'Please print or download the codes below in case you cannot use your mobile device you installed the Google Authenticator. Each code is valid only one-time. If you generate a new set of codes, then the current set will be invalid.',
'tfa_download' => 'Download Backup Codes',
'tfa_new_backup_code' => 'Generate a new set of backup codes'
);
Expand Down
4 changes: 2 additions & 2 deletions language/english_utf-8.php
Expand Up @@ -438,15 +438,15 @@
'tfa_help1' => 'Make sure to install "Google Authenticator" application on your mobile device before you enable Two Factor Authentication.',
'tfa_help2' => 'Enable Two Factor Authentication.',
'tfa_help3' => 'Run "Google Authenticator", tap on the plus icon and scan the QR code.',
'tfa_help4' => 'Hit the "Save" button at the bottom of the screen.',
'tfa_help4' => 'Print or download the codes below in case you cannot use your mobile device you installed the Google Authenticator. Each code is valid only one-time. If you generate a new set of codes, then the current set will be invalid.',
'tfa_help5' => 'Hit the "Save" button at the bottom of the screen.',
'tfa_enter_code' => 'Enter the %d-digit code your Google Authenticator app is showing',
'tfa_code' => 'Google Authenticator Code',
'tfa_qrcode' => 'QR Code',
'tfa_show_qrcode' => 'Show QR code',
'tfa_hide_qrcode' => 'Hide QR code',
'tfa_do_not_require_tfa_again' => 'Don\'t require Two Factor Authentication again on this device',
'tfa_backup_code' => 'Backup Codes',
'tfa_backup_code_desc' => 'Please print or download the codes below in case you cannot use your mobile device you installed the Google Authenticator. Each code is valid only one-time. If you generate a new set of codes, then the current set will be invalid.',
'tfa_download' => 'Download Backup Codes',
'tfa_new_backup_code' => 'Generate a new set of backup codes'
);
Expand Down
6 changes: 3 additions & 3 deletions language/japanese_utf-8.php
Expand Up @@ -444,17 +444,17 @@
'user_max_login_attempts' => 'ログインの試行回数の上限を超えました、',
'tfa_two_factor_auth' => '2段階認証',
'tfa_help1' => '2段階認証を有効にする前に、Google認証システムのアプリケーションをモバイル端末にインストールしてください。',
'tfa_help2' => '2段階認証を有効にしてください。',
'tfa_help2' => '「2段階認証を有効にする」を「はい」にしてください。',
'tfa_help3' => 'Google認証システムを起動して、プラスアイコンをタップし、QRコードをスキャンしてください。',
'tfa_help4' => '画面下部の「保存」をクリックしてください。',
'tfa_help4' => 'Google認証システムをインストールしたデバイスを使えない場合に備えて、下記のコードを印刷するかダウンロードしてください。各コードは1回だけ有効です。新しいコードを生成すると、現在のコードは無効になります。',
'tfa_help5' => '画面下部の「保存」をクリックしてください。',
'tfa_enter_code' => 'Google認証システムに表示されている%d桁の数字を入力してください',
'tfa_code' => '認証コード',
'tfa_qrcode' => 'QRコード',
'tfa_show_qrcode' => 'QRコードを表示',
'tfa_hide_qrcode' => 'QRコードを隠す',
'tfa_do_not_require_tfa_again' => 'このデバイスでは今後2段階認証を要求しない',
'tfa_backup_code' => 'バックアップコード',
'tfa_backup_code_desc' => 'Google認証システムをインストールしたデバイスを使えない場合に備えて、下記のコードを印刷するかダウンロードしてください。各コードは1回だけ有効です。新しいコードを生成すると、現在のコードは無効になります。',
'tfa_download' => 'バックアップコードをダウンロード',
'tfa_new_backup_code' => 'バックアップコードを再作成'
);
Expand Down
25 changes: 16 additions & 9 deletions public_html/javascript/two_factor_auth.js
Expand Up @@ -2,31 +2,38 @@
var geeklog;

geeklog = geeklog || {};

geeklog.tfa = {
imageTag: document.getElementById('qrcode_data'),
elements: document.getElementsByClassName('tfa'),
init: function () {
'use strict';
var self = this;

// Hide QR code for the first time
this.hideQRCodeImage();
// Hide QR code and backup codes at first
this.hideTFAElements();

// Show/Hide QR code image
document.getElementById('enable_tfa').addEventListener('change', function (ev) {
if (ev.target.value === '0') {
self.hideQRCodeImage();
self.hideTFAElements();
} else {
self.showQRCodeImage();
self.showTFAElements();
}
}, false);
},
showQRCodeImage: function () {
showTFAElements: function () {
'use strict';
this.imageTag.style.display = '';
var i;
for (i = 0; i < this.elements.length; i++) {
this.elements[i].style.display = '';
}
},
hideQRCodeImage: function () {
hideTFAElements: function () {
'use strict';
this.imageTag.style.display = 'none';
var i;
for (i = 0; i < this.elements.length; i++) {
this.elements[i].style.display = 'none';
}
}
};

Expand Down
13 changes: 11 additions & 2 deletions public_html/layout/denim/preferences/profile.thtml
Expand Up @@ -78,6 +78,7 @@
<li>{lang_tfa_help2}</li>
<li>{lang_tfa_help3}</li>
<li>{lang_tfa_help4}</li>
<li>{lang_tfa_help5}</li>
</ol>
</div>

Expand All @@ -89,8 +90,16 @@
</select>
</dd>

<dt><label for="tfa_qrcode">{lang_tfa_qrcode}</label></dt>
<dd><img src="{qrcode_data}" alt="" id="qrcode_data"{xhtml}></dd>
<dt class="tfa"><label for="tfa_qrcode">{lang_tfa_qrcode}</label></dt>
<dd class="tfa"><img src="{qrcode_data}" alt="" id="qrcode_data"{xhtml}></dd>

<dt class="tfa"><label for="tfa_backup_code">{lang_tfa_backup_code}</label></dt>
<dd class="tfa">
<p class="tfa"><a href="{site_url}/usersettings.php?mode=download_backupcodes" id="tfa_backup_code">{lang_tfa_download}</a></p>
<ul class="tfa">
{backup_codes}
</ul>
</dd>
</dl>
</div>
</fieldset>
Expand Down
48 changes: 48 additions & 0 deletions public_html/usersettings.php
Expand Up @@ -171,9 +171,15 @@ function edituser()
if (empty($secret)) {
$secret = $tfa->createSecret();
$tfa->saveSecretToDatabase($secret);
$backupCodes = $tfa->createBackupCodes();
} else {
$backupCodes = $tfa->getBackupCodesFromDatabase();
}

$qrCodeDat = $tfa->getQRCodeImageAsDataURI($secret, $_USER['email']);
$backupCodes = '<li class="backupcode">' . PHP_EOL
. implode('</li><li class="backupcode">', $backupCodes)
. '</li>' . PHP_EOL;

$preferences->set_var(array(
'enable_twofactorauth' => true,
Expand All @@ -182,12 +188,16 @@ function edituser()
'lang_tfa_help2' => $LANG04['tfa_help2'],
'lang_tfa_help3' => $LANG04['tfa_help3'],
'lang_tfa_help4' => $LANG04['tfa_help4'],
'lang_tfa_help5' => $LANG04['tfa_help5'],
'lang_enable_twofactorauth' => $LANG_confignames['Core']['enable_twofactorauth'],
'lang_tfa_qrcode' => $LANG04['tfa_qrcode'],
'lang_tfa_show_qrcode' => $LANG04['tfa_show_qrcode'],
'lang_tfa_hide_qrcode' => $LANG04['tfa_hide_qrcode'],
'lang_tfa_backup_code' => $LANG04['tfa_backup_code'],
'lang_tfa_download' => $LANG04['tfa_download'],
'enable_tfa_options' => $enableTfaOptions,
'qrcode_data' => $qrCodeDat,
'backup_codes' => $backupCodes,
));
$_SCRIPTS->setJavaScriptFile('two_factor_auth', '/javascript/two_factor_auth.js');
} else {
Expand Down Expand Up @@ -1436,6 +1446,40 @@ function savepreferences($A)
PLG_userInfoChanged($_USER['uid']);
}

/**
* Download a file containing backup codes
*/
function downloadBackupCodes() {
global $_CONF, $_USER;

if (isset($_CONF['enable_twofactorauth']) && $_CONF['enable_twofactorauth'] &&
!COM_isAnonUser() && isset($_USER['uid']) &&($_USER['uid'] > 1)) {
$tfa = new \Geeklog\TwoFactorAuthentication($_USER['uid']);

try {
$secret = $tfa->loadSecretFromDatabase();

if (empty($secret)) {
$secret = $tfa->createSecret();
$tfa->saveSecretToDatabase($secret);
$backupCodes = $tfa->createBackupCodes();
} else {
$backupCodes = $tfa->getBackupCodesFromDatabase();
}

$backupCodes = implode("\r\n", $backupCodes);
header('Content-Type: text/plain');
header('Content-Length: ' . strlen($backupCodes));
header('Content-Disposition: attachment; filename="gl_backup_codes.txt"');
echo $backupCodes;
} catch (\RobThree\Auth\TwoFactorAuthException $e) {
COM_errorLog(__FUNCTION__ . ': ' . $e->getMessage());
}
}

die();
}

// MAIN
if (Geeklog\Input::post('btncancel') === $LANG_ADMIN['cancel']) {
COM_redirect($_CONF['site_url']);
Expand Down Expand Up @@ -1496,6 +1540,10 @@ function savepreferences($A)
COM_redirect($_CONF['site_url'] . '/usersettings.php?msg=5');
break;

case 'download_backupcodes':
downloadBackupCodes();
break;

case 'synch':
// This case is the result of a callback from an OAuth service.
// The user has made a request to resynch their Geeklog user account with the remote OAuth service
Expand Down
2 changes: 1 addition & 1 deletion system/classes/TwoFactorAuthentication.php
Expand Up @@ -20,7 +20,7 @@ class TwoFactorAuthentication
const NUM_DIGITS_OF_BACKUP_CODE = 8;

// Number of backup codes in database
const NUM_BACKUP_CODES = 4;
const NUM_BACKUP_CODES = 10;

/**
* Flag to show whether two factor auth is enabled for the current user
Expand Down

0 comments on commit a3923e4

Please sign in to comment.