Hash user tokens, increase token entropy

Fixes #1934
This commit is contained in:
Pavel Djundik 2018-01-05 15:26:12 +02:00
parent b3702b0550
commit eac092e661
2 changed files with 41 additions and 10 deletions

View File

@ -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"] || "");

View File

@ -373,7 +373,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;
} }
@ -418,7 +418,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;
} }
@ -459,11 +459,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);
@ -495,8 +495,9 @@ function getClientConfiguration() {
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());
@ -548,11 +549,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