mirror of
https://github.com/thelounge/thelounge
synced 2024-11-21 19:43:07 +00:00
Merge pull request #1940 from thelounge/xpaw/fix-1934
Hash user tokens, increase token entropy
This commit is contained in:
commit
98c3108bde
2 changed files with 41 additions and 10 deletions
|
@ -94,6 +94,27 @@ function Client(manager, name, config) {
|
||||||
|
|
||||||
if (typeof client.config.sessions !== "object") {
|
if (typeof client.config.sessions !== "object") {
|
||||||
client.config.sessions = {};
|
client.config.sessions = {};
|
||||||
|
} else {
|
||||||
|
// TODO: This is just for backwards compatibility. Remove in v3.0.0
|
||||||
|
const newSessions = {};
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
_.forOwn(client.config.sessions, (session, key) => {
|
||||||
|
if (key.length !== 128) {
|
||||||
|
key = client.calculateTokenHash(key);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
newSessions[key] = session;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
log.info(`User ${colors.bold(client.name)} has been updated with new security requirements for tokens.`);
|
||||||
|
|
||||||
|
delete client.config.token;
|
||||||
|
client.config.sessions = newSessions;
|
||||||
|
client.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_.forOwn(client.config.sessions, (session) => {
|
_.forOwn(client.config.sessions, (session) => {
|
||||||
|
@ -282,7 +303,7 @@ Client.prototype.connect = function(args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Client.prototype.generateToken = function(callback) {
|
Client.prototype.generateToken = function(callback) {
|
||||||
crypto.randomBytes(48, (err, buf) => {
|
crypto.randomBytes(64, (err, buf) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
@ -291,6 +312,10 @@ Client.prototype.generateToken = function(callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Client.prototype.calculateTokenHash = function(token) {
|
||||||
|
return crypto.createHash("sha512").update(token).digest("hex");
|
||||||
|
};
|
||||||
|
|
||||||
Client.prototype.updateSession = function(token, ip, request) {
|
Client.prototype.updateSession = function(token, ip, request) {
|
||||||
const client = this;
|
const client = this;
|
||||||
const agent = UAParser(request.headers["user-agent"] || "");
|
const agent = UAParser(request.headers["user-agent"] || "");
|
||||||
|
|
|
@ -389,7 +389,7 @@ function initializeClient(socket, client, token, lastMessage) {
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("push:register", (subscription) => {
|
socket.on("push:register", (subscription) => {
|
||||||
if (!client.isRegistered() || !client.config.sessions[token]) {
|
if (!client.isRegistered() || !client.config.sessions.hasOwnProperty(token)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +434,7 @@ function initializeClient(socket, client, token, lastMessage) {
|
||||||
tokenToSignOut = token;
|
tokenToSignOut = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(tokenToSignOut in client.config.sessions)) {
|
if (!client.config.sessions.hasOwnProperty(tokenToSignOut)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,11 +475,11 @@ function initializeClient(socket, client, token, lastMessage) {
|
||||||
|
|
||||||
if (!Helper.config.public && token === null) {
|
if (!Helper.config.public && token === null) {
|
||||||
client.generateToken((newToken) => {
|
client.generateToken((newToken) => {
|
||||||
client.attachedClients[socket.id].token = token = newToken;
|
client.attachedClients[socket.id].token = token = client.calculateTokenHash(newToken);
|
||||||
|
|
||||||
client.updateSession(token, getClientIp(socket), socket.request);
|
client.updateSession(token, getClientIp(socket), socket.request);
|
||||||
|
|
||||||
sendInitEvent(token);
|
sendInitEvent(newToken);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sendInitEvent(null);
|
sendInitEvent(null);
|
||||||
|
@ -519,8 +519,9 @@ function getServerConfiguration() {
|
||||||
function performAuthentication(data) {
|
function performAuthentication(data) {
|
||||||
const socket = this;
|
const socket = this;
|
||||||
let client;
|
let client;
|
||||||
|
let token = null;
|
||||||
|
|
||||||
const finalInit = () => initializeClient(socket, client, data.token || null, data.lastMessage || -1);
|
const finalInit = () => initializeClient(socket, client, token, data.lastMessage || -1);
|
||||||
|
|
||||||
const initClient = () => {
|
const initClient = () => {
|
||||||
socket.emit("configuration", getClientConfiguration());
|
socket.emit("configuration", getClientConfiguration());
|
||||||
|
@ -572,11 +573,16 @@ function performAuthentication(data) {
|
||||||
client = manager.findClient(data.user);
|
client = manager.findClient(data.user);
|
||||||
|
|
||||||
// We have found an existing user and client has provided a token
|
// We have found an existing user and client has provided a token
|
||||||
if (client && data.token && typeof client.config.sessions[data.token] !== "undefined") {
|
if (client && data.token) {
|
||||||
client.updateSession(data.token, getClientIp(socket), socket.request);
|
const providedToken = client.calculateTokenHash(data.token);
|
||||||
|
|
||||||
authCallback(true);
|
if (client.config.sessions.hasOwnProperty(providedToken)) {
|
||||||
return;
|
token = providedToken;
|
||||||
|
|
||||||
|
client.updateSession(providedToken, getClientIp(socket), socket.request);
|
||||||
|
|
||||||
|
return authCallback(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform password checking
|
// Perform password checking
|
||||||
|
|
Loading…
Reference in a new issue