-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
126 lines (123 loc) · 4.32 KB
/
index.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
var jwt = require('jsonwebtoken');
var KmsJwt = require('kms-jwt');
var winston = require('winston')
var bbjwtLogger = winston.createLogger({
transports: new winston.transports.Console({
format: new winston.format.simple()
}),
level: 'info'
});
var kmsJwt = null;
var getKmsJwt = () => {
if (!kmsJwt) {
kmsJwt = new KmsJwt({
signingKey: process.env.SIGNING_KEY
});
}
return kmsJwt;
};
module.exports = {
/**
* Gets a client id from a token, checks both KMS type and v1 type tokens
* Calls callback with (null, clientId) if possible
* @param {*} jwt { string | object} jwt to decode
* @param {*} callback {(err: any, clientId: string) => any}
*/
getClientIdFromToken: function(jwt, callback) {
var self = this;
if (typeof jwt === 'string') {
self.decodeToken(jwt, (err, data) => {
if(err) {
callback(err, null);
} else {
self.getClientIdFromToken(data, callback)
}
});
} else if(jwt && jwt.hasOwnProperty('bbcid')) {
callback(null, jwt.bbcid)
} else if(jwt && jwt.hasOwnProperty('clientId')) {
callback(null, jwt.clientId)
} else {
callback('JWT : Error retrieving clientId, token undefined/missing data?', null);
}
},
/**
* Decodes a token, first trying kms, then v1 token.
* Callback is called with decoded token.
* @param {*} token {string} token to decode
* @param {*} callback {(err: any, decodedToken: {}) => any}
*/
decodeToken: function(token, callback) {
var decoded = false;
// strip Bearer from prefix
if (token && token.indexOf(' ') > -1) {
token = token.split(' ')[1];
}
var self = this;
self.decodeWithKms(token, (err, decodedToken) => {
if(!err && decodedToken) {
callback(null, decodedToken);
} else {
bbjwtLogger.debug('kms token decoding failed, attempt v1 token decode', { kmsError: err.toString() });
try {
decoded = self.decodeV1Token(token);
if (decoded) {
callback(null, decoded);
} else {
throw new Error('decodeV1Token failed');
}
} catch(exception) {
if (err) {
bbjwtLogger.warn('both kms and v1 token decoding failed', { kmsError: err.toString(), v1Error: exception.toString() })
} else {
bbjwtLogger.warn('v1 token decoding failed', { v1Error: exception.toString() });
}
callback(exception, decoded);
}
}
});
},
/**
* Attempts to decode V1 token.
* @param {*} token {string}
* @returns {false|object} Returns decoded token from jsonwebtoken.verify or false if token expired
*/
decodeV1Token: function(token) {
var decoded = jwt.verify(token, process.env.JWT_SECRET);
if (!decoded.hasOwnProperty('expires') || decoded.expires < Date.now()/1000) {
bbjwtLogger.info('jwt token expired failed', { jwt: token });
return false;
}
return decoded;
},
/**
* Attempts to decode token using kms.
* Callback called with decoded token.
* @param {*} token {string} token to decode
* @param {*} callback
*/
decodeWithKms: function(token, callback) {
try {
var kj = getKmsJwt();
kj.verify(token, (err, decoded) => {
if (err) {
bbjwtLogger.debug('kms verify failed', { kmsError: err.toString() });
callback(err, null);
} else {
callback(null, decoded);
}
});
} catch(err) {
bbjwtLogger.warn('error occurred while trying to decode with kms', { kmsError: err.toString() });
callback(err, null)
}
},
/**
* Optionally sets a logger to better control communication.
* Must comply with winston logger api
* @param {*} lgr
*/
setLogger: function(lgr) {
bbjwtLogger = lgr;
}
};