-
Notifications
You must be signed in to change notification settings - Fork 1k
/
nuveAuthenticator.js
100 lines (79 loc) · 2.91 KB
/
nuveAuthenticator.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
/* global require, exports */
const serviceRegistry = require('./../mdb/serviceRegistry');
const mauthParser = require('./mauthParser');
const logger = require('./../logger').logger;
// Logger
const log = logger.getLogger('NuveAuthenticator');
const cache = {};
const checkTimestamp = (ser, params) => {
const lastParams = cache[ser.name];
if (lastParams === undefined) {
return true;
}
const lastTS = lastParams.timestamp;
const newTS = params.timestamp;
const lastC = lastParams.cnonce;
const newC = params.cnonce;
if (newTS < lastTS || (lastTS === newTS && lastC === newC)) {
log.debug(`message: checkTimestamp lastTimestamp: ${lastTS}, newTimestamp: ${newTS
}, lastCnonce: ${lastC}, newCnonce: ${newC}`);
return false;
}
return true;
};
const checkSignature = (params, key) => {
if (params.signature_method !== 'HMAC_SHA1') {
return false;
}
const calculatedSignature = mauthParser.calculateClientSignature(params, key);
if (calculatedSignature !== params.signature) {
return false;
}
return true;
};
/*
* This function has the logic needed for authenticate a nuve request.
* If the authentication success exports the service and the user and role (if needed).
* Else send back a response with an authentication request to the client.
*/
exports.authenticate = (req, res, next) => {
const authHeader = req.header('Authorization');
const challengeReq = 'MAuth realm="http://marte3.dit.upm.es"';
let params;
if (authHeader !== undefined) {
params = mauthParser.parseHeader(authHeader);
// Get the service from the data base.
serviceRegistry.getService(params.serviceid, (serv) => {
if (serv === undefined || serv === null) {
log.info(`message: authenticate fail - unknown service, serviceId: ${
params.serviceid}`);
res.status(401).send({ 'WWW-Authenticate': challengeReq });
return;
}
const key = serv.key;
// Check if timestam and cnonce are valids in order to avoid duplicate requests.
if (!checkTimestamp(serv, params)) {
log.info('message: authenticate fail - Invalid timestamp or cnonce');
res.status(401).send({ 'WWW-Authenticate': challengeReq });
return;
}
// Check if the signature is valid.
if (checkSignature(params, key)) {
if (params.username !== undefined && params.role !== undefined) {
req.user = params.username;
req.role = params.role;
}
cache[serv.name] = params;
req.service = serv;
// If everything in the authentication is valid continue with the request.
next();
} else {
log.info('message: authenticate fail - wrong credentials');
res.status(401).send({ 'WWW-Authenticate': challengeReq });
}
});
} else {
log.info('message: authenticate fail - MAuth header not present');
res.status(401).send({ 'WWW-Authenticate': challengeReq });
}
};