Created middleware to retrieve JWT token from header

This commit is contained in:
Chris Troutner
2019-10-20 11:55:46 -07:00
parent 532f06cec1
commit 4032e66be3
7 changed files with 436 additions and 184 deletions
+209 -99
View File
@@ -102,16 +102,18 @@
}
},
"@chris.troutner/bch-js": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/@chris.troutner/bch-js/-/bch-js-1.4.4.tgz",
"integrity": "sha512-928YAVLKhQ0869/toMkIJl76/7Q31UGVNdYFky1tueJ3BibxgiM+nKl2YbQd06doLuZUniwcD9lKm3sHjFqNbw==",
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@chris.troutner/bch-js/-/bch-js-1.6.1.tgz",
"integrity": "sha512-Wkv7iVw9wYjNF5/Ewy5Qq995x1AV+DWRqikZg9FQxCl7Tub7PmmDfADcJwp+tNKGZs5Q+dpiL30P6zBld52g7g==",
"requires": {
"apidoc": "^0.17.7",
"assert": "^2.0.0",
"axios": "^0.19.0",
"bc-bip68": "^1.0.5",
"bch-wallet-bridge.js": "github:web3bch/bch-wallet-bridge.js#master",
"bchaddrjs-slp": "^0.2.5",
"bigi": "^1.4.2",
"bignumber.js": "^9.0.0",
"bip-schnorr": "^0.3.0",
"bip21": "github:Bitcoin-com/bip21",
"bip32-utils": "github:Bitcoin-com/bip32-utils#0.13.1",
@@ -141,7 +143,6 @@
"repl.history": "^0.1.4",
"safe-buffer": "^5.1.2",
"satoshi-bitcoin": "^1.0.4",
"slpjs": "^0.21.0",
"socket.io": "^2.1.1",
"socket.io-client": "^2.1.1",
"touch": "^3.1.0",
@@ -287,9 +288,9 @@
"dev": true
},
"@semantic-release/github": {
"version": "5.4.2",
"resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-5.4.2.tgz",
"integrity": "sha512-8gkOa5tED/+sjAPwZRYsLaGr6VuAGLZinSvLsuF9/l4qLeYV8gvj7fhjFJepGu6y31t7PR2J9SWzmsqsBAyyKQ==",
"version": "5.5.4",
"resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-5.5.4.tgz",
"integrity": "sha512-CovZ9zs/rbBOCyyzmstoCwGS5qNEgab3wB8y3SAvOD7TfhtqizWVRkUJV7nzzaevomhUSZD/lp7Cs/fk1sE1Qw==",
"dev": true,
"requires": {
"@octokit/rest": "^16.27.0",
@@ -301,16 +302,49 @@
"fs-extra": "^8.0.0",
"globby": "^10.0.0",
"http-proxy-agent": "^2.1.0",
"https-proxy-agent": "^2.2.1",
"issue-parser": "^4.0.0",
"https-proxy-agent": "^3.0.0",
"issue-parser": "^5.0.0",
"lodash": "^4.17.4",
"mime": "^2.4.3",
"p-filter": "^2.0.0",
"p-retry": "^4.0.0",
"parse-github-url": "^1.0.1",
"url-join": "^4.0.0"
},
"dependencies": {
"https-proxy-agent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz",
"integrity": "sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ==",
"dev": true,
"requires": {
"agent-base": "^4.3.0",
"debug": "^3.1.0"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
}
}
},
"issue-parser": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-5.0.0.tgz",
"integrity": "sha512-q/16W7EPHRL0FKVz9NU++TUsoygXGj6JOi88oulyAcQG+IEZ0T6teVdE+VLbe19OfL/tbV8Wi3Dfo0HedeHW0Q==",
"dev": true,
"requires": {
"lodash.capitalize": "^4.2.1",
"lodash.escaperegexp": "^4.1.2",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.uniqby": "^4.7.0"
}
},
"mime": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
@@ -1466,8 +1500,8 @@
}
},
"bchaddrjs-slp": {
"version": "git://github.com/simpleledger/bchaddrjs.git#ea05d679783a6737f2f99adc37ebf485dc64f006",
"from": "git://github.com/simpleledger/bchaddrjs.git#master",
"version": "0.2.6",
"resolved": "git://github.com/simpleledger/bchaddrjs.git#ea05d679783a6737f2f99adc37ebf485dc64f006",
"requires": {
"bs58check": "^2.1.2",
"cashaddrjs-slp": "^0.2.11"
@@ -1519,8 +1553,7 @@
"bignumber.js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
"dev": true
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
},
"binary-extensions": {
"version": "1.13.1",
@@ -1711,7 +1744,7 @@
"integrity": "sha512-x0wMVSCZ56ZQnSQ+Xim7XfS0IYiOyOwo0pdMCmR+cDNB7zRhICFuH5i3lNdLSgUw1e7Pc3FmUlC9wruQNlYMnA=="
},
"bitcoincashjs-lib": {
"version": "github:christroutner/bitcoincashjs-lib#0a2291b5c5558241003aa9609f82846313604f15",
"version": "github:christroutner/bitcoincashjs-lib#b03ca974d4fd548cb42c7a522863e5d9be6051ef",
"from": "github:christroutner/bitcoincashjs-lib",
"requires": {
"bech32": "^1.1.2",
@@ -1884,6 +1917,11 @@
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==",
"dev": true
},
"bowser": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz",
"integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w=="
},
"boxen": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
@@ -2236,6 +2274,11 @@
"resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz",
"integrity": "sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY="
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"buffer-equals": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz",
@@ -2429,9 +2472,9 @@
"dev": true
},
"cashaddrjs": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/cashaddrjs/-/cashaddrjs-0.3.6.tgz",
"integrity": "sha512-TEeTEXT8Gft4cNoZKisCdyrAymnSRYpZHtvCRgXJ9OmOwyTKn5vnCWbPQLL3EiUkm1HeMxSrKNK29nMfvaT2Qw==",
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/cashaddrjs/-/cashaddrjs-0.3.8.tgz",
"integrity": "sha512-gpXj9Qki9noucK0ahPB6dx9A539KQ4TbqKLwl/JsCvD4iLLu1thtoAIDy2hwP6PWg6o1nvK+igsutMA6OvO2Mg==",
"requires": {
"big-integer": "1.6.36"
},
@@ -2722,9 +2765,9 @@
}
},
"commander": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-3.0.0.tgz",
"integrity": "sha512-pl3QrGOBa9RZaslQiqnnKX2J068wcQw7j9AIaBQ9/JEp5RY6je4jKTImg0Bd+rpoONSe7GUFSgkxLeo17m3Pow=="
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz",
"integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow=="
},
"commist": {
"version": "1.1.0",
@@ -3674,6 +3717,14 @@
"safer-buffer": "^2.1.0"
}
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ecurve": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz",
@@ -4567,12 +4618,20 @@
}
},
"eslint-utils": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz",
"integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.0.0"
"eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
"dev": true
}
}
},
"eslint-visitor-keys": {
@@ -4814,11 +4873,34 @@
"basic-auth": "^2.0.1"
}
},
"express-jwt": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/express-jwt/-/express-jwt-5.3.1.tgz",
"integrity": "sha512-1C9RNq0wMp/JvsH/qZMlg3SIPvKu14YkZ4YYv7gJQ1Vq+Dv8LH9tLKenS5vMNth45gTlEUGx+ycp9IHIlaHP/g==",
"requires": {
"async": "^1.5.0",
"express-unless": "^0.3.0",
"jsonwebtoken": "^8.1.0",
"lodash.set": "^4.0.0"
},
"dependencies": {
"async": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
}
}
},
"express-rate-limit": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.0.0.tgz",
"integrity": "sha512-dhT57wqxfqmkOi4HM7NuT4Gd7gbUgSK2ocG27Y6lwm8lbOAw9XQfeANawGq8wLDtlGPO1ZgDj0HmKsykTxfFAg=="
},
"express-unless": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/express-unless/-/express-unless-0.3.1.tgz",
"integrity": "sha1-JVfBRudb65A+LSR/m1ugFFJpbiA="
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -6141,9 +6223,9 @@
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA=="
},
"handlebars": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.3.tgz",
"integrity": "sha512-B0W4A2U1ww3q7VVthTKfh+epHx+q4mCt6iK+zEAzbMBpWQAwxCeKxEGpj/1oQTpzPXDNSOG7hmG14TsISH50yw==",
"requires": {
"neo-async": "^2.6.0",
"optimist": "^0.6.1",
@@ -6323,9 +6405,9 @@
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"helmet": {
"version": "3.20.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.20.0.tgz",
"integrity": "sha512-Ob+TqmQFZ5f7WgP8kBbAzNPsbf6p1lOj5r+327/ymw/IILWih3wcx9u/u/S8Mwv5wbBkO7Li6x5s23t3COhUKw==",
"version": "3.21.1",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.21.1.tgz",
"integrity": "sha512-IC/54Lxvvad2YiUdgLmPlNFKLhNuG++waTF5KPYq/Feo3NNhqMFbcLAlbVkai+9q0+4uxjxGPJ9bNykG+3zZNg==",
"requires": {
"depd": "2.0.0",
"dns-prefetch-control": "0.2.0",
@@ -6334,14 +6416,14 @@
"feature-policy": "0.3.0",
"frameguard": "3.1.0",
"helmet-crossdomain": "0.4.0",
"helmet-csp": "2.8.0",
"helmet-csp": "2.9.2",
"hide-powered-by": "1.1.0",
"hpkp": "2.0.0",
"hsts": "2.2.0",
"ienoopen": "1.1.0",
"nocache": "2.1.0",
"referrer-policy": "1.2.0",
"x-xss-protection": "1.2.0"
"x-xss-protection": "1.3.0"
},
"dependencies": {
"depd": {
@@ -6357,14 +6439,14 @@
"integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
},
"helmet-csp": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.8.0.tgz",
"integrity": "sha512-MlCPeM0Sm3pS9RACRihx70VeTHmkQwa7sum9EK1tfw1VZyvFU0dBWym9nHh3CRkTRNlyNm/WFCMvuh9zXkOjNw==",
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.9.2.tgz",
"integrity": "sha512-Lt5WqNfbNjEJ6ysD4UNpVktSyjEKfU9LVJ1LaFmPfYseg/xPealPfgHhtqdAdjPDopp5zbg/VWCyp4cluMIckw==",
"requires": {
"bowser": "^2.6.1",
"camelize": "1.0.0",
"content-security-policy-builder": "2.1.0",
"dasherize": "2.0.0",
"platform": "1.3.5"
"dasherize": "2.0.0"
}
},
"help-me": {
@@ -6518,27 +6600,6 @@
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
},
"https-proxy-agent": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
"integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
"dev": true,
"requires": {
"agent-base": "^4.3.0",
"debug": "^3.1.0"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
}
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -7109,19 +7170,6 @@
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"issue-parser": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-4.0.0.tgz",
"integrity": "sha512-1RmmAXHl5+cqTZ9dRr861xWy0Gkc9TWTEklgjKv+nhlB1dY1NmGBV8b20jTWRL5cPGpOIXkz84kEcDBM8Nc0cw==",
"dev": true,
"requires": {
"lodash.capitalize": "^4.2.1",
"lodash.escaperegexp": "^4.1.2",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.uniqby": "^4.7.0"
}
},
"istanbul-lib-coverage": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
@@ -7297,6 +7345,30 @@
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA="
},
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"requires": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -7324,6 +7396,25 @@
"integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==",
"dev": true
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"keccak": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz",
@@ -7553,34 +7644,56 @@
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
"dev": true
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.ismatch": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
"integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=",
"dev": true
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
"dev": true
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
"dev": true
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.memoize": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
"integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"lodash.set": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=",
"dev": true
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
},
"lodash.toarray": {
"version": "4.4.0",
@@ -12567,12 +12680,6 @@
"safe-buffer": "^5.1.1"
}
},
"parse-github-url": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
"integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
"dev": true
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@@ -12634,6 +12741,14 @@
"passport-strategy": "1.x.x"
}
},
"passport-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
"integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
"requires": {
"passport-strategy": "1.x.x"
}
},
"passport-strategy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
@@ -12870,11 +12985,6 @@
"find-up": "^3.0.0"
}
},
"platform": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
"integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q=="
},
"pluralize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
@@ -15254,19 +15364,19 @@
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"uglify-js": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
"integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.3.tgz",
"integrity": "sha512-KfQUgOqTkLp2aZxrMbCuKCDGW9slFYu2A23A36Gs7sGzTLcRBDORdOi5E21KWHFIfkY8kzgi/Pr1cXCh0yIp5g==",
"optional": true,
"requires": {
"commander": "~2.20.0",
"commander": "~2.20.3",
"source-map": "~0.6.1"
},
"dependencies": {
"commander": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"optional": true
},
"source-map": {
@@ -15882,9 +15992,9 @@
}
},
"x-xss-protection": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.2.0.tgz",
"integrity": "sha512-xN0kV+8XfOQM2OPPBdEbGtbvJNNP1pvZR7sE6d44cjJFQG4OiGDdienPg5iOUGswBTiGbBvtYDURd30BMJwwqg=="
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.3.0.tgz",
"integrity": "sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg=="
},
"xdg-basedir": {
"version": "3.0.0",
+3 -2
View File
@@ -22,7 +22,7 @@
"node": ">=10.15.1"
},
"dependencies": {
"@chris.troutner/bch-js": "^1.3.0",
"@chris.troutner/bch-js": "^1.6.1",
"apidoc": "^0.17.7",
"axios": "^0.19.0",
"body-parser": "^1.18.3",
@@ -33,7 +33,7 @@
"express": "^4.15.5",
"express-basic-auth": "^1.1.3",
"express-rate-limit": "^5.0.0",
"helmet": "^3.12.1",
"helmet": "^3.21.1",
"level": "^5.0.1",
"mkdirp": "^0.5.1",
"mocha": "^6.1.4",
@@ -42,6 +42,7 @@
"passport": "^0.4.0",
"passport-anonymous": "^1.0.1",
"passport-http": "^0.3.0",
"passport-local": "^1.0.0",
"pg": "^7.11.0",
"pg-hstore": "^2.3.2",
"slp-sdk": "^4.4.1",
+6
View File
@@ -15,7 +15,10 @@ const helmet = require("helmet")
const debug = require("debug")("rest-cloud:server")
const http = require("http")
const cors = require("cors")
// Auth and rate limiting middleware libraries.
const AuthMW = require("./middleware/auth")
const jwtAuth = require("./middleware/jwt-auth")
// v2
const indexV2 = require("./routes/v2/index")
@@ -88,6 +91,9 @@ app.use(express.static(path.join(__dirname, "public")))
const v2prefix = "v2"
const v3prefix = "v3"
// Inspect the header for a JWT token.
app.use(`/${v3prefix}/`, jwtAuth.getTokenFromHeaders)
// Instantiate the authorization middleware, used to implement pro-tier rate limiting.
const auth = new AuthMW()
app.use(`/${v2prefix}/`, auth.mw())
+43
View File
@@ -1,6 +1,13 @@
/*
Handle authorization for bypassing rate limits.
1) Default is 'Anonymous Authentication', which unlocks the freemimum tier by
default.
2) Hard-coded 'Basic Authentication' is a token that does not expire and is
provided to buisiness partners.
3) JWT-based 'Local Authentication' is used for normal users that pay to
access the premium pro-tier services.
This file uses the passport npm library to check the header of each REST API
call for the prescence of a Basic authorization header:
https://en.wikipedia.org/wiki/Basic_access_authentication
@@ -14,7 +21,9 @@
const passport = require("passport")
const BasicStrategy = require("passport-http").BasicStrategy
const AnonymousStrategy = require("passport-anonymous")
const LocalStrategy = require("passport-local")
const wlogger = require("../util/winston-logging")
const axios = require("axios")
// Used for debugging and iterrogating JS objects.
const util = require("util")
@@ -88,6 +97,40 @@ class AuthMW {
return done(null, true)
})
)
// JWT token based authentication.
passport.use(
new LocalStrategy(
{
usernameField: "user[email]",
passwordField: "user[password]",
passReqToCallback: true,
session: false
},
async (req, email, password, done) => {
console.log(`Checking against local strategy.`)
const userData = {}
const isValid = true
// Lookup the user from the database.
// const userData = await userDB.findByEmail(email)
//console.log(`userData: ${util.inspect(userDataRaw)}`)
// Hash the password and see if it matches the saved hash.
// const isValid = jwt.validatePassword(userData, password)
if (isValid) {
//console.log(`Passwords match!`)
return done(null, userData)
}
return done(null, false, {
errors: { "email or password": "is invalid" }
})
}
)
)
}
// Middleware called by the route.
+43
View File
@@ -0,0 +1,43 @@
/*
This middleware inspects the request header for a JWT token.
If found, will populate req.locals.jwtToken with the JWT token.
*/
"use strict"
// This function searches the header for the a JWT token in the authorization header.
// If one is found, this middleware passes the JWT token through the
// req.locals.jwtToken property.
const getTokenFromHeaders = (req, res, next) => {
try {
// console.log(`getTokenFromHeaders2: Searching headers for a JWT token.`)
// console.log(`req.headers: `, req.headers)
// If the authorization header exists.
if (req.headers.authorization) {
const authStr = req.headers.authorization
// If the header is proceeded by the word 'Token'
if (authStr.split(" ")[0] === "Token") {
const token = authStr.split(" ")[1]
// console.log(`JWT found: ${token}`)
// Create the req.locals property if it does not yet exist.
if (!req.locals) req.locals = {}
req.locals.jwtToken = token
}
}
} catch (err) {
console.log(`Error in getTokenFromHeaders2: `, err)
}
next()
}
const jwtAuth = {
getTokenFromHeaders
}
module.exports = jwtAuth
+19 -2
View File
@@ -24,11 +24,28 @@ const PRO_RPM = 10 * maxRequests
const uniqueRateLimits = {}
const routeRateLimit = function(req, res, next) {
// Disable rate limiting if 0 passed from RATE_LIMIT_MAX_REQUESTS
if (maxRequests === 0) return next()
// Create a res.locals object if not passed in.
if (!req.locals) req.locals = {}
// Disable rate limiting if 0 passed from RATE_LIMIT_MAX_REQUESTS
if (maxRequests === 0) return next()
if (req.locals.jwtToken)
console.log(`req.locals.jwtToken: ${req.locals.jwtToken}`)
// If no JWT token was provided, skip
if (req.payload)
console.log(`req.payload: ${JSON.stringify(req.payload, null, 2)}`)
// // Unlock the pro-tier rate limits if the user passed in a valid JWT token.
// if (!proRateLimits) {
// const user = await getUserFromJWT(req)
//
// // Enable pro-tier rate limits for this user.
// if(user) {
// console.log(`${user.email} (${user.id}) passed in valid JWT`)
// proRateLimits = true
// }
// }
// Current route
const rateLimitTier = req.locals.proLimit ? "PRO" : "BASIC"
+113 -81
View File
@@ -14,8 +14,11 @@ const axios = require("axios")
const util = require("util")
util.inspect.defaultOptions = { depth: 1 }
const SERVER = `http://192.168.0.36:12400/v3/`
//const SERVER = `http://localhost:3000/v2/`
// const SERVER = `http://192.168.0.36:12400/v3/`
const SERVER = `http://localhost:3000/v3/`
const TEST_JWT =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkYTc5ZDk4OTYyMjRjNjM2MmQwYzkwMiIsImlhdCI6MTU3MTUzOTU1MSwiZXhwIjoxNTc0MTMxNTUxfQ.PfPW_Z2NYT1O2zUHXopcz2aLGHSGudaKOIGnt7SuAi4"
describe("#rate limits", () => {
it("should get control/getNetworkInfo() with no auth", async () => {
@@ -32,102 +35,131 @@ describe("#rate limits", () => {
assert.hasAnyKeys(result.data, ["version"])
})
it("should trigger rate-limit handler if rate limits exceeds 30 request per minute", async () => {
// it("should trigger rate-limit handler if rate limits exceeds 30 request per minute", async () => {
// try {
// // Actual rate limit is 60 per minute X 4 nodes = 240 rpm.
// const options = {
// method: "GET",
// url: `${SERVER}control/getNetworkInfo`
// }
//
// const promises = []
// for (let i = 0; i < 30; i++) {
// const promise = axios(options)
// promises.push(promise)
// }
//
// await Promise.all(promises)
//
// assert.equal(true, false, "Unexpected result!")
// } catch (err) {
// //console.log(`err.response: ${util.inspect(err.response)}`)
//
// assert.equal(err.response.status, 429)
// assert.include(err.response.data.error, "Too many requests")
// }
// })
// it("should not trigger rate-limit handler if correct pro-tier password is used", async () => {
// try {
// const username = "BITBOX"
//
// // Pro-tier is accessed by using the right password.
// const password = "BITBOX"
// //const password = "something"
//
// const combined = `${username}:${password}`
// const base64Credential = Buffer.from(combined).toString("base64")
// const readyCredential = `Basic ${base64Credential}`
//
// const options = {
// method: "GET",
// url: `${SERVER}control/getNetworkInfo`,
// headers: { Authorization: readyCredential }
// }
//
// const promises = []
// for (let i = 0; i < 30; i++) {
// const promise = axios(options)
// promises.push(promise)
// }
//
// await Promise.all(promises)
//
// assert.equal(true, true, "Not throwing an error is a pass!")
// } catch (err) {
// // console.log(`err.response: ${util.inspect(err.response)}`)
//
// assert.equal(
// true,
// false,
// "This error handler should not have been triggered. Is the password correct?"
// )
// }
// })
// it("should trigger rate-limit handler if rate limits exceeds pro-tier limit", async () => {
// try {
// const username = "BITBOX"
//
// // Pro-tier is accessed by using the right password.
// const password = "BITBOX"
// //const password = "something"
//
// const combined = `${username}:${password}`
// const base64Credential = Buffer.from(combined).toString("base64")
// const readyCredential = `Basic ${base64Credential}`
//
// // Actual rate limit is 60 per minute X 4 nodes = 240 rpm.
// const options = {
// method: "GET",
// url: `${SERVER}control/getNetworkInfo`,
// headers: { Authorization: readyCredential }
// }
//
// const promises = []
// for (let i = 0; i < 80; i++) {
// const promise = axios(options)
// promises.push(promise)
// }
//
// await Promise.all(promises)
//
// assert.equal(true, false, "Unexpected result!")
// } catch (err) {
// //console.log(`err.response: ${util.inspect(err.response)}`)
//
// assert.equal(err.response.status, 429)
// assert.include(err.response.data.error, "Too many requests")
// }
// })
it("should unlock pro-tier for a valid JWT token", async () => {
try {
// Actual rate limit is 60 per minute X 4 nodes = 240 rpm.
const options = {
method: "GET",
url: `${SERVER}control/getNetworkInfo`
}
const promises = []
for (let i = 0; i < 30; i++) {
const promise = axios(options)
promises.push(promise)
}
await Promise.all(promises)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err.response: ${util.inspect(err.response)}`)
assert.equal(err.response.status, 429)
assert.include(err.response.data.error, "Too many requests")
}
})
it("should not trigger rate-limit handler if correct pro-tier password is used", async () => {
try {
const username = "BITBOX"
// Pro-tier is accessed by using the right password.
const password = "BITBOX"
//const password = "something"
const combined = `${username}:${password}`
const base64Credential = Buffer.from(combined).toString("base64")
const readyCredential = `Basic ${base64Credential}`
const options = {
method: "GET",
url: `${SERVER}control/getNetworkInfo`,
headers: { Authorization: readyCredential }
headers: {
Authorization: `Token ${TEST_JWT}`
}
}
const promises = []
for (let i = 0; i < 30; i++) {
for (let i = 0; i < 1; i++) {
const promise = axios(options)
promises.push(promise)
}
await Promise.all(promises)
//assert.equal(true, false, "Unexpected result!")
assert.equal(true, true, "Not throwing an error is a pass!")
} catch (err) {
// console.log(`err.response: ${util.inspect(err.response)}`)
assert.equal(
true,
false,
"This error handler should not have been triggered. Is the password correct?"
)
}
})
it("should trigger rate-limit handler if rate limits exceeds pro-tier limit", async () => {
try {
const username = "BITBOX"
// Pro-tier is accessed by using the right password.
const password = "BITBOX"
//const password = "something"
const combined = `${username}:${password}`
const base64Credential = Buffer.from(combined).toString("base64")
const readyCredential = `Basic ${base64Credential}`
// Actual rate limit is 60 per minute X 4 nodes = 240 rpm.
const options = {
method: "GET",
url: `${SERVER}control/getNetworkInfo`,
headers: { Authorization: readyCredential }
}
const promises = []
for (let i = 0; i < 80; i++) {
const promise = axios(options)
promises.push(promise)
}
await Promise.all(promises)
console.log(`err.response: ${util.inspect(err.response)}`)
assert.equal(true, false, "Unexpected result!")
} catch (err) {
//console.log(`err.response: ${util.inspect(err.response)}`)
assert.equal(err.response.status, 429)
assert.include(err.response.data.error, "Too many requests")
}
})
// Override default timeout for this test.
}).timeout(20000)
})