Skip to content

Commit 303dda8

Browse files
committed
Improve disabled user token handling
1 parent 4aabd23 commit 303dda8

8 files changed

Lines changed: 58 additions & 45 deletions

File tree

OpenFlow/src/Config.ts

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ export class Config {
8383
public static db: DatabaseConnection = null;
8484
public static version: string = Config.getversion();
8585
public static logpath: string = Config.getEnv("logpath", __dirname);
86+
public static log_queries: boolean = Config.parseBoolean(Config.getEnv("log_queries", "false"));
87+
8688

8789
public static NODE_ENV: string = Config.getEnv("NODE_ENV", "development");
8890

@@ -123,10 +125,6 @@ export class Config {
123125
public static amqp_requeue_time: number = parseInt(Config.getEnv("amqp_requeue_time", "1000")); // 1 seconds
124126
public static amqp_dlx: string = Config.getEnv("amqp_dlx", "openflow-dlx"); // Dead letter exchange, used to pickup dead or timeout messages
125127

126-
// public static amqp_default_expiration: number = parseInt(Config.getEnv("amqp_default_expiration", (60 * 1000).toString())); // 1 min
127-
// public static deadLetterExchange: string = Config.getEnv("deadletterexchange", "openflow-dlx"); // queue used to handle messages, that was not picked up.
128-
// public static dlxmessagettl: number = parseInt(Config.getEnv("dlxmessagettl", "2000")); // time to live for messages in miliseconds
129-
// public static dlxmessageexpires: number = parseInt(Config.getEnv("dlxmessageexpires", "1500")); // expire messages after this amount of miliseconds
130128
public static mongodb_url: string = Config.getEnv("mongodb_url", "mongodb://localhost:27017");
131129
public static mongodb_db: string = Config.getEnv("mongodb_db", "openflow");
132130

@@ -142,23 +140,13 @@ export class Config {
142140
public static downloadtoken_expires_in: string = Config.getEnv("downloadtoken_expires_in", "15m");
143141
public static personalnoderedtoken_expires_in: string = Config.getEnv("personalnoderedtoken_expires_in", "365d");
144142

145-
// Used to configure personal nodered's
146-
// public static force_queue_prefix: boolean = Config.parseBoolean(Config.getEnv("force_queue_prefix", "true"));
147143
public static nodered_image: string = Config.getEnv("nodered_image", "cloudhack/openflownodered:edge");
148144
public static saml_federation_metadata: string = Config.getEnv("saml_federation_metadata", "");
149145
public static api_ws_url: string = Config.getEnv("api_ws_url", "ws://localhost:3000");
150146
public static namespace: string = Config.getEnv("namespace", ""); // also sent to website
151147
public static nodered_domain_schema: string = Config.getEnv("nodered_domain_schema", ""); // also sent to website
152148
public static nodered_initial_liveness_delay: number = parseInt(Config.getEnv("nodered_initial_liveness_delay", "60"));
153149

154-
// Environment variables to set a prefix for RabbitMQs Dead Letter Exchange, Dead Letter Routing Key,
155-
// Dead Letter Queue, and Message Time to Live - to enable timeouts for RabbitMQ messages
156-
// These values must be the same for OpenFlowNodeRED and OpenFlow, or will cause errors when asserting queues
157-
// public static amqp_dlx_prefix: string = Config.getEnv("amqp_dlx_prefix", "DLX.");
158-
// public static amqp_dlrk_prefix: string = Config.getEnv("amqp_dlrk_prefix", "dlx.");
159-
// public static amqp_dlq_prefix: string = Config.getEnv("amqp_dlq_prefix", "dlq.");
160-
// public static amqp_message_ttl: number = parseInt(Config.getEnv("amqp_message_ttl", "20000"));
161-
162150
public static baseurl(): string {
163151
var result: string = "";
164152
if (Config.tls_crt != '' && Config.tls_key != '') {
@@ -171,13 +159,6 @@ export class Config {
171159
} else { result = result + "/"; }
172160
return result;
173161
}
174-
// public static async get_login_providers():Promise<void> {
175-
// this.login_providers = await Config.db.query<Provider>({_type: "provider"}, null, 1, 0, null, "config", Crypt.rootToken());
176-
// // if(this.login_providers.length > 0) { return; }
177-
// if(fs.existsSync("config/login_providers.json")) {
178-
// // this.login_providers = JSON.parse(fs.readFileSync("config/login_providers.json", "utf8"));
179-
// }
180-
// }
181162
public static getEnv(name: string, defaultvalue: string): string {
182163
var value: any = process.env[name];
183164
if (!value || value === "") { value = defaultvalue; }

OpenFlow/src/DatabaseConnection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ export class DatabaseConnection {
350350
}
351351
for (var i: number = 0; i < arr.length; i++) { arr[i] = this.decryptentity(arr[i]); }
352352
DatabaseConnection.traversejsondecode(arr);
353-
this._logger.debug("[" + user.username + "][" + collectionname + "] query gave " + arr.length + " results ");
353+
if (Config.log_queries) this._logger.debug("[" + user.username + "][" + collectionname + "] query gave " + arr.length + " results ");
354354
return arr;
355355
}
356356
/**

OpenFlow/src/Messages/Message.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,28 @@ export class Message {
576576
}
577577
this.Send(cli);
578578
}
579-
579+
public static async DoSignin(cli: WebSocketServerClient, rawAssertion: string): Promise<TokenUser> {
580+
var tuser: TokenUser;
581+
var user: User;
582+
var type: string = "jwtsignin";
583+
if (!NoderedUtil.IsNullEmpty(rawAssertion)) {
584+
type = "samltoken";
585+
user = await LoginProvider.validateToken(rawAssertion);
586+
tuser = TokenUser.From(user);
587+
} else if (!NoderedUtil.IsNullEmpty(cli.jwt)) {
588+
tuser = Crypt.verityToken(cli.jwt);
589+
user = await DBHelper.FindByUsername(tuser.username);
590+
tuser = TokenUser.From(user);
591+
}
592+
if (user.disabled) {
593+
Audit.LoginFailed(tuser.username, type, "websocket", cli.remoteip, cli.clientagent, cli.clientversion);
594+
tuser = null;
595+
// cli._logger.debug("Disabled user " + tuser.username + " failed logging in using " + type);
596+
} else {
597+
Audit.LoginSuccess(tuser, type, "websocket", cli.remoteip, cli.clientagent, cli.clientversion);
598+
}
599+
return tuser;
600+
}
580601
private async Signin(cli: WebSocketServerClient): Promise<void> {
581602
this.Reply();
582603
var msg: SigninMessage

OpenFlow/src/WebSocketServer.ts

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { DatabaseConnection } from "./DatabaseConnection";
66
import { Crypt } from "./Crypt";
77
import { Message } from "./Messages/Message";
88
import { Config } from "./Config";
9-
import { SigninMessage, NoderedUtil } from "openflow-api";
9+
import { SigninMessage, NoderedUtil, TokenUser } from "openflow-api";
1010

1111
export class WebSocketServer {
1212
private static _logger: winston.Logger;
@@ -36,22 +36,26 @@ export class WebSocketServer {
3636
}
3737
private static async pingClients(): Promise<void> {
3838
let count: number = WebSocketServer._clients.length;
39-
WebSocketServer._clients = WebSocketServer._clients.filter(function (cli: WebSocketServerClient): boolean {
39+
for (var i = WebSocketServer._clients.length - 1; i >= 0; i--) {
40+
var cli: WebSocketServerClient = WebSocketServer._clients[i];
4041
try {
4142
if (!NoderedUtil.IsNullEmpty(cli.jwt)) {
42-
var tuser = Crypt.verityToken(cli.jwt);
4343
var payload = Crypt.decryptToken(cli.jwt);
4444
var clockTimestamp = Math.floor(Date.now() / 1000);
45-
// WebSocketServer._logger.silly((payload.exp - clockTimestamp))
4645
if ((payload.exp - clockTimestamp) < 60) {
47-
WebSocketServer._logger.debug("Token for " + tuser.username + " expires in less than 1 minute, send new jwt to client");
48-
var l: SigninMessage = new SigninMessage();
49-
cli.jwt = Crypt.createToken(tuser, Config.shorttoken_expires_in);
50-
l.jwt = cli.jwt;
51-
l.user = tuser;
52-
var m: Message = new Message(); m.command = "refreshtoken";
53-
m.data = JSON.stringify(l);
54-
cli.Send(m);
46+
WebSocketServer._logger.debug("Token for " + cli.id + "/" + cli.user.name + "/" + cli.clientagent + " expires in less than 1 minute, send new jwt to client");
47+
var tuser: TokenUser = await Message.DoSignin(cli, null);
48+
if (tuser != null) {
49+
var l: SigninMessage = new SigninMessage();
50+
cli.jwt = Crypt.createToken(tuser, Config.shorttoken_expires_in);
51+
l.jwt = cli.jwt;
52+
l.user = tuser;
53+
var m: Message = new Message(); m.command = "refreshtoken";
54+
m.data = JSON.stringify(l);
55+
cli.Send(m);
56+
} else {
57+
cli.Close();
58+
}
5559
}
5660
}
5761
} catch (error) {
@@ -62,17 +66,22 @@ export class WebSocketServer {
6266
var seconds = (now.getTime() - cli.lastheartbeat.getTime()) / 1000;
6367
if (seconds >= Config.client_heartbeat_timeout) {
6468
if (cli.user != null) {
65-
WebSocketServer._logger.info("client " + cli.user.name + "/" + cli.clientagent + " timeout, close down");
69+
WebSocketServer._logger.info("client " + cli.id + "/" + cli.user.name + "/" + cli.clientagent + " timeout, close down");
6670
} else {
67-
WebSocketServer._logger.info("client not signed/" + cli.clientagent + " timeout, close down");
71+
WebSocketServer._logger.info("client not signed/" + cli.id + "/" + cli.clientagent + " timeout, close down");
6872
}
6973
cli.Close();
70-
return false;
7174
}
7275
cli.ping();
73-
if (!cli.connected() && cli.queuecount() == 0) return false;
74-
return true;
75-
});
76+
if (!cli.connected() && cli.queuecount() == 0) {
77+
if (cli.user != null) {
78+
WebSocketServer._logger.info("removing disconnected client " + cli.id + "/" + cli.user.name + "/" + cli.clientagent);
79+
} else {
80+
WebSocketServer._logger.info("removing disconnected client " + cli.id + "/" + cli.clientagent + " timeout, close down");
81+
}
82+
WebSocketServer._clients.splice(i, 1);
83+
}
84+
}
7685
if (count !== WebSocketServer._clients.length) {
7786
WebSocketServer._logger.info("new client count: " + WebSocketServer._clients.length);
7887
}

OpenFlow/src/WebSocketServerClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class WebSocketServerClient {
4646
if ((socketObject as any)._socket != undefined) {
4747
this.remoteip = (socketObject as any)._socket.remoteAddress;
4848
}
49-
logger.info("new client ");;
49+
logger.info("new client " + this.id);;
5050
socketObject.on("open", (e: Event): void => this.open(e));
5151
socketObject.on("message", (e: string): void => this.message(e)); // e: MessageEvent
5252
socketObject.on("error", (e: Event): void => this.error(e));

OpenFlow/src/public/WebSocketClientService.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export class WebSocketClientService {
8686
console.log(error);
8787
try {
8888
document.write(error);
89+
document.write("<br/><a href=\"/Signout\">Signout</a>");
8990
} catch (error) {
9091

9192
}
@@ -126,7 +127,8 @@ export class WebSocketClientService {
126127
info(msg) { console.log(msg); },
127128
verbose(msg) { console.debug(msg); },
128129
error(msg) { console.error(msg); },
129-
debug(msg) { console.debug(msg); }
130+
debug(msg) { console.debug(msg); },
131+
silly(msg) { console.debug(msg); }
130132
}
131133
public user: TokenUser = null;
132134
public jwt: string = null;

OpenFlowNodeRED/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"morgan": "^1.10.0",
3838
"node-red": "^1.1.2",
3939
"node-red-node-email": "^1.7.8",
40-
"openflow-api": "^1.0.16",
40+
"openflow-api": "^1.0.17",
4141
"os-service": "^2.2.0",
4242
"passport-saml": "^1.3.4",
4343
"passport-saml-metadata": "^2.3.0",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"morgan": "^1.10.0",
5959
"multer": "^1.4.2",
6060
"multer-gridfs-storage": "^4.2.0",
61-
"openflow-api": "^1.0.16",
61+
"openflow-api": "^1.0.17",
6262
"os-service": "^2.2.0",
6363
"passport": "^0.4.1",
6464
"passport-google-oauth20": "^2.0.0",

0 commit comments

Comments
 (0)