Improved websocket auth when 2nd factor is used.
Ylian Saint-Hilaire committed
Mar 21, 2019 at 11:45 UTC
e8356b0dae859aaa7a33773e7fae94802d70ecc2
1 file changed
+64
-4
webserver.js
+64
-4
@@ -2507,9 +2507,26 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2507
if ((req.query.user != null) && (req.query.pass != null)) {
2508
// A user/pass is provided in URL arguments
2509
obj.authenticate(req.query.user, req.query.pass, domain, function (err, userid) {
2510
- if ((err == null) && (obj.users[userid])) {
2511
- // We are authenticated
2512
- func(ws, req, domain, obj.users[userid]);
2510
+ var user = obj.users[userid];
2511
+ if ((err == null) && (user)) {
2512
+ // Check if a 2nd factor is needed
2513
+ if (checkUserOneTimePasswordRequired(domain, user) == true) {
2514
+ if (req.query.token) {
2515
+ try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { }
2516
+ } else {
2517
+ checkUserOneTimePassword(req, domain, user, req.query.token, null, function (result) {
2518
+ if (result == false) {
2519
+ try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { }
2520
+ } else {
2521
+ // We are authenticated with 2nd factor.
2522
+ func(ws, req, domain, user);
2523
+ }
2524
+ });
2525
+ }
2526
+ } else {
2527
+ // We are authenticated
2528
+ func(ws, req, domain, user);
2529
+ }
2530
} else {
2531
// Failed to authenticate, see if a default user is active
2532
if (obj.args.user && obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) {
@@ -2529,12 +2546,55 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2546
if ((cookie != null) && (obj.users[cookie.userid]) && (cookie.domainid == domain.id)) {
2547
// Valid cookie, we are authenticated
2548
func(ws, req, domain, obj.users[cookie.userid], cookie);
2532
- return;
2549
} else {
2550
// This is a bad cookie, keep going anyway, maybe we have a active session that will save us.
2551
Debug(1, 'ERR: Websocket bad cookie auth: ' + req.query.auth);
2552
+ try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2' })); ws.close(); } catch (e) { }
2553
}
2554
+ return;
2555
+ } else if (req.headers['x-meshauth'] != null) {
2556
+ // This is authentication using a custom HTTP header
2557
+ var s = req.headers['x-meshauth'].split(',');
2558
+ for (var i in s) { s[i] = Buffer.from(s[i], 'base64').toString(); }
2559
+ if ((s.length < 2) || (s.length > 3)) { try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2' })); ws.close(); } catch (e) { } return; }
2560
+ obj.authenticate(s[0], s[1], domain, function (err, userid) {
2561
+ var user = obj.users[userid];
2562
+ if ((err == null) && (user)) {
2563
+ // Check if a 2nd factor is needed
2564
+ if (checkUserOneTimePasswordRequired(domain, user) == true) {
2565
+ if (s.length != 3) {
2566
+ try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { }
2567
+ } else {
2568
+ checkUserOneTimePassword(req, domain, user, s[2], null, function (result) {
2569
+ if (result == false) {
2570
+ try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { }
2571
+ } else {
2572
+ // We are authenticated with 2nd factor.
2573
+ func(ws, req, domain, user);
2574
+ }
2575
+ });
2576
+ }
2577
+ } else {
2578
+ // We are authenticated
2579
+ func(ws, req, domain, user);
2580
+ }
2581
+ } else {
2582
+ // Failed to authenticate, see if a default user is active
2583
+ if (obj.args.user && obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) {
2584
+ // A default user is active
2585
+ func(ws, req, domain, obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]);
2586
+ } else {
2587
+ // If not authenticated, close the websocket connection
2588
+ Debug(1, 'ERR: Websocket bad user/pass auth');
2589
+ try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2' })); ws.close(); } catch (e) { }
2590
+ }
2591
+ }
2592
+ });
2593
+ return;
2594
}
2595
+
2596
+ //console.log(req.headers['x-meshauth']);
2597
+
2598
if (obj.args.user && obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) {
2599
// A default user is active
2600
func(ws, req, domain, obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]);