forked from openiap/opencore
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode-red-contrib-middleware-auth.ts
More file actions
107 lines (102 loc) · 5.21 KB
/
Copy pathnode-red-contrib-middleware-auth.ts
File metadata and controls
107 lines (102 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import * as express from "express";
import { Config } from "./Config";
import { Logger } from "./Logger";
import { NoderedUtil, TokenUser, WebSocketClient } from "@openiap/openflow-api";
interface HashTable<T> {
[key: string]: T;
}
export class CachedUser {
public firstsignin: Date;
constructor(
public user: any,
public jwt: string
) {
this.firstsignin = new Date();
}
}
export class noderedcontribmiddlewareauth {
public static authorizationCache: HashTable<CachedUser> = {};
private static getUser(authorization: string): CachedUser {
const res: CachedUser = this.authorizationCache[authorization];
if (res === null || res === undefined) return null;
const begin: number = res.firstsignin.getTime();
const end: number = new Date().getTime();
const seconds = Math.round((end - begin) / 1000);
if (seconds < Config.api_credential_cache_seconds) { return res; }
delete this.authorizationCache[authorization];
return null;
}
public static async process(socket: WebSocketClient, req: express.Request, res: express.Response, next: express.NextFunction): Promise<void> {
if (Config.api_allow_anonymous) {
return next();
}
const authorization: string = req.headers.authorization;
let cacheduser: CachedUser = this.getUser(authorization);
if (cacheduser != null) {
req.user = cacheduser.user;
(req.user as any).jwt = cacheduser.jwt;
return next();
}
if (!NoderedUtil.IsNullEmpty(authorization) && authorization.indexOf(" ") > 1 &&
(authorization.toLocaleLowerCase().startsWith("bearer") || authorization.toLocaleLowerCase().startsWith("jwt"))) {
const token = authorization.split(" ")[1];
try {
let result = await NoderedUtil.SigninWithToken({ jwt: token, validate_only: true });
if (result == null || result.user == null) result = await NoderedUtil.SigninWithToken({ rawAssertion: token, validate_only: true });
if (result.user != null) {
const user: TokenUser = TokenUser.assign(result.user);
const allowed = user.roles.filter(x => x.name == "nodered api users" || x.name == Config.noderedadmins || x.name == Config.noderedapiusers);
if (allowed.length > 0 && !NoderedUtil.IsNullEmpty(allowed[0].name)) {
cacheduser = new CachedUser(result.user, result.jwt);
this.authorizationCache[authorization] = cacheduser;
Logger.instanse.info("noderedcontribmiddlewareauth: Authorized " + user.username + " for " + req.url);
req.user = cacheduser.user;
(req.user as any).jwt = cacheduser.jwt;
return next();
} else {
console.warn("noderedcontribmiddlewareauth: " + user.username + " is not member of 'nodered api users' for " + req.url);
}
}
} catch (error) {
console.error(error);
return;
}
res.statusCode = 401;
res.end('Unauthorized');
return;
}
// parse login and password from headers
const b64auth = (authorization || '').split(' ')[1] || ''
// const [login, password] = new Buffer(b64auth, 'base64').toString().split(':')
const [login, password] = Buffer.from(b64auth, "base64").toString().split(':')
if (login && password) {
try {
const result = await NoderedUtil.SigninWithUsername({ username: login, password, validate_only: true });
if (result.user != null) {
const user: TokenUser = TokenUser.assign(result.user);
const allowed = user.roles.filter(x => x.name == "nodered api users" || x.name == Config.noderedadmins || x.name == Config.noderedapiusers);
if (allowed.length > 0 && !NoderedUtil.IsNullEmpty(allowed[0].name)) {
cacheduser = new CachedUser(result.user, result.jwt);
this.authorizationCache[authorization] = cacheduser;
Logger.instanse.info("noderedcontribmiddlewareauth: Authorized " + user.username + " for " + req.url);
req.user = cacheduser.user;
(req.user as any).jwt = cacheduser.jwt;
return next();
} else {
console.warn("noderedcontribmiddlewareauth: " + user.username + " is not member of 'nodered api users' for " + req.url);
}
} else {
console.warn("noderedcontribmiddlewareauth: failed locating user for " + req.url);
}
} catch (error) {
console.error(error);
}
} else {
Logger.instanse.warn("noderedcontribmiddlewareauth: Unauthorized, no username/password for " + req.url);
}
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="OpenFlow"');
res.end('Unauthorized');
// next();
}
}