-
Notifications
You must be signed in to change notification settings - Fork 1
/
basicauth.js
160 lines (124 loc) · 4.75 KB
/
basicauth.js
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
'use strict';
const chalk = require('chalk');
require('console-stamp')(console, {
format: ':date(yyyy-mm-dd HH:MM:ss.l)::label:'
});
const fs = require('fs');
const crypto = require('crypto');
const {safetypeof} = require("./gyutil.js");
const gyconfig = require('./gyconfig.js').getGlobalConfig();
const jwt = require('./jwtauth.js');
const MAX_USERS = 4096;
let gusermap;
function basicInit()
{
if (!gyconfig.userPassFile) {
throw new Error('Basic authentication method set but no User Password File (userPassFile) specified in global config');
}
try {
const userpass = fs.readFileSync(gyconfig.userPassFile);
if (!userpass || userpass.length === 0) {
throw new Error(`Empty Basic authentication User Password File : ${gyconfig.userPassFile} : Please provide a valid file.`);
}
let tarr;
try {
tarr = JSON.parse(userpass);
}
catch(e) {
throw new Error(`Basic authentication User Password file ${gyconfig.userPassFile} not in JSON format - Please specify the config file in JSON format : ${e}`);
}
if (!Array.isArray(tarr)) {
throw new Error(`Basic authentication User Password file ${gyconfig.userPassFile} not a JSON Array - Please specify the config file in a JSON Array format`);
}
if (tarr.length === 0) {
throw new Error(`Basic authentication User Password file ${gyconfig.userPassFile} is an empty JSON Array - Please specify valid objects in the JSON Array`);
}
else if (tarr.length > MAX_USERS) {
throw new Error(`Basic authentication User Password file ${gyconfig.userPassFile} Array has too many elements ${tarr.length} - Please specify max ${MAX_USERS} objects in the JSON Array`);
}
const tmap = new Map();
for (let obj of tarr) {
if (safetypeof(obj) !== 'object') {
throw new Error(`Basic authentication User Passwod file ${gyconfig.userPassFile} JSON Array element not of object format...`);
}
if ((!obj.user) || (!obj.password && !obj.pass_sha256)) {
throw new Error(`Basic authentication User Passwod file ${gyconfig.userPassFile} JSON Array element does not have mandatory property 'user' or either of 'password' or 'pass_sha256'`);
}
const p = obj.password ? obj.password : obj.pass_sha256;
const type = obj.password ? 'password' : 'pass_sha256';
if ((typeof obj.user !== 'string') || (typeof p !== 'string')) {
throw new Error(`Basic authentication User Passwod file ${gyconfig.userPassFile} JSON Array element does not have mandatory property in string format : 'user' or either of 'password' or 'pass_sha256'`);
}
let role;
if (obj.role) {
if (Array.isArray(obj.role)) {
role = obj.role;
}
else if (typeof obj.role === 'string') {
role = [ obj.role ];
}
else {
role = [ 'readonly' ];
}
}
else {
role = [ 'readonly' ];
}
tmap.set(obj.user, { pass : p, type, role });
}
gusermap = tmap;
console.log(`Basic User Password Authentication specified : Total of ${gusermap.size} entries specified`);
}
catch(e) {
throw new Error(`Exception caught while reading Basic User Password authentication config from ${gyconfig.userPassFile} : ${e}`);
}
}
function handleBasicAuth(req, res)
{
try {
if ((typeof req.body.username !== 'string') || (typeof req.body.password !== 'string')) {
res.status(400).end(JSON.stringify({status : 'failed', error : 400, errmsg : 'Missing username or password fields' }));
return;
}
if (!gusermap) {
res.status(500).end(JSON.stringify({status : 'failed', error : 500, errmsg : 'User Password Mapping not set yet!' }));
return;
}
const uobj = gusermap.get(req.body.username);
let pass;
if (!uobj) {
res.status(401).end(JSON.stringify({status : 'failed', error : 401, errmsg : 'Invalid Username or Password' }));
return;
}
if (uobj.type !== 'pass_sha256') {
pass = req.body.password;
}
else {
pass = crypto.createHash('sha256').update(req.body.password).digest('hex');
}
if (uobj.pass !== pass) {
res.status(401).end(JSON.stringify({status : 'failed', error : 401, errmsg : 'Invalid Username or Password' }));
return;
}
jwt.createJwt({ user : req.body.username, role : uobj.role })
.then(token => {
return res.status(200).end(JSON.stringify({
status : 'ok',
user : req.body.username,
effrole : jwt.getEffectiveRole(uobj.role),
token : token,
}));
})
.catch(error => {
return res.status(500).end(JSON.stringify({status : 'failed', error : 500, errmsg : error}));
});
}
catch(e) {
console.error(`Exception caught while authentcating User Password : ${e}`);
return res.status(500).end(JSON.stringify({status : 'failed', error : 500, errmsg : 'Exception caught while authenticating'}));
}
}
module.exports = {
basicInit,
handleBasicAuth,
};