Merge pull request #1097 from AStove/TOTP

Support TOTP
This commit is contained in:
Lorenz Hübschle-Schneider 2019-12-21 16:49:26 +01:00 committed by GitHub
commit fa0b2f6142
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 15 deletions

View File

@ -100,33 +100,42 @@
<div class="panel-body">
<form class="form-signin" role="form">
<div class="form-group">
<label class="control-label" for="host">WeeChat relay hostname and port number</label>
<div class="input-group">
<div class="row no-gutter">
<div class="col-sm-9">
<label class="control-label" for="host">WeeChat relay hostname</label>
<input type="text" class="form-control favorite-font" id="host" ng-model="settings.hostField" ng-change="parseHost()" ng-class="{'is-invalid': hostInvalid}" placeholder="Address" autocapitalize="off">
</div>
<div class="col-sm-3">
<label class="control-label" for="port">Port</label>
<input type="text" class="form-control favorite-font" id="port" ng-model="settings.port" ng-disabled="portDisabled" placeholder="Port">
</div>
</div>
</div>
<label class="control-label" for="password">WeeChat relay password</label>
<input type="password" class="form-control favorite-font" id="password" ng-model="password" placeholder="Password">
<div class="alert alert-danger" ng-show="passwordError" ng-cloak>
Error: wrong password
<div class="row no-gutter">
<div ng-class="settings.useTotp ? 'col-sm-9' : 'col-sm-12'" ng>
<label class="control-label" for="password">WeeChat relay password</label>
<input type="password" class="form-control favorite-font" id="password" ng-model="password" placeholder="Password">
</div>
<div class="col-sm-3" ng-Show="settings.useTotp">
<label class="control-label" for="totp">Token</label>
<input type="text" class="form-control favorite-font" id="totp" ng-model="totp" ng-change="parseTotp()" ng-class="{'is-invalid': totpInvalid}" autocomplete="off">
</div>
</div>
<div class="alert alert-danger" ng-show="passwordError" ng-cloak>
Error: wrong password or token
</div>
<div class="checkbox">
<label class="control-label" for="savepassword">
<input type="checkbox" id="savepassword" ng-model="settings.savepassword">
Save password in your browser
</label>
</div>
<div class="checkbox" ng-show="settings.savepassword">
<label class="control-label" for="autoconnect">
<input type="checkbox" id="autoconnect" ng-model="settings.autoconnect">
Automatically connect
<div class="checkbox">
<label class="control-label" for="useTotp">
<input type="checkbox" id="useTotp" ng-model="settings.useTotp">
Use Time-based One-Time Password <a href="https://blog.weechat.org/post/2019/01/14/Support-of-TOTP" target="_blank"><i class="glyphicon glyphicon-info-sign"></i></a>
</label>
</div>
<div class="checkbox">
@ -135,8 +144,14 @@
Encryption. <strong>Strongly recommended!</strong> Need help? Check below.
</label>
</div>
<div class="checkbox" ng-show="settings.savepassword">
<label class="control-label" for="autoconnect">
<input type="checkbox" id="autoconnect" ng-model="settings.autoconnect" ng-disabled="settings.useTotp">
Automatically connect
</label>
</div>
</div>
<button class="btn btn-lg btn-primary" ng-disabled="hostInvalid" ng-click="connect()" ng-cloak>{{ connectbutton }} <i ng-class="connectbuttonicon" class="glyphicon"></i></button>
<button class="btn btn-lg btn-primary" ng-disabled="hostInvalid || (totpInvalid && settings.useTotp)" ng-click="connect()" ng-cloak>{{ connectbutton }} <i ng-class="connectbuttonicon" class="glyphicon"></i></button>
</form>
</div>
</div>
@ -151,6 +166,7 @@
</div>
<div id="collapseTwo" class="panel-collapse collapse">
<div class="panel-body">
<h3>Use TLS encryption</h3>
<p><span class="label label-danger">WeeChat version 0.4.2 or higher is required—we recommend at least 1.0.</p>
<p>To start using Glowing Bear, follow the instructions below to set up an encrypted relay. All communication goes directly between your browser and your WeeChat relay! This means that your server must be accessible. We never see any of your data or your password, and you don't need to trust a "cloud". All settings, including your password, are saved locally in your own browser between sessions.</p>
<div class="alert alert-warning" ng-show="show_tls_warning"><strong>You're using Glowing Bear over an unencrypted connection (http://). This is not recommended!</strong> We recommend using our secure hosted version at <a href="https://www.glowing-bear.org/">https://www.glowing-bear.org/</a>, or <a href="https://latest.glowing-bear.org/">https://latest.glowing-bear.org</a> for the latest and greatest development version. You can still follow the instructions below to set up an encrypted relay, though.</div>
@ -168,6 +184,11 @@ chown -R <strong>username</strong>:<strong>username</strong> ~<strong>username</
/relay add ssl.weechat {{ settings.port || 9001 }}
</pre>
<p>Your certificate needs to be renewed every couple of months. Either follow the instructions for automatic renewal at <a href="https://certbot.eff.org/">https://certbot.eff.org</a>, or run <code>certbot renew</code> manually when renewal is due. <strong>Important:</strong> You'll need to follow the instructions for copying the certificate to the right place again, and re-run <code>/relay sslcertkey</code> in WeeChat.</p>
<h3>Use TOTP (Time-based One-Time Password)</h3>
<p><a href="https://blog.weechat.org/post/2019/01/14/Support-of-TOTP">Configure</a> WeeChat for TOTP. The secret key has to be a base 32 string.</p>
<pre>/secure set relay_totp_secret xxxxx
/set relay.network.totp_secret "${sec.data.relay_totp_secret}"</pre>
<p>Open an authenticator app and create an entry with the same secret. In Glowing Bear check the checkbox for "use Time-based One-Time Password" and fill in the one time password as you see it in the authenticator app.</p>
</div>
</div>
</div>

View File

@ -20,7 +20,7 @@ weechat.factory('connection',
var locked = false;
// Takes care of the connection and websocket hooks
var connect = function (host, port, path, passwd, ssl, noCompression, successCallback, failCallback) {
var connect = function (host, port, path, passwd, ssl, useTotp, totp, noCompression, successCallback, failCallback) {
$rootScope.passwordError = false;
connectionData = [host, port, path, passwd, ssl, noCompression];
var proto = ssl ? 'wss' : 'ws';
@ -45,7 +45,9 @@ weechat.factory('connection',
ngWebsockets.send(
weeChat.Protocol.formatInit({
password: passwd,
compression: noCompression ? 'off' : 'zlib'
compression: noCompression ? 'off' : 'zlib',
useTotp: useTotp,
totp: totp
})
);
@ -326,9 +328,16 @@ weechat.factory('connection',
};
var attemptReconnect = function (bufferId, timeout) {
// won't work if totp is mandatory
if (settings.useTotp)
{
$log.info('Not reconnecting because totp will be expired.');
return;
}
$log.info('Attempting to reconnect...');
var d = connectionData;
connect(d[0], d[1], d[2], d[3], d[4], function() {
connect(d[0], d[1], d[2], d[3], d[4], false, "", function() {
$rootScope.reconnecting = false;
// on success, update active buffer
models.setActiveBuffer(bufferId);

View File

@ -45,6 +45,7 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
'port': 9001,
'path': 'weechat',
'ssl': (window.location.protocol === "https:"),
'useTotp': false,
'savepassword': false,
'autoconnect': false,
'nonicklist': utils.isMobileUi(),
@ -687,6 +688,16 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
}
};
settings.addCallback('useTotp', function() {
if (settings.useTotp) {
settings.autoconnect = false;
}
});
$scope.parseTotp = function() {
$scope.totpInvalid = !/^\d{4,10}$/.test($scope.totp);
};
$scope.connect = function() {
notifications.requestNotificationPermission();
$rootScope.sslError = false;
@ -695,7 +706,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$rootScope.bufferBottom = true;
$scope.connectbutton = 'Connecting';
$scope.connectbuttonicon = 'glyphicon-refresh glyphicon-spin';
connection.connect(settings.host, settings.port, settings.path, $scope.password, settings.ssl);
connection.connect(settings.host, settings.port, settings.path, $scope.password, settings.ssl, settings.useTotp, $scope.totp);
$scope.totp = "";//clear for next time
};
$scope.disconnect = function() {

View File

@ -648,6 +648,9 @@
if (params.password !== null) {
keys.push('password=' + params.password);
}
if (params.useTotp) {
keys.push('totp=' + params.totp);
}
parts.push(keys.join(','));
return WeeChatProtocol._formatCmd(null, 'init', parts);