-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
150 lines (129 loc) · 4.71 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
const { getBootstrapConfig } = require('./helpers/config');
const { handleInternalError } = require('./helpers/errors');
const jwt = require('./helpers/jwt');
const modules = require('./modules');
const authentication = require('./lib/authentication');
const jsonwebtoken = require('jsonwebtoken');
const checkAuthentication = (config, res, token, ctx, cb) => {
console.log("checking authentication...")
const decryptTokenWithKeys = authentication.decryptTokenWithKeys.bind(undefined, token);
module.exports.__getPublicKeys()
.then(decryptTokenWithKeys)
.then(function (decryptedToken) {
let validAudience = module.exports.__verifyAudience(decryptedToken);
if (!validAudience) {
console.log("WrongAudienceError: Token's audience did not match any for this function.");
throw new authentication.WrongAudienceError(`Token's audience ${decryptedToken.aud} did not match any for this function.`); //
}
ctx.originalToken = token;
ctx.token = decryptedToken;
modules.install(ctx);
console.log("authentication successful");
cb(null, ctx);
})
.catch(function (e) {
let message = "Authentication Error: An unexpected error has occurred, please contact [email protected]";
let statusCode = 500;
if (e instanceof jsonwebtoken.JsonWebTokenError) {
// Can probably even make this more specific, however should be good for now.
message = 'Authentication Error: Could not decrypt token with any of the public keys, please contact [email protected]';
statusCode = 401;
}
if (e instanceof authentication.WrongAudienceError) {
message = 'Authentication Error: ' + e.message;
statusCode = 401;
}
console.log(message);
if (process.env.DEV === 'true' && e.stack) {
console.log(e.stack);
}
if (config.authRequired) {
res.status(statusCode).send({
error: {
'message': message
}
});
// exit function early
return cb(new Error(message));
}
modules.install(ctx);
return cb(null, ctx);
});
};
module.exports = function bootstrap(handlerFactoryFunction) {
return (req, res) => {
wrapFunction(getBootstrapConfig(), req, res, (bootstrapError, ctx) => {
if (bootstrapError) {
return handleInternalError(res, bootstrapError);
}
handlerFactoryFunction(ctx)(req, res);
});
};
};
function wrapFunction(config, req, res, cb) {
if (config.authRequired !== false) {
// test for strict equality disable of auth.
config.authRequired = true;
}
let ctx = req.ctx = {};
if (config.mockToken) {
ctx.originalToken = '__change_in_handler__';
ctx.token = {};
}
config.cors = config.cors || {}; // config that gets passed in is always set by user
// will probably be a config yaml file
// Allow user to add headers here.
config.cors.headers = config.cors.headers || [];
// Combine user headers with our own defaults
const corsHeaders = ['Content-Type', 'Authorization'];
config.cors.headers.forEach((header) => {
if (corsHeaders.indexOf(header) === -1) {
corsHeaders.push(header);
}
});
// Set CORS up.
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Headers', corsHeaders.join(', '));
res.set('Access-Control-Allow-Credential', true);
res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
// IF Method is OPTIONS we want to return after setting headers
// @TODO may want to put this behind a disable flag
if (req.method === 'OPTIONS') {
res.status(200).send();
return;
}
let token;
try {
token = jwt.parse(req);
console.log("jwt successfully parsed");
} catch (e) {
if (config.authRequired && !ignoreAuthForRoute(config, req.path)) {
console.log("authentication is required and failed to successfully parse jwt");
res.status(401).send({
error: {
'message': 'Could not find user credentials.'
}
});
return cb(e);
}
modules.install(ctx);
return cb(null, ctx);
}
checkAuthentication(config, res, token, ctx, cb);
}
const ignoreAuthForRoute = (config, route) => {
if (config.ignoreAuthRoutes && config.ignoreAuthRoutes.length > 0) {
return config.ignoreAuthRoutes.includes(route);
}
return false;
};
const getPublicKeys = () => {
return authentication.getPublicKeys();
};
const verifyAudience = (decryptedToken) => {
return authentication.verifyAudience(decryptedToken);
};
module.exports.__checkAuthentication = checkAuthentication;
module.exports.__ignoreAuthForRoute = ignoreAuthForRoute;
module.exports.__getPublicKeys = getPublicKeys;
module.exports.__verifyAudience = verifyAudience;