forked from aws-samples/amazon-cloudfront-functions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
113 lines (91 loc) · 2.92 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
var crypto = require('crypto');
//Response when JWT is not valid.
var response401 = {
statusCode: 401,
statusDescription: 'Unauthorized'
};
function jwt_decode(token, key, noVerify, algorithm) {
// check token
if (!token) {
throw new Error('No token supplied');
}
// check segments
var segments = token.split('.');
if (segments.length !== 3) {
throw new Error('Not enough or too many segments');
}
// All segment should be base64
var headerSeg = segments[0];
var payloadSeg = segments[1];
var signatureSeg = segments[2];
// base64 decode and parse JSON
var header = JSON.parse(_base64urlDecode(headerSeg));
var payload = JSON.parse(_base64urlDecode(payloadSeg));
if (!noVerify) {
var signingMethod = 'sha256';
var signingType = 'hmac';
// Verify signature. `sign` will return base64 string.
var signingInput = [headerSeg, payloadSeg].join('.');
if (!_verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
throw new Error('Signature verification failed');
}
// Support for nbf and exp claims.
// According to the RFC, they should be in seconds.
if (payload.nbf && Date.now() < payload.nbf*1000) {
throw new Error('Token not yet active');
}
if (payload.exp && Date.now() > payload.exp*1000) {
throw new Error('Token expired');
}
}
return payload;
};
//Function to ensure a constant time comparison to prevent
//timing side channels.
function _constantTimeEquals(a, b) {
if (a.length != b.length) {
return false;
}
var xor = 0;
for (var i = 0; i < a.length; i++) {
xor |= (a.charCodeAt(i) ^ b.charCodeAt(i));
}
return 0 === xor;
}
function _verify(input, key, method, type, signature) {
if(type === "hmac") {
return _constantTimeEquals(signature, _sign(input, key, method));
}
else {
throw new Error('Algorithm type not recognized');
}
}
function _sign(input, key, method) {
return crypto.createHmac(method, key).update(input).digest('base64url');
}
function _base64urlDecode(str) {
return String.bytesFrom(str, 'base64url')
}
function handler(event) {
var request = event.request;
//Secret key used to verify JWT token.
//Update with your own key.
var key = "LzdWGpAToQ1DqYuzHxE6YOqi7G3X2yvNBot9mCXfx5k";
// If no JWT token, then generate HTTP redirect 401 response.
if(!request.querystring.jwt) {
console.log("Error: No JWT in the querystring");
return response401;
}
var jwtToken = request.querystring.jwt.value;
try{
jwt_decode(jwtToken, key);
}
catch(e) {
console.log(e);
return response401;
}
//Remove the JWT from the query string if valid and return.
delete request.querystring.jwt;
console.log("Valid JWT token");
return request;
}