Merge pull request #1411 from thelounge/xpaw/refactor-auth
Refactor authentication flow
This commit is contained in:
commit
bd530552c2
@ -562,7 +562,7 @@ $(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
sidebar.on("click", "#sign-out", function() {
|
sidebar.on("click", "#sign-out", function() {
|
||||||
socket.emit("sign-out", storage.get("token"));
|
socket.emit("sign-out");
|
||||||
storage.remove("token");
|
storage.remove("token");
|
||||||
|
|
||||||
if (!socket.connected) {
|
if (!socket.connected) {
|
||||||
|
@ -300,13 +300,13 @@ Client.prototype.updateSession = function(token, ip, request) {
|
|||||||
const agent = UAParser(request.headers["user-agent"] || "");
|
const agent = UAParser(request.headers["user-agent"] || "");
|
||||||
let friendlyAgent = "";
|
let friendlyAgent = "";
|
||||||
|
|
||||||
if (agent.browser.name.length) {
|
if (agent.browser.name) {
|
||||||
friendlyAgent = `${agent.browser.name} ${agent.browser.major}`;
|
friendlyAgent = `${agent.browser.name} ${agent.browser.major}`;
|
||||||
} else {
|
} else {
|
||||||
friendlyAgent = "Unknown browser";
|
friendlyAgent = "Unknown browser";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agent.os.name.length) {
|
if (agent.os.name) {
|
||||||
friendlyAgent += ` on ${agent.os.name} ${agent.os.version}`;
|
friendlyAgent += ` on ${agent.os.name} ${agent.os.version}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
326
src/server.js
326
src/server.js
@ -100,9 +100,10 @@ in ${config.public ? "public" : "private"} mode`);
|
|||||||
|
|
||||||
sockets.on("connect", function(socket) {
|
sockets.on("connect", function(socket) {
|
||||||
if (config.public) {
|
if (config.public) {
|
||||||
auth.call(socket, {});
|
performAuthentication.call(socket, {});
|
||||||
} else {
|
} else {
|
||||||
init(socket);
|
socket.emit("auth", {success: true});
|
||||||
|
socket.on("auth", performAuthentication);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -173,129 +174,157 @@ function index(req, res, next) {
|
|||||||
res.render("index", data);
|
res.render("index", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(socket, client, generateToken) {
|
function initializeClient(socket, client, generateToken, token) {
|
||||||
if (!client) {
|
socket.emit("authorized");
|
||||||
socket.emit("auth", {success: true});
|
|
||||||
socket.on("auth", auth);
|
|
||||||
} else {
|
|
||||||
socket.emit("authorized");
|
|
||||||
|
|
||||||
client.ip = getClientIp(socket.request);
|
socket.on("disconnect", function() {
|
||||||
|
client.clientDetach(socket.id);
|
||||||
|
});
|
||||||
|
client.clientAttach(socket.id);
|
||||||
|
|
||||||
socket.on("disconnect", function() {
|
socket.on(
|
||||||
client.clientDetach(socket.id);
|
"input",
|
||||||
});
|
function(data) {
|
||||||
client.clientAttach(socket.id);
|
client.input(data);
|
||||||
|
|
||||||
socket.on(
|
|
||||||
"input",
|
|
||||||
function(data) {
|
|
||||||
client.input(data);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
socket.on(
|
|
||||||
"more",
|
|
||||||
function(data) {
|
|
||||||
client.more(data);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
socket.on(
|
|
||||||
"conn",
|
|
||||||
function(data) {
|
|
||||||
// prevent people from overriding webirc settings
|
|
||||||
data.ip = null;
|
|
||||||
data.hostname = null;
|
|
||||||
client.connect(data);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!Helper.config.public && !Helper.config.ldap.enable) {
|
|
||||||
socket.on(
|
|
||||||
"change-password",
|
|
||||||
function(data) {
|
|
||||||
var old = data.old_password;
|
|
||||||
var p1 = data.new_password;
|
|
||||||
var p2 = data.verify_password;
|
|
||||||
if (typeof p1 === "undefined" || p1 === "") {
|
|
||||||
socket.emit("change-password", {
|
|
||||||
error: "Please enter a new password"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (p1 !== p2) {
|
|
||||||
socket.emit("change-password", {
|
|
||||||
error: "Both new password fields must match"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.password
|
|
||||||
.compare(old || "", client.config.password)
|
|
||||||
.then((matching) => {
|
|
||||||
if (!matching) {
|
|
||||||
socket.emit("change-password", {
|
|
||||||
error: "The current password field does not match your account password"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const hash = Helper.password.hash(p1);
|
|
||||||
|
|
||||||
client.setPassword(hash, (success) => {
|
|
||||||
const obj = {};
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
obj.success = "Successfully updated your password";
|
|
||||||
} else {
|
|
||||||
obj.error = "Failed to update your password";
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.emit("change-password", obj);
|
|
||||||
});
|
|
||||||
}).catch((error) => {
|
|
||||||
log.error(`Error while checking users password. Error: ${error}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
socket.on(
|
||||||
|
"more",
|
||||||
|
function(data) {
|
||||||
|
client.more(data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
socket.on(
|
||||||
|
"conn",
|
||||||
|
function(data) {
|
||||||
|
// prevent people from overriding webirc settings
|
||||||
|
data.ip = null;
|
||||||
|
data.hostname = null;
|
||||||
|
|
||||||
|
client.connect(data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Helper.config.public && !Helper.config.ldap.enable) {
|
||||||
socket.on(
|
socket.on(
|
||||||
"open",
|
"change-password",
|
||||||
function(data) {
|
function(data) {
|
||||||
client.open(socket.id, data);
|
var old = data.old_password;
|
||||||
}
|
var p1 = data.new_password;
|
||||||
);
|
var p2 = data.verify_password;
|
||||||
socket.on(
|
if (typeof p1 === "undefined" || p1 === "") {
|
||||||
"sort",
|
socket.emit("change-password", {
|
||||||
function(data) {
|
error: "Please enter a new password"
|
||||||
client.sort(data);
|
});
|
||||||
}
|
return;
|
||||||
);
|
}
|
||||||
socket.on(
|
if (p1 !== p2) {
|
||||||
"names",
|
socket.emit("change-password", {
|
||||||
function(data) {
|
error: "Both new password fields must match"
|
||||||
client.names(data);
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.password
|
||||||
|
.compare(old || "", client.config.password)
|
||||||
|
.then((matching) => {
|
||||||
|
if (!matching) {
|
||||||
|
socket.emit("change-password", {
|
||||||
|
error: "The current password field does not match your account password"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const hash = Helper.password.hash(p1);
|
||||||
|
|
||||||
|
client.setPassword(hash, (success) => {
|
||||||
|
const obj = {};
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
obj.success = "Successfully updated your password";
|
||||||
|
} else {
|
||||||
|
obj.error = "Failed to update your password";
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit("change-password", obj);
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
log.error(`Error while checking users password. Error: ${error}`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
socket.on("msg:preview:toggle", function(data) {
|
socket.on(
|
||||||
const networkAndChan = client.find(data.target);
|
"open",
|
||||||
if (!networkAndChan) {
|
function(data) {
|
||||||
return;
|
client.open(socket.id, data);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const message = networkAndChan.chan.findMessage(data.msgId);
|
socket.on(
|
||||||
|
"sort",
|
||||||
|
function(data) {
|
||||||
|
client.sort(data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (!message) {
|
socket.on(
|
||||||
return;
|
"names",
|
||||||
}
|
function(data) {
|
||||||
|
client.names(data);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const preview = message.findPreview(data.link);
|
socket.on("msg:preview:toggle", function(data) {
|
||||||
|
const networkAndChan = client.find(data.target);
|
||||||
|
if (!networkAndChan) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (preview) {
|
const message = networkAndChan.chan.findMessage(data.msgId);
|
||||||
preview.shown = data.shown;
|
|
||||||
|
if (!message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const preview = message.findPreview(data.link);
|
||||||
|
|
||||||
|
if (preview) {
|
||||||
|
preview.shown = data.shown;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("sign-out", () => {
|
||||||
|
delete client.config.sessions[token];
|
||||||
|
|
||||||
|
client.manager.updateUser(client.name, {
|
||||||
|
sessions: client.config.sessions
|
||||||
|
}, (err) => {
|
||||||
|
if (err) {
|
||||||
|
log.error("Failed to update sessions for", client.name, err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("sign-out", (token) => {
|
socket.emit("sign-out");
|
||||||
delete client.config.sessions[token];
|
});
|
||||||
|
|
||||||
|
socket.join(client.id);
|
||||||
|
|
||||||
|
const sendInitEvent = (tokenToSend) => {
|
||||||
|
socket.emit("init", {
|
||||||
|
active: client.lastActiveChannel,
|
||||||
|
networks: client.networks,
|
||||||
|
token: tokenToSend
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (generateToken) {
|
||||||
|
client.generateToken((newToken) => {
|
||||||
|
token = newToken;
|
||||||
|
|
||||||
|
client.updateSession(token, getClientIp(socket.request), socket.request);
|
||||||
|
|
||||||
client.manager.updateUser(client.name, {
|
client.manager.updateUser(client.name, {
|
||||||
sessions: client.config.sessions
|
sessions: client.config.sessions
|
||||||
@ -305,53 +334,13 @@ function init(socket, client, generateToken) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit("sign-out");
|
sendInitEvent(token);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
socket.join(client.id);
|
sendInitEvent(null);
|
||||||
|
|
||||||
const sendInitEvent = (token) => {
|
|
||||||
socket.emit("init", {
|
|
||||||
active: client.lastActiveChannel,
|
|
||||||
networks: client.networks,
|
|
||||||
token: token
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (generateToken) {
|
|
||||||
client.generateToken((token) => {
|
|
||||||
client.updateSession(token, getClientIp(socket.request), socket.request);
|
|
||||||
|
|
||||||
client.manager.updateUser(client.name, {
|
|
||||||
sessions: client.config.sessions
|
|
||||||
}, (err) => {
|
|
||||||
if (err) {
|
|
||||||
log.error("Failed to update sessions for", client.name, err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sendInitEvent(token);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
sendInitEvent(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reverseDnsLookup(socket, client) {
|
|
||||||
client.ip = getClientIp(socket.request);
|
|
||||||
|
|
||||||
dns.reverse(client.ip, function(err, host) {
|
|
||||||
if (!err && host.length) {
|
|
||||||
client.hostname = host[0];
|
|
||||||
} else {
|
|
||||||
client.hostname = client.ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
init(socket, client);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function localAuth(client, user, password, callback) {
|
function localAuth(client, user, password, callback) {
|
||||||
// If no user is found, or if the client has not provided a password,
|
// If no user is found, or if the client has not provided a password,
|
||||||
// fail the authentication straight away
|
// fail the authentication straight away
|
||||||
@ -408,18 +397,25 @@ function ldapAuth(client, user, password, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function auth(data) {
|
function performAuthentication(data) {
|
||||||
const socket = this;
|
const socket = this;
|
||||||
let client;
|
let client;
|
||||||
|
|
||||||
|
const finalInit = () => initializeClient(socket, client, !!data.remember, data.token || null);
|
||||||
|
|
||||||
const initClient = () => {
|
const initClient = () => {
|
||||||
// If webirc is enabled and we do not know this users IP address,
|
client.ip = getClientIp(socket.request);
|
||||||
// perform reverse dns lookup
|
|
||||||
if (Helper.config.webirc !== null && !client.config.ip) {
|
// If webirc is enabled perform reverse dns lookup
|
||||||
reverseDnsLookup(socket, client);
|
if (Helper.config.webirc === null) {
|
||||||
} else {
|
return finalInit();
|
||||||
init(socket, client, data.remember === "on");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reverseDnsLookup(client.ip, (hostname) => {
|
||||||
|
client.hostname = hostname;
|
||||||
|
|
||||||
|
finalInit();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Helper.config.public) {
|
if (Helper.config.public) {
|
||||||
@ -470,3 +466,13 @@ function auth(data) {
|
|||||||
localAuth(client, data.user, data.password, authCallback);
|
localAuth(client, data.user, data.password, authCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reverseDnsLookup(ip, callback) {
|
||||||
|
dns.reverse(ip, (err, hostnames) => {
|
||||||
|
if (!err && hostnames.length) {
|
||||||
|
return callback(hostnames[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(ip);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user