Merge pull request #370 from thelounge/xpaw/persistent-token

Implement user token persistency
This commit is contained in:
Jérémie Astori 2016-06-16 02:13:35 -04:00 committed by GitHub
commit cfdcd405d5
5 changed files with 67 additions and 36 deletions

View File

@ -67,7 +67,7 @@
</div> </div>
<div class="col-xs-12"> <div class="col-xs-12">
<label class="remember"> <label class="remember">
<input type="checkbox" name="remember" checked> <input type="checkbox" name="remember" id="sign-in-remember" checked>
Stay signed in Stay signed in
</label> </label>
</div> </div>

View File

@ -129,6 +129,11 @@ $(function() {
feedback.hide(); feedback.hide();
}); });
} }
if (data.token && window.localStorage.getItem("token") !== null) {
window.localStorage.setItem("token", data.token);
}
passwordForm passwordForm
.find("input") .find("input")
.val("") .val("")
@ -163,8 +168,10 @@ $(function() {
} }
} }
if (data.token) { if (data.token && $("#sign-in-remember").is(":checked")) {
window.localStorage.setItem("token", data.token); window.localStorage.setItem("token", data.token);
} else {
window.localStorage.removeItem("token");
} }
$("body").removeClass("signed-out"); $("body").removeClass("signed-out");

View File

@ -64,10 +64,15 @@ function Client(manager, name, config) {
sockets: manager.sockets, sockets: manager.sockets,
manager: manager manager: manager
}); });
var client = this; var client = this;
crypto.randomBytes(48, function(err, buf) {
client.token = buf.toString("hex"); if (!client.config.token) {
}); client.updateToken(function() {
client.manager.updateUser(client.name, {token: client.config.token});
});
}
if (config) { if (config) {
var delay = 0; var delay = 0;
(config.networks || []).forEach(function(n) { (config.networks || []).forEach(function(n) {
@ -255,19 +260,36 @@ Client.prototype.connect = function(args) {
}); });
}; };
Client.prototype.setPassword = function(hash) { Client.prototype.updateToken = function(callback) {
var client = this; var client = this;
client.manager.updateUser(client.name, {password: hash});
// re-read the hash off disk to ensure we use whatever is saved. this will crypto.randomBytes(48, function(err, buf) {
// prevent situations where the password failed to save properly and so client.config.token = buf.toString("hex");
// a restart of the server would forget the change and use the old callback();
// password again. });
var user = client.manager.readUserConfig(client.name); };
if (user.password === hash) {
client.config.password = hash; Client.prototype.setPassword = function(hash, callback) {
return true; var client = this;
}
return false; client.updateToken(function() {
client.manager.updateUser(client.name, {
token: client.config.token,
password: hash
});
// re-read the hash off disk to ensure we use whatever is saved. this will
// prevent situations where the password failed to save properly and so
// a restart of the server would forget the change and use the old
// password again.
var user = client.manager.readUserConfig(client.name);
if (user.password === hash) {
client.config.password = hash;
callback(true);
} else {
callback(false);
}
});
}; };
Client.prototype.input = function(data) { Client.prototype.input = function(data) {

View File

@ -23,6 +23,7 @@ program
return; return;
} }
user.password = bcrypt.hashSync(password, bcrypt.genSaltSync(8)); user.password = bcrypt.hashSync(password, bcrypt.genSaltSync(8));
user.token = null; // Will be regenerated when the user is loaded
fs.writeFileSync( fs.writeFileSync(
file, file,
JSON.stringify(user, null, " ") JSON.stringify(user, null, " ")

View File

@ -109,7 +109,7 @@ function index(req, res, next) {
}); });
} }
function init(socket, client, token) { function init(socket, client) {
if (!client) { if (!client) {
socket.emit("auth"); socket.emit("auth");
socket.on("auth", auth); socket.on("auth", auth);
@ -160,16 +160,21 @@ function init(socket, client, token) {
}); });
return; return;
} }
var salt = bcrypt.genSaltSync(8); var salt = bcrypt.genSaltSync(8);
var hash = bcrypt.hashSync(p1, salt); var hash = bcrypt.hashSync(p1, salt);
if (client.setPassword(hash)) {
socket.emit("change-password", { client.setPassword(hash, function(success) {
success: "Successfully updated your password" var obj = {};
});
return; if (success) {
} obj.success = "Successfully updated your password, all your other sessions were logged out";
socket.emit("change-password", { obj.token = client.config.token;
error: "Failed to update your password" } else {
obj.error = "Failed to update your password";
}
socket.emit("change-password", obj);
}); });
} }
); );
@ -196,12 +201,12 @@ function init(socket, client, token) {
socket.emit("init", { socket.emit("init", {
active: client.activeChannel, active: client.activeChannel,
networks: client.networks, networks: client.networks,
token: token || "" token: client.config.token
}); });
} }
} }
function reverseDnsLookup(socket, client, token) { function reverseDnsLookup(socket, client) {
client.ip = getClientIp(socket.request); client.ip = getClientIp(socket.request);
dns.reverse(client.ip, function(err, host) { dns.reverse(client.ip, function(err, host) {
@ -211,7 +216,7 @@ function reverseDnsLookup(socket, client, token) {
client.hostname = client.ip; client.hostname = client.ip;
} }
init(socket, client, token); init(socket, client);
}); });
} }
@ -233,7 +238,7 @@ function auth(data) {
var success = false; var success = false;
_.each(manager.clients, function(client) { _.each(manager.clients, function(client) {
if (data.token) { if (data.token) {
if (data.token === client.token) { if (data.token === client.config.token) {
success = true; success = true;
} }
} else if (client.config.user === data.user) { } else if (client.config.user === data.user) {
@ -242,14 +247,10 @@ function auth(data) {
} }
} }
if (success) { if (success) {
var token;
if (data.remember || data.token) {
token = client.token;
}
if (config.webirc !== null && !client.config["ip"]) { if (config.webirc !== null && !client.config["ip"]) {
reverseDnsLookup(socket, client, token); reverseDnsLookup(socket, client);
} else { } else {
init(socket, client, token); init(socket, client);
} }
return false; return false;
} }