diff --git a/.babelrc b/.babelrc index b3c8fbb..64f0844 100644 --- a/.babelrc +++ b/.babelrc @@ -1,12 +1,9 @@ { - "presets": [ - "@babel/preset-env" - ], + "presets": ["@babel/preset-env"], "env": { "test": { - "plugins": [ - "istanbul" - ] + "plugins": ["istanbul"] } - } -} \ No newline at end of file + }, + "plugins": ["@babel/plugin-transform-runtime"] +} diff --git a/README.md b/README.md index d00a11e..aaad177 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,16 @@ ![GitHub Repo stars](https://img.shields.io/github/stars/akdombrowski/jwt-authn?style=for-the-badge&logo=github) ![GitHub forks](https://img.shields.io/github/forks/akdombrowski/jwt-authn?style=for-the-badge&logo=github) ![GitHub watchers](https://img.shields.io/github/watchers/akdombrowski/jwt-authn?style=for-the-badge&logo=github) +[![](https://data.jsdelivr.com/v1/package/npm/jwt-authn/badge)](https://www.jsdelivr.com/package/npm/jwt-authn) + +[![Rate on Openbase](https://badges.openbase.com/js/rating/jwt-authn.svg)](https://openbase.com/js/jwt-authn?utm_source=embedded&utm_medium=badge&utm_campaign=rate-badge) # jwt-authn +jwt-authn is an npm package for dealing with JSON Web Tokens (JWT). Encoding, decoding, verifying, signing, and more coming. It includes support for the RS256 and HS256 algorithms and JWK and PEM format keys (even encrypted keys). Only Node >=15.x as a requirement! + +Now with command line support! -jwt-authn is an npm package for dealing with JSON Web Tokens. Encoding, decoding, verifying, signing, and more coming. It includes support for the RS256 and HS256 algorithms and JWK and PEM format keys (even encrypted keys). No package dependencies! Its only dependency is NodeJS itself. *[Must be on Node >= 15.x](https://nodejs.org/en/about/releases/) @@ -25,6 +30,7 @@ jwt-authn is an npm package for dealing with JSON Web Tokens. Encoding, decoding - [⬆Usage](#usage) - [⬆Installation:](#installation) - [⬆Accepted Form of JWTs](#accepted-form-of-jwts) + - [⬆ CLI support for JWT Decoding](#-cli-support-for-jwt-decoding) - [⬆ Decoding a JWT](#-decoding-a-jwt) - [⬆ **jwtDecode(jwt)**](#-jwtdecodejwt) - [⬆ Encoding a JWT](#-encoding-a-jwt) @@ -60,10 +66,27 @@ Use the package manager [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg. npm install jwt-authn ``` + ```Shell yarn add jwt-authn ``` +Or from a cdn: +``` +https://cdn.jsdelivr.net/npm/jwt-authn@1.0.39/lib +``` + +If using for the command line support (or it'll only be available in the current directory's node_modules folder): + +```Shell +npm install -g jwt-authn +``` + +```Shell +yarn global install jwt-authn +``` + +
--- @@ -92,6 +115,34 @@ eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTk --- +### [⬆](#index) CLI support for JWT Decoding + +
+ +Running just jwt-authn will try to decode whatever is in your clipboard. +```Shell +# Decodes what's in your clipboard. +jwt-authn +``` + +Alternatively, you can run jwt-authn with the clipboard option. +```Shell +jwt-authn -c +``` + +```Shell +jwt-authn --clipboard +``` + +or to decode the input +```Shell +jwt-authn eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk +``` + +
+ +--- + ### [⬆](#index) Decoding a JWT
diff --git a/cli/index.js b/cli/index.js new file mode 100644 index 0000000..bffd388 --- /dev/null +++ b/cli/index.js @@ -0,0 +1,96 @@ +#!/usr/bin/env node + +import { jwtDecode } from "../lib"; +import clipboardy from "clipboardy"; + +const decode = async (jwt) => { + try { + const decoded = await jwtDecode(jwt); + return decoded; + } catch (e) { + throw e; + } +}; + +export const HELP_TEXT = + "******HELP*****\n\ +use -c or --clipboard or call command with no arguments to decode the JWT in your clipboard\n\ +or call command with JWT as first argument\n\ +****************"; + +export const cli = async (clipboard, argv) => { + // read passed in argument + let arg2; + if (argv) { + arg2 = argv[2]; + } + + if (arg2 == "-h" || arg2 === "--help") { + // Help display + console.log(HELP_TEXT); + return HELP_TEXT; + } else if (arg2 === "-c" || arg2 === "--clipboard" || !arg2) { + // Check for something in the clipboard. + if (clipboard) { + // Great, there's something in the clipboard. Let's try to decode it as a + // JWT. + try { + const decoded = await decode(clipboard); + // Show what we found in the clipboard + console.log("Decoding: "); + console.log(clipboard); + // Show the decoded jwt. + console.log(decoded); + return decoded; + } catch (e) { + console.error("I found an error :("); + console.error( + "Couldn't decode what was in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard" + ); + console.error("what's on your clipboard? "); + console.error(clipboard); + throw e; + } + } else { + console.error("I found an error :(."); + console.error( + "Nothing in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard" + ); + } + } else if (arg2) { + try { + const decoded = jwtDecode(arg2); + console.log("Decoding: \n" + arg2); + console.log(decoded); + return decoded; + } catch (e) { + console.error("I found an error :(."); + console.error(e, e.message); + throw e; + } + } else { + console.error("I found an error :(."); + console.error( + "Nothing in clipboard and no arguments given. Pass in a JWT as the first argument or copy a JWT to your clipboard" + ); + throw new Error( + "Nothing in clipboard and no arguments given. Pass in a JWT as the first argument or copy a JWT to your clipboard" + ); + } + return 1; +}; + +// read from clipboard +let clipboard; +try { + clipboard = clipboardy.readSync(); +} catch (e) { + clipboard = null; +} + +// read passed in argument +const argv = process.argv; + +cli(clipboard, argv); + +export default cli; diff --git a/cli/index.min.js b/cli/index.min.js new file mode 100644 index 0000000..d66e027 --- /dev/null +++ b/cli/index.min.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +import{jwtDecode}from"../lib";import clipboardy from"clipboardy";const decode=async o=>await jwtDecode(o);export const HELP_TEXT="******HELP*****\nuse -c or --clipboard or call command with no arguments to decode the JWT in your clipboard\nor call command with JWT as first argument\n****************";export const cli=async(o,r)=>{let e;if(r&&(e=r[2]),"-h"==e||"--help"===e)return console.log(HELP_TEXT),HELP_TEXT;if("-c"!==e&&"--clipboard"!==e&&e)if(e)try{const o=jwtDecode(e);return console.log("Decoding: \n"+e),console.log(o),o}catch(o){console.error("I found an error :(."),console.error(o,o.message)}else console.error("I found an error :(."),console.error("Nothing in clipboard and no arguments given. Pass in a JWT as the first argument or copy a JWT to your clipboard");else if(o)try{const r=await decode(o);return console.log("Decoding: "),console.log(o),console.log(r),r}catch(r){console.error("I found an error :(."),console.error("Couldn't decode what was in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard"),console.error("what's on your clipboard? "),console.error(o),console.error(r,r.message)}else console.error("I found an error :(."),console.error("Nothing in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard");return 1};let clipboard;try{clipboard=clipboardy.readSync()}catch(o){clipboard=null}const argv=process.argv;cli(clipboard,argv);export default cli; diff --git a/cli_lib/index.js b/cli_lib/index.js new file mode 100644 index 0000000..8816ec4 --- /dev/null +++ b/cli_lib/index.js @@ -0,0 +1,173 @@ +#!/usr/bin/env node +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = exports.cli = exports.HELP_TEXT = void 0; + +var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); + +var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); + +var _lib = require("../lib"); + +var _clipboardy = _interopRequireDefault(require("clipboardy")); + +var decode = /*#__PURE__*/function () { + var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(jwt) { + return _regenerator["default"].wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.next = 2; + return (0, _lib.jwtDecode)(jwt); + + case 2: + return _context.abrupt("return", _context.sent); + + case 3: + case "end": + return _context.stop(); + } + } + }, _callee); + })); + + return function decode(_x) { + return _ref.apply(this, arguments); + }; +}(); + +var HELP_TEXT = "******HELP*****\n\ +use -c or --clipboard or call command with no arguments to decode the JWT in your clipboard\n\ +or call command with JWT as first argument\n\ +****************"; +exports.HELP_TEXT = HELP_TEXT; + +var cli = /*#__PURE__*/function () { + var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(clipboard, argv) { + var arg2, decoded, _decoded; + + return _regenerator["default"].wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + // read passed in argument + if (argv) { + arg2 = argv[2]; + } + + if (!(arg2 == "-h" || arg2 === "--help")) { + _context2.next = 6; + break; + } + + // Help display + console.log(HELP_TEXT); + return _context2.abrupt("return", HELP_TEXT); + + case 6: + if (!(arg2 === "-c" || arg2 === "--clipboard" || !arg2)) { + _context2.next = 31; + break; + } + + if (!clipboard) { + _context2.next = 27; + break; + } + + _context2.prev = 8; + _context2.next = 11; + return decode(clipboard); + + case 11: + decoded = _context2.sent; + // Show what we found in the clipboard + console.log("Decoding: "); + console.log(clipboard); // Show the decoded jwt. + + console.log(decoded); + return _context2.abrupt("return", decoded); + + case 18: + _context2.prev = 18; + _context2.t0 = _context2["catch"](8); + console.error("I found an error :(."); + console.error("Couldn't decode what was in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard"); + console.error("what's on your clipboard? "); + console.error(clipboard); + console.error(_context2.t0, _context2.t0.message); + + case 25: + _context2.next = 29; + break; + + case 27: + console.error("I found an error :(."); + console.error("Nothing in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard"); + + case 29: + _context2.next = 47; + break; + + case 31: + if (!arg2) { + _context2.next = 45; + break; + } + + _context2.prev = 32; + _decoded = (0, _lib.jwtDecode)(arg2); + console.log("Decoding: \n" + arg2); + console.log(_decoded); + return _context2.abrupt("return", _decoded); + + case 39: + _context2.prev = 39; + _context2.t1 = _context2["catch"](32); + console.error("I found an error :(."); + console.error(_context2.t1, _context2.t1.message); + + case 43: + _context2.next = 47; + break; + + case 45: + console.error("I found an error :(."); + console.error("Nothing in clipboard and no arguments given. Pass in a JWT as the first argument or copy a JWT to your clipboard"); + + case 47: + return _context2.abrupt("return", 1); + + case 48: + case "end": + return _context2.stop(); + } + } + }, _callee2, null, [[8, 18], [32, 39]]); + })); + + return function cli(_x2, _x3) { + return _ref2.apply(this, arguments); + }; +}(); // read from clipboard + + +exports.cli = cli; +var clipboard; + +try { + clipboard = _clipboardy["default"].readSync(); +} catch (e) { + clipboard = null; +} // read passed in argument + + +var argv = process.argv; +cli(clipboard, argv); +var _default = cli; +exports["default"] = _default; \ No newline at end of file diff --git a/cli_lib/index.min.js b/cli_lib/index.min.js new file mode 100644 index 0000000..c90bbe4 --- /dev/null +++ b/cli_lib/index.min.js @@ -0,0 +1,112 @@ +#!/usr/bin/env node +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); + +var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); + +var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); + +var _lib = require("../lib"); + +var _clipboardy = _interopRequireDefault(require("clipboardy")); + +var clipboard = _clipboardy["default"].readSync(), + arg2 = process.argv[2], + decode = /*#__PURE__*/function () { + var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(o) { + return _regenerator["default"].wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.next = 2; + return (0, _lib.jwtDecode)(o); + + case 2: + return _context.abrupt("return", _context.sent); + + case 3: + case "end": + return _context.stop(); + } + } + }, _callee); + })); + + return function decode(_x) { + return _ref.apply(this, arguments); + }; +}(), + cli = /*#__PURE__*/function () { + var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(o, r) { + var _r; + + return _regenerator["default"].wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + if (!("-h" == r || "--help" === r)) { + _context2.next = 4; + break; + } + + console.log("use -c or --clipboard or call command with no arguments to decode the JWT in you clipboard"), console.log("or call command with JWT as first argument"); + _context2.next = 22; + break; + + case 4: + if (!("-c" !== r && "--clipboard" !== r && r)) { + _context2.next = 8; + break; + } + + if (r) try { + console.log("Decoding: \n" + r), console.log((0, _lib.jwtDecode)(r)); + } catch (o) { + console.error("I found an error :(."), console.error(o, o.message); + } else console.error("I found an error :(."), console.error("Nothing in clipboard and no arguments given. Pass in a JWT as the first argument or copy a JWT to your clipboard"); + _context2.next = 22; + break; + + case 8: + if (!o) { + _context2.next = 21; + break; + } + + _context2.prev = 9; + _context2.next = 12; + return decode(o); + + case 12: + _r = _context2.sent; + console.log("Decoding: \n" + o), console.log(_r); + _context2.next = 19; + break; + + case 16: + _context2.prev = 16; + _context2.t0 = _context2["catch"](9); + console.error("I found an error :(."), console.error("Couldn't decode what was in clipboard. Pass in a JWT as the first argument or copy a JWT to clipboard"), console.error("what's on your clipboard? "), console.error(o), console.error(_context2.t0, _context2.t0.message); + + case 19: + _context2.next = 22; + break; + + case 21: + console.error("I found an error :(."), console.error("Nothing in clipboard. Pass in a JWT as the first argument or copy a JWT to your clipboard"); + + case 22: + case "end": + return _context2.stop(); + } + } + }, _callee2, null, [[9, 16]]); + })); + + return function cli(_x2, _x3) { + return _ref2.apply(this, arguments); + }; +}(); + +cli(clipboard, arg2); \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index e5c0d72..744c2cd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,7 @@ "use strict"; +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); + Object.defineProperty(exports, "__esModule", { value: true }); @@ -7,8 +9,6 @@ exports["default"] = exports.jwtEncode = exports.parseToJSON = exports.base64URL var _crypto = _interopRequireDefault(require("crypto")); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } - /** * Decodes a JWT that is in JWS format. * @@ -35,8 +35,8 @@ var jwtDecode = function jwtDecode(jwt) { var base64URLDecodedHeader = Buffer.from(header, "base64url").toString("utf8"); if (!base64URLDecodedHeader) { - console.err("base64URLDecodedHeader"); - console.err(base64URLDecodedHeader); + console.error("base64URLDecodedHeader"); + console.error(base64URLDecodedHeader); throw new Error("Header isn't base64url encoded"); } // 4. Verify that the resulting octet sequence is a UTF-8-encoded // representation of a completely valid JSON object conforming to @@ -81,16 +81,28 @@ var jwtDecode = function jwtDecode(jwt) { }; } - throw new Error("Not using compact serialization (JWS)."); + throw new SyntaxError("Not using compact serialization (JWS)."); } catch (e) { - console.error(e.message, e); - return { - header: null, - payload: null, - signature: null - }; + // debugging(e); + console.error("I found an error :(."); + throw e; } }; + +exports.jwtDecode = jwtDecode; + +var debugging = function debugging(e) { + // debugging + console.error(e.message, e); + console.error("e instanceof SyntaxError"); + console.error(e instanceof SyntaxError); + console.error(e.message); + console.error(e.name); + console.error(e.fileName); + console.error(e.lineNumber); + console.error(e.columnNumber); + console.error(e.stack); +}; /** * Uses HMAC with SHA256 to create the signature of a JWT. * @@ -102,8 +114,6 @@ var jwtDecode = function jwtDecode(jwt) { */ -exports.jwtDecode = jwtDecode; - var hs256Sign = function hs256Sign(headerPayload, key) { var secret = _crypto["default"].createSecretKey(key, "base64url"); @@ -162,10 +172,12 @@ var rs256JWKSign = function rs256JWKSign(headerPayload, privateKey) { if (e instanceof TypeError) { secret = privateKey; } else { + console.error("I found an error :(."); console.error(e.message, e); } } } else { + console.error("I found an error :(."); console.error("RSA-SHA256 not found"); throw new Error("RSA-SHA256 isn't available in the current system."); } diff --git a/lib/index.min.js b/lib/index.min.js new file mode 100644 index 0000000..9dacb08 --- /dev/null +++ b/lib/index.min.js @@ -0,0 +1 @@ +"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=exports.jwtEncode=exports.parseToJSON=exports.base64URLEncode=exports.createHeaderPayload=exports.hs256Verify=exports.rs256PEMVerify=exports.rs256JWKVerify=exports.rs256PEMSign=exports.rs256JWKSign=exports.hs256Sign=exports.jwtDecode=void 0;var _crypto=_interopRequireDefault(require("crypto")),jwtDecode=function(r){try{if(!r.includes("."))throw new Error("Need at least one '.'");var e=r.split("."),o=e[0],t=Buffer.from(o,"base64url").toString("utf8");if(!t)throw console.error("base64URLDecodedHeader"),console.error(t),new Error("Header isn't base64url encoded");var a=JSON.parse(t),s=a.typ,n=a.cty,i=a.alg;if(s&&"JWT"!==s)throw new Error("Need to be type jwt. Received: ".concat(s));if(n&&"JWT"!==n)throw new Error("Need a cty of 'JWT'. Received: ".concat(n));if(!i)throw new Error("Missing algorithm in JOSE header.");if(3===e.length){var c=e[1],f=Buffer.from(c,"base64url").toString("utf8");return{header:a,payload:JSON.parse(f),signature:e[2]}}throw new SyntaxError("Not using compact serialization (JWS).")}catch(r){throw console.error("I found an error :(."),r}};exports.jwtDecode=jwtDecode;var debugging=function(r){console.error(r.message,r),console.error("e instanceof SyntaxError"),console.error(r instanceof SyntaxError),console.error(r.message),console.error(r.name),console.error(r.fileName),console.error(r.lineNumber),console.error(r.columnNumber),console.error(r.stack)},hs256Sign=function(r,e){var o=_crypto.default.createSecretKey(e,"base64url"),t=_crypto.default.createHmac("sha256",o);t.update(r,"ascii");var a=t.digest();return Buffer.from(a).toString("base64url")};exports.hs256Sign=hs256Sign;var rs256JWKSign=function(r,e){var o;if(!_crypto.default.getHashes().includes("RSA-SHA256"))throw console.error("I found an error :(."),console.error("RSA-SHA256 not found"),new Error("RSA-SHA256 isn't available in the current system.");try{try{o=JSON.parse(e)}catch(r){if(!JSON.stringify(e))throw new Error("Not valid JSON.");o=e}var t=_crypto.default.createPrivateKey({key:o,format:"jwk"});return _crypto.default.sign("sha256",Buffer.from(r),{key:t}).toString("base64url")}catch(r){r instanceof TypeError?o=e:(console.error("I found an error :(."),console.error(r.message,r))}return null};exports.rs256JWKSign=rs256JWKSign;var rs256PEMSign=function(r,e,o){var t;if(!_crypto.default.getHashes().includes("RSA-SHA256"))return console.error("RSA-SHA256 not found"),null;try{t=_crypto.default.createPrivateKey({key:e,format:"pem"})}catch(r){if(r instanceof TypeError&&r.message.includes("Passphrase required for encrypted key")){if(!o)throw new Error("Need a passphrase since private key is encrypted");t=_crypto.default.createPrivateKey({key:e,format:"pem",passphrase:o})}}return _crypto.default.sign("sha256",Buffer.from(r),{key:t}).toString("base64url")};exports.rs256PEMSign=rs256PEMSign;var rs256JWKVerify=function(r,e){var o=r.split("."),t=o[0]+"."+o[1],a=o[2],s=_crypto.default.createPublicKey({key:e,format:"jwk"});return _crypto.default.verify(null,Buffer.from(t,"ascii"),{key:s},Buffer.from(a,"base64url"))};exports.rs256JWKVerify=rs256JWKVerify;var rs256PEMVerify=function(r,e){var o=r.split("."),t=o[0]+"."+o[1],a=o[2],s=_crypto.default.createPublicKey({key:e,format:"pem"});return _crypto.default.verify(null,Buffer.from(t,"ascii"),{key:s},Buffer.from(a,"base64url"))};exports.rs256PEMVerify=rs256PEMVerify;var hs256Verify=function(r,e,o){var t=r.split("."),a=t[0]+"."+t[1],s=t[2],n=_crypto.default.createSecretKey(e,"base64url");n=o&&Buffer.isEncoding(o)?_crypto.default.createSecretKey(e,o):_crypto.default.createSecretKey(e,"base64url");var i=_crypto.default.createHmac("sha256",n);i.update(a,"ascii");var c=i.digest();return Buffer.from(c).toString("base64url")===s};exports.hs256Verify=hs256Verify;var createHeaderPayload=function(r,e){if(Buffer.isEncoding("base64url")){var o,t;if("string"==typeof r)o=Buffer.from(r,"ascii").toString("base64url");else{var a=parseToJSON(r);o=base64URLEncode(a)}if("string"==typeof e)t=Buffer.from(e,"ascii").toString("base64url");else{var s=parseToJSON(e);t=base64URLEncode(s)}return"".concat(o,".").concat(t)}throw new Error("Error: Base64URL encoding isn't available.")};exports.createHeaderPayload=createHeaderPayload;var base64URLEncode=function(r){if(Buffer.isEncoding("base64url")){var e=JSON.stringify(r);return Buffer.from(e,"ascii").toString("base64url")}throw new Error("Error: Base64URL encoding isn't available")};exports.base64URLEncode=base64URLEncode;var parseToJSON=function(r){if(Buffer.isEncoding("base64url"))return r instanceof Object?r:JSON.parse(r);throw new Error("Error: Base64URL encoding isn't available")};exports.parseToJSON=parseToJSON;var jwtEncode=function(r,e,o,t){var a=r;if(Buffer.isEncoding("base64url")){if(r instanceof Object){a=r;var s=JSON.stringify(r);Buffer.from(s,"ascii").toString("base64url")}else a=JSON.parse(r),Buffer.from(r,"ascii").toString("base64url");var n,i=createHeaderPayload(r,e),c=a.alg;if(c){switch(c.toLowerCase()){case"hs256":n=hs256Sign(i,o);break;case"rs256":if(!t||!t.keyFormat)throw new Error("Need to specify keyFormat in options for RS256 algorithm as either jwk or pem.");var f=t.keyFormat;"jwk"===f.toLowerCase()?n=rs256JWKSign(i,o):"pem"===f.toLowerCase()&&(n=t.passphrase?rs256PEMSign(i,o,t.passphrase):rs256PEMSign(i,o));break;default:throw new Error("Unsupported alg: ".concat(c))}return i+"."+n}throw new Error("Algorithm couldn't be determined. alg:"+c)}throw new Error("Error: Base64URL encoding isn't available.")};exports.jwtEncode=jwtEncode;var _default=jwtDecode;exports.default=_default; diff --git a/package-lock.json b/package-lock.json index fc3448c..3452c5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,23 @@ { "name": "jwt-authn", - "version": "1.0.35", + "version": "1.0.39", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jwt-authn", - "version": "1.0.35", - "license": "GNU GPLv3", + "version": "1.0.39", + "license": "MIT-Modern-Variant", + "dependencies": { + "clipboardy": "^2.3.0" + }, + "bin": { + "jwt-authn": "cli_lib/index.js" + }, "devDependencies": { "@babel/cli": "^7.13.14", "@babel/core": "^7.13.14", + "@babel/plugin-transform-runtime": "^7.13.15", "@babel/preset-env": "^7.13.12", "@babel/register": "^7.13.14", "@istanbuljs/nyc-config-babel": "^3.0.0", @@ -19,8 +26,10 @@ "chai": "^4.3.4", "core-js": "^3.10.0", "cross-env": "^7.0.3", + "minify": "^7.0.1", "mocha": "^8.3.2", - "nyc": "^15.1.0" + "nyc": "^15.1.0", + "sinon": "^10.0.0" }, "engines": { "node": ">=15.0" @@ -1044,6 +1053,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.13.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.15.tgz", + "integrity": "sha512-d+ezl76gx6Jal08XngJUkXM4lFXK/5Ikl9Mh4HKDxSfGJXmZ9xG64XT2oivBzfxb/eQ62VfvoMkaCZUKJMVrBA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-plugin-utils": "^7.13.0", + "babel-plugin-polyfill-corejs2": "^0.2.0", + "babel-plugin-polyfill-corejs3": "^0.2.0", + "babel-plugin-polyfill-regenerator": "^0.2.0", + "semver": "^6.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz", @@ -1422,6 +1448,41 @@ "node": ">=0.10.0" } }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -1507,6 +1568,25 @@ "node": ">=8" } }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -1834,6 +1914,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -2074,6 +2164,27 @@ "node": ">=0.10.0" } }, + "node_modules/clean-css": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.2.tgz", + "integrity": "sha512-QcaGg9OuMo+0Ds933yLOY+gHPWbxhxqF0HDexmToPf8pczvmvZGYzd+QqWp9/mkucAOKViI+dSFOqoZIvXbeBw==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2083,6 +2194,19 @@ "node": ">=6" } }, + "node_modules/clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dependencies": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -2293,6 +2417,18 @@ "node": ">= 8" } }, + "node_modules/css-b64-images": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", + "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=", + "dev": true, + "bin": { + "css-b64-images": "bin/css-b64-images" + }, + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -2388,6 +2524,16 @@ "node": ">=0.3.1" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/electron-to-chromium": { "version": "1.3.717", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.717.tgz", @@ -2400,6 +2546,14 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -2446,6 +2600,92 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -2851,6 +3091,17 @@ "node": ">=8.0.0" } }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -3035,6 +3286,71 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier-terser/node_modules/clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/html-minifier-terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/html-minifier-terser/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": { + "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==", + "dev": true + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3142,6 +3458,20 @@ "node": ">=0.10.0" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -3257,6 +3587,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3267,8 +3608,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/isobject": { "version": "3.0.1", @@ -3481,6 +3821,12 @@ "node": ">=6" } }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -3521,6 +3867,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "node_modules/log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -3603,6 +3955,15 @@ "node": ">=8" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -3761,6 +4122,26 @@ "node": ">=0.10.0" } }, + "node_modules/minify": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/minify/-/minify-7.0.1.tgz", + "integrity": "sha512-U3CjnPKRjPu3DxZX7NsB833r2ijbw9af3fHsaChn6o7BHKvaT/zxYDQ8Q/3W7VFXGDrnkAx6XBx3ggEf5KJm7A==", + "dev": true, + "dependencies": { + "clean-css": "^5.0.1", + "css-b64-images": "~0.2.5", + "debug": "^4.1.0", + "html-minifier-terser": "^5.1.1", + "terser": "^5.3.2", + "try-to-catch": "^3.0.0" + }, + "bin": { + "minify": "bin/minify.js" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -3999,6 +4380,34 @@ "node": ">=0.10.0" } }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", @@ -4035,6 +4444,25 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "engines": { + "node": ">=4" + } + }, "node_modules/nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -4412,11 +4840,18 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -4480,6 +4915,26 @@ "node": ">=8" } }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -4530,6 +4985,21 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -4659,6 +5129,15 @@ "node": ">=8" } }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4790,6 +5269,15 @@ "jsesc": "bin/jsesc" } }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -5002,8 +5490,55 @@ "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/sinon": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.1.0", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/slash": { "version": "2.0.0", @@ -5466,6 +6001,14 @@ "node": ">=8" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -5490,6 +6033,38 @@ "node": ">=4" } }, + "node_modules/terser": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.1.tgz", + "integrity": "sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "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==", + "dev": true + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -5576,6 +6151,21 @@ "node": ">=0.12.0" } }, + "node_modules/try-to-catch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-3.0.0.tgz", + "integrity": "sha512-eIm6ZXwR35jVF8By/HdbbkcaCDTBI5PpCPkejRKrYp0jyf/DbCCcRhHD7/O9jtFI3ewsqo9WctFEiJTS6i+CQA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -5899,8 +6489,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -6875,6 +7464,20 @@ "@babel/helper-plugin-utils": "^7.12.13" } }, + "@babel/plugin-transform-runtime": { + "version": "7.13.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.15.tgz", + "integrity": "sha512-d+ezl76gx6Jal08XngJUkXM4lFXK/5Ikl9Mh4HKDxSfGJXmZ9xG64XT2oivBzfxb/eQ62VfvoMkaCZUKJMVrBA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-plugin-utils": "^7.13.0", + "babel-plugin-polyfill-corejs2": "^0.2.0", + "babel-plugin-polyfill-corejs3": "^0.2.0", + "babel-plugin-polyfill-regenerator": "^0.2.0", + "semver": "^6.3.0" + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz", @@ -7198,6 +7801,41 @@ } } }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -7267,6 +7905,11 @@ "default-require-extensions": "^3.0.0" } }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==" + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -7525,6 +8168,16 @@ "get-intrinsic": "^1.0.2" } }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -7717,12 +8370,39 @@ } } }, + "clean-css": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.2.tgz", + "integrity": "sha512-QcaGg9OuMo+0Ds933yLOY+gHPWbxhxqF0HDexmToPf8pczvmvZGYzd+QqWp9/mkucAOKViI+dSFOqoZIvXbeBw==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "requires": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + } + }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -7892,6 +8572,12 @@ "which": "^2.0.1" } }, + "css-b64-images": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", + "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=", + "dev": true + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -7958,6 +8644,16 @@ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "electron-to-chromium": { "version": "1.3.717", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.717.tgz", @@ -7970,6 +8666,14 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -8000,6 +8704,70 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -8311,6 +9079,14 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -8451,6 +9227,57 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "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==", + "dev": true + } + } + } + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -8537,6 +9364,11 @@ "kind-of": "^6.0.2" } }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -8624,6 +9456,14 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -8634,8 +9474,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", @@ -8794,6 +9633,12 @@ "minimist": "^1.2.5" } }, + "just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -8828,6 +9673,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -8888,6 +9739,15 @@ } } }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -9021,6 +9881,20 @@ } } }, + "minify": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/minify/-/minify-7.0.1.tgz", + "integrity": "sha512-U3CjnPKRjPu3DxZX7NsB833r2ijbw9af3fHsaChn6o7BHKvaT/zxYDQ8Q/3W7VFXGDrnkAx6XBx3ggEf5KJm7A==", + "dev": true, + "requires": { + "clean-css": "^5.0.1", + "css-b64-images": "~0.2.5", + "debug": "^4.1.0", + "html-minifier-terser": "^5.1.1", + "terser": "^5.3.2", + "try-to-catch": "^3.0.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -9193,6 +10067,34 @@ "to-regex": "^3.0.1" } }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", @@ -9220,6 +10122,21 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + }, + "dependencies": { + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + } + } + }, "nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -9516,11 +10433,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -9566,6 +10487,26 @@ "release-zalgo": "^1.0.0" } }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -9604,6 +10545,23 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -9699,6 +10657,15 @@ "fromentries": "^1.2.0" } }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -9814,6 +10781,12 @@ } } }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -9982,8 +10955,44 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "sinon": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "slash": { "version": "2.0.0", @@ -10370,6 +11379,11 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -10385,6 +11399,31 @@ "has-flag": "^3.0.0" } }, + "terser": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.1.tgz", + "integrity": "sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "commander": { + "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==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -10454,6 +11493,18 @@ } } }, + "try-to-catch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-3.0.0.tgz", + "integrity": "sha512-eIm6ZXwR35jVF8By/HdbbkcaCDTBI5PpCPkejRKrYp0jyf/DbCCcRhHD7/O9jtFI3ewsqo9WctFEiJTS6i+CQA==", + "dev": true + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -10705,8 +11756,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "3.0.3", diff --git a/package.json b/package.json index a7b87fb..2494fea 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "jwt-authn", - "version": "1.0.39", + "version": "1.0.40", "description": "JWT decoder, encoder, and more with only Node >=15.x as a dependency.", "main": "./lib", "scripts": { - "build": "babel ./src -d ./lib", + "prepare": "npm run build", + "build": "npm run babelify && npm run minify", "test": "cross-env NODE_ENV=test nyc mocha test", - "prepublish": "npm run build" + "babelify": "babel ./src/index.js -d ./lib/ && babel ./cli/index.js -d ./cli_lib/", + "minify": "minify ./lib/index.js > ./lib/index.min.js && minify ./cli/index.js > ./cli/index.min.js" }, "repository": { "type": "git", @@ -52,6 +54,7 @@ "devDependencies": { "@babel/cli": "^7.13.14", "@babel/core": "^7.13.14", + "@babel/plugin-transform-runtime": "^7.13.15", "@babel/preset-env": "^7.13.12", "@babel/register": "^7.13.14", "@istanbuljs/nyc-config-babel": "^3.0.0", @@ -60,10 +63,11 @@ "chai": "^4.3.4", "core-js": "^3.10.0", "cross-env": "^7.0.3", + "minify": "^7.0.1", "mocha": "^8.3.2", - "nyc": "^15.1.0" + "nyc": "^15.1.0", + "sinon": "^10.0.0" }, - "prepublishOnly": "npm run build", "nyc": { "require": [ "@babel/register" @@ -75,5 +79,9 @@ }, "engines": { "node": ">=15.0" + }, + "bin": "./cli_lib/index.js", + "dependencies": { + "clipboardy": "^2.3.0" } } diff --git a/src/index.js b/src/index.js index 8125590..4cdb4ad 100644 --- a/src/index.js +++ b/src/index.js @@ -28,8 +28,8 @@ export const jwtDecode = (jwt) => { "utf8" ); if (!base64URLDecodedHeader) { - console.err("base64URLDecodedHeader"); - console.err(base64URLDecodedHeader); + console.error("base64URLDecodedHeader"); + console.error(base64URLDecodedHeader); throw new Error("Header isn't base64url encoded"); } @@ -75,13 +75,26 @@ export const jwtDecode = (jwt) => { }; } - throw new Error("Not using compact serialization (JWS)."); + throw new SyntaxError("Not using compact serialization (JWS)."); } catch (e) { - console.error(e.message, e); - return { header: null, payload: null, signature: null }; + // debugging(e); + throw e; } }; +const debugging = (e) => { + // debugging + console.error(e.message, e); + console.error("e instanceof SyntaxError"); + console.error(e instanceof SyntaxError); + console.error(e.message); + console.error(e.name); + console.error(e.fileName); + console.error(e.lineNumber); + console.error(e.columnNumber); + console.error(e.stack); +}; + /** * Uses HMAC with SHA256 to create the signature of a JWT. * @@ -141,6 +154,7 @@ export const rs256JWKSign = (headerPayload, privateKey) => { secret = privateKey; } else { console.error(e.message, e); + throw e; } } } else { @@ -369,12 +383,24 @@ export const createHeaderPayload = (header, payload) => { export const base64URLEncode = (jsonObject) => { if (Buffer.isEncoding("base64url")) { // not a string. convert to string - const stringifyHeader = JSON.stringify(jsonObject); + const stringify = JSON.stringify(jsonObject); // headerBase64URL = base64url.encode(stringifyHeader); - const payloadBase64URL = Buffer.from(stringifyHeader, "ascii").toString( - "base64url" - ); - return payloadBase64URL; + const base64URLify = Buffer.from(stringify, "ascii").toString("base64url"); + return base64URLify; + } else if (window) { + const b64c = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // base64 dictionary + const b64u = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; // base64url dictionary + const btoa = window.btoa(); + + const stringify = JSON.stringify(jsonObject); + const base64urlify = btoa(stringify); + // Remove trailing "=" + let s = base64urlify.split("=")[0]; + s = s.replace("+", "-"); + s = s.replace("/", "_"); + return s; } throw new Error("Error: Base64URL encoding isn't available"); @@ -420,7 +446,6 @@ export const parseToJSON = (input) => { */ export const jwtEncode = (header, payload, key, options) => { let headerBase64URL; - let payloadBase64URL; let jsonHeader = header; if (Buffer.isEncoding("base64url")) { diff --git a/src/index.min.js b/src/index.min.js new file mode 100644 index 0000000..ab4b1b6 --- /dev/null +++ b/src/index.min.js @@ -0,0 +1 @@ +import crypto from"crypto";export const jwtDecode=jwt=>{try{if(!jwt.includes("."))throw new Error("Need at least one '.'");const components=jwt.split("."),header=components[0],base64URLDecodedHeader=Buffer.from(header,"base64url").toString("utf8");if(!base64URLDecodedHeader)throw console.err("base64URLDecodedHeader"),console.err(base64URLDecodedHeader),new Error("Header isn't base64url encoded");const jsonHeader=JSON.parse(base64URLDecodedHeader),{typ:typ,cty:cty,alg:alg}=jsonHeader;if(typ&&"JWT"!==typ)throw new Error(`Need to be type jwt. Received: ${typ}`);if(cty&&"JWT"!==cty)throw new Error(`Need a cty of 'JWT'. Received: ${cty}`);if(!alg)throw new Error("Missing algorithm in JOSE header.");if(3===components.length){const payload=components[1],base64urlDecodedPayload=Buffer.from(payload,"base64url").toString("utf8"),jsonPayload=JSON.parse(base64urlDecodedPayload);return{header:jsonHeader,payload:jsonPayload,signature:components[2]}}throw new Error("Not using compact serialization (JWS).")}catch(e){return console.error(e.message,e),{header:null,payload:null,signature:null}}};export const hs256Sign=(headerPayload,key)=>{const secret=crypto.createSecretKey(key,"base64url"),hmac=crypto.createHmac("sha256",secret);hmac.update(headerPayload,"ascii");const hmacked=hmac.digest(),base64URLHmacked=Buffer.from(hmacked).toString("base64url");return base64URLHmacked};export const rs256JWKSign=(headerPayload,privateKey)=>{const hashes=crypto.getHashes();if(!hashes.includes("RSA-SHA256"))throw console.error("RSA-SHA256 not found"),new Error("RSA-SHA256 isn't available in the current system.");{let secret;try{try{secret=JSON.parse(privateKey)}catch(e){if(!JSON.stringify(privateKey))throw new Error("Not valid JSON.");secret=privateKey}const keyObject=crypto.createPrivateKey({key:secret,format:"jwk"}),sig=crypto.sign("sha256",Buffer.from(headerPayload),{key:keyObject}),sigBase64URL=sig.toString("base64url");return sigBase64URL}catch(e){e instanceof TypeError?secret=privateKey:console.error(e.message,e)}}return null};export const rs256PEMSign=(headerPayload,privateKey,passphrase)=>{const hashes=crypto.getHashes();let pemKey;if(!hashes.includes("RSA-SHA256"))return console.error("RSA-SHA256 not found"),null;try{pemKey=crypto.createPrivateKey({key:privateKey,format:"pem"})}catch(e){if(e instanceof TypeError&&e.message.includes("Passphrase required for encrypted key")){if(!passphrase)throw new Error("Need a passphrase since private key is encrypted");pemKey=crypto.createPrivateKey({key:privateKey,format:"pem",passphrase:passphrase})}}const sig=crypto.sign("sha256",Buffer.from(headerPayload),{key:pemKey}),sigBase64URL=sig.toString("base64url");return sigBase64URL};export const rs256JWKVerify=(jwt,publicKey)=>{const jwtComponents=jwt.split("."),headerPayload=jwtComponents[0]+"."+jwtComponents[1],signature=jwtComponents[2],keyObject=crypto.createPublicKey({key:publicKey,format:"jwk"}),isVerified=crypto.verify(null,Buffer.from(headerPayload,"ascii"),{key:keyObject},Buffer.from(signature,"base64url"));return isVerified};export const rs256PEMVerify=(jwt,publicKey)=>{const jwtComponents=jwt.split("."),headerPayload=jwtComponents[0]+"."+jwtComponents[1],signature=jwtComponents[2],keyObject=crypto.createPublicKey({key:publicKey,format:"pem"}),isVerified=crypto.verify(null,Buffer.from(headerPayload,"ascii"),{key:keyObject},Buffer.from(signature,"base64url"));return isVerified};export const hs256Verify=(jwt,passphrase,passphraseEncoding)=>{const jwtComponents=jwt.split("."),headerPayload=jwtComponents[0]+"."+jwtComponents[1],signature=jwtComponents[2];let secret=crypto.createSecretKey(passphrase,"base64url");secret=passphraseEncoding&&Buffer.isEncoding(passphraseEncoding)?crypto.createSecretKey(passphrase,passphraseEncoding):crypto.createSecretKey(passphrase,"base64url");const hmac=crypto.createHmac("sha256",secret);hmac.update(headerPayload,"ascii");const hmacked=hmac.digest(),base64URLHmacked=Buffer.from(hmacked).toString("base64url"),isVerified=base64URLHmacked===signature;return isVerified};export const createHeaderPayload=(header,payload)=>{if(Buffer.isEncoding("base64url")){let headerBase64URL,payloadBase64URL;if("string"==typeof header)headerBase64URL=Buffer.from(header,"ascii").toString("base64url");else{const jsonHeader=parseToJSON(header);headerBase64URL=base64URLEncode(jsonHeader)}if("string"==typeof payload)payloadBase64URL=Buffer.from(payload,"ascii").toString("base64url");else{const jsonPayload=parseToJSON(payload);payloadBase64URL=base64URLEncode(jsonPayload)}const headerPayload=`${headerBase64URL}.${payloadBase64URL}`;return headerPayload}throw new Error("Error: Base64URL encoding isn't available.")};export const base64URLEncode=jsonObject=>{if(Buffer.isEncoding("base64url")){const stringifyHeader=JSON.stringify(jsonObject),payloadBase64URL=Buffer.from(stringifyHeader,"ascii").toString("base64url");return payloadBase64URL}throw new Error("Error: Base64URL encoding isn't available")};export const parseToJSON=input=>{let json=input;if(Buffer.isEncoding("base64url"))return json=input instanceof Object?input:JSON.parse(input),json;throw new Error("Error: Base64URL encoding isn't available")};export const jwtEncode=(header,payload,key,options)=>{let headerBase64URL,payloadBase64URL,jsonHeader=header;if(Buffer.isEncoding("base64url")){if(header instanceof Object){jsonHeader=header;const stringifyHeader=JSON.stringify(header);headerBase64URL=Buffer.from(stringifyHeader,"ascii").toString("base64url")}else jsonHeader=JSON.parse(header),headerBase64URL=Buffer.from(header,"ascii").toString("base64url");const headerPayload=createHeaderPayload(header,payload),{alg:alg}=jsonHeader;let sig;if(alg){switch(alg.toLowerCase()){case"hs256":sig=hs256Sign(headerPayload,key);break;case"rs256":if(!options||!options.keyFormat)throw new Error("Need to specify keyFormat in options for RS256 algorithm as either jwk or pem.");{const keyFormat=options.keyFormat;"jwk"===keyFormat.toLowerCase()?sig=rs256JWKSign(headerPayload,key):"pem"===keyFormat.toLowerCase()&&(sig=options.passphrase?rs256PEMSign(headerPayload,key,options.passphrase):rs256PEMSign(headerPayload,key))}break;default:throw new Error(`Unsupported alg: ${alg}`)}return headerPayload+"."+sig}throw new Error("Algorithm couldn't be determined. alg:"+alg)}throw new Error("Error: Base64URL encoding isn't available.")};export default jwtDecode; \ No newline at end of file diff --git a/test/index.js b/test/index.js index 32eef34..b9f5bd6 100644 --- a/test/index.js +++ b/test/index.js @@ -11,6 +11,9 @@ import { createHeaderPayload, } from "../src/index.js"; import crypto from "crypto"; +import cli, { HELP_TEXT } from "../cli/index.js"; +import sinon from "sinon"; +import { spawn } from "child_process"; const expect = chai.expect; chai.config.includeStack = true; @@ -376,7 +379,7 @@ g8W+z36ROKfkVVbmEVHY1Kg9yMo7oKYZEIa5AcAZyxxDoedT0jnlBRaWLtM=\n-----END RSA PRIVA // Check that we can verify our JWT using the public key that's paired with the private key we used to sign the JWT. expect(rs256PEMVerify(encoded, publicKey)).to.be.true; done(); - }).timeout(3000); + }).timeout(10000); }); }); }); @@ -614,3 +617,120 @@ describe("Signing and Verification", () => { }); }); }); + +describe("#cli()", () => { + let sandbox; + before(() => { + sandbox = sinon.createSandbox(); + }); + beforeEach(() => { + sandbox.restore(); + }); + + describe("using help", () => { + context("when argument is -h", () => { + it("shows the help screen", () => { + const log = sandbox.spy(console, "log"); + // Mock process.argv + const processArgv = [0, 0, "-h"]; + cli(null, [0, 0, "-h"]); + expect(log.calledOnceWith(HELP_TEXT)).to.be.true; + }); + }); + + context("when argument is --help", () => { + it("shows the help screen", () => { + const log = sandbox.spy(console, "log"); + // Mock process.argv + const processArgv = [0, 0, "-h"]; + cli(null, [0, 0, "-h"]); + expect(log.calledOnceWith(HELP_TEXT)).to.be.true; + }); + }); + }); + + describe("mock using clipboard", () => { + context("when 'clipboard' contains a jwt", () => { + it("decodes the jwt", async () => { + const log = sandbox.spy(console, "log"); + const myCli = cli; + const spy = sandbox.spy(myCli); + + const clipboard = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; + const expectedOutput = { + header: { alg: "HS256", typ: "JWT" }, + payload: { sub: "1234567890", name: "John Doe", iat: 1516239022 }, + signature: "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", + }; + const cliOutput = await spy(clipboard, null); + + expect( + spy.calledOnceWith( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + ) + ).to.be.true; + expect(log.calledWith("Decoding: ")).to.be.true; + expect( + log.calledWith( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + ) + ).to.be.true; + expect( + log.getCall(2).firstArg, + "decoded jwt was logged to the console" + ).to.be.deep.equal(expectedOutput); + expect(expectedOutput).to.be.deep.equal(cliOutput); + }); + }); + + context("when 'clipboard' doesn't contain a jwt", () => { + context("when it's not in proper JSON format", () => { + it("throws a SyntaxError", async () => { + const err = sandbox.spy(console, "error"); + const spy = sandbox.spy(cli); + + const clipboard = "abc.abc.abc"; + let syntaxErr; + + try { + await spy(clipboard, null); + } catch (e) { + try { + syntaxErr = await spy.returnValues[0]; + } catch (ex) { + expect(ex instanceof SyntaxError).to.be.true; + } + } + + expect(err.calledWith("I found an error :(")).to.be.true; + expect(spy.called).to.be.true; + }); + }); + + context("when it doesn't contain a '.'", () => { + it("throws an error", async () => { + const err = sandbox.spy(console, "error"); + const spy = sandbox.spy(cli); + + const clipboard = "abc"; + let dotErr; + + try { + await spy(clipboard, null); + } catch (e) { + try { + dotErr = await spy.returnValues[0]; + } catch (ex) { + expect(ex instanceof Error).to.be.true; + expect(ex.message).to.equal("Need at least one '.'"); + } + } + + expect(err.calledWith("I found an error :(")).to.be.true; + expect(spy.called).to.be.true; + }); + }); + }); + }); +});