├── .gitignore ├── .vscode └── settings.json ├── README.md ├── bin └── jsonwebtokenydoo.js ├── lib └── private-key.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # sass cache 61 | .sass-cache 62 | style.css.map 63 | 64 | *.pem 65 | 66 | dump.rdb 67 | 68 | dist 69 | 70 | .DS_Store -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 2, 3 | "editor.formatOnSave": true 4 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jsonwebtokenydoo 2 | 3 | Command line utility that assists with GitHub App Authentication 4 | 5 | ![jsonwebtokenydoo](https://user-images.githubusercontent.com/7718702/39935423-debeff6a-5540-11e8-8f4c-e3a347c415a4.gif) 6 | 7 | ## Installation 8 | 9 | * Install as dev dependency: `npm install --save-dev jsonwebtokenydoo` 10 | * Run using `ghtoken` 11 | 12 | This installation assumes that the current `/node_modules/.bin` is in your `PATH`. If you don't have this set up already you can add the following to your `~/.bashrc` or `~/.zshrc`: 13 | 14 | ``` 15 | export PATH=${PATH}:node_modules/.bin/ 16 | ``` 17 | 18 | `jsonwebtokenydoo` assumes that you have a private key (.pem file) in your current directory or that you have a `PRIVATE_KEY` or `PRIVATE_KEY_PATH` environment variable set via your `.env` file. This is the default pattern for [Probot apps](https://github.com/probot/probot). 19 | 20 | `jsonwebtokenydoo` will automatically detect your app id if it's set as an `APP_ID` environment variable via your `.env` file. If it can't detect your app id, it will ask you for it. 21 | 22 | ## Run directly 23 | 24 | Don't want to install `jsonwebtokenydoo` as a dev dependency? 25 | You can run it directly with `npx jsonwebtokenydoo` 26 | 27 | Note that `jsonwebtokenydoo` still expects a private key (.pem file) in your current directory or a `PRIVATE_KEY` or `PRIVATE_KEY_PATH` environment variable set via your `.env` file. 28 | -------------------------------------------------------------------------------- /bin/jsonwebtokenydoo.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const inquirer = require("inquirer"); 4 | const jwt = require("jsonwebtoken"); 5 | const chalk = require("chalk"); 6 | const axios = require("axios"); 7 | require("dotenv").config(); 8 | 9 | const { findPrivateKey } = require("../lib/private-key"); 10 | 11 | function printInstallationCurl(jwt, url, resourceNameOrId) { 12 | const completeUrl = url.replace(":something", chalk.bold(resourceNameOrId)); 13 | console.log( 14 | chalk.grey("\nMaking request to get installation id:\n"), 15 | "curl -i \\\n", 16 | `-H "Authorization: Bearer ${chalk.green(jwt)}" \\\n`, 17 | '-H "Accept: application/vnd.github.machine-man-preview+json" \\\n', 18 | completeUrl 19 | ); 20 | } 21 | 22 | async function main() { 23 | let appId = process.env.APP_ID; 24 | if (!appId) { 25 | ({ appId } = await inquirer.prompt([ 26 | { 27 | type: "input", 28 | name: "appId", 29 | message: 30 | "Could not automatically find your APP_ID. Please enter your app id" 31 | } 32 | ])); 33 | } 34 | if (!appId) { 35 | console.log("You need to enter an app id to use this tool."); 36 | process.exit(1); 37 | } 38 | const cert = findPrivateKey(); 39 | const signedJWT = jwt.sign( 40 | { 41 | iat: Math.floor(new Date() / 1000), // Issued at time 42 | exp: Math.floor(new Date() / 1000) + 60, // JWT expiration time 43 | iss: appId 44 | }, 45 | cert, 46 | { algorithm: "RS256" } 47 | ); 48 | const config = { 49 | headers: { 50 | Authorization: `Bearer ${signedJWT}`, 51 | Accept: "application/vnd.github.machine-man-preview+json" 52 | } 53 | }; 54 | console.log( 55 | `${chalk.bold("Signed JWT (valid for 60 minutes)")}\n${chalk.green( 56 | signedJWT 57 | )}\n\n` 58 | ); 59 | let { installationId } = await inquirer.prompt([ 60 | { 61 | type: "input", 62 | name: "installationId", 63 | message: "Do you know the installation id? (Leave blank if not)" 64 | } 65 | ]); 66 | if (!installationId) { 67 | const { resource } = await inquirer.prompt([ 68 | { 69 | type: "list", 70 | name: "resource", 71 | message: 72 | "Based on which resource do you want to generate an installation token?", 73 | choices: ["user", "org", "repo"] 74 | } 75 | ]); 76 | const idQuestion = { 77 | type: "list", 78 | name: "idAnswer", 79 | message: `Do you have the ${resource} id or the ${resource} name?`, 80 | choices: ["id", "name"] 81 | }; 82 | let idAnswer; 83 | if (resource === "user" || resource === "org") { 84 | ({ idAnswer } = await inquirer.prompt(idQuestion)); 85 | } 86 | 87 | const { resourceNameOrId } = await inquirer.prompt([ 88 | { 89 | type: "input", 90 | name: "resourceNameOrId", 91 | message: `Please enter the ${resource} ${idAnswer}` 92 | } 93 | ]); 94 | let response; 95 | try { 96 | if (resource === "user") { 97 | if (idAnswer === "name") { 98 | printInstallationCurl( 99 | signedJWT, 100 | "https://api.github.com/users/:something/installation", 101 | resourceNameOrId 102 | ); 103 | response = await axios.get( 104 | `https://api.github.com/users/${resourceNameOrId}/installation`, 105 | config 106 | ); 107 | } else { 108 | printInstallationCurl( 109 | signedJWT, 110 | "https://api.github.com/user/:something/installation", 111 | resourceNameOrId 112 | ); 113 | response = await axios.get( 114 | `https://api.github.com/user/${resourceNameOrId}/installation`, 115 | config 116 | ); 117 | } 118 | } else if (resource == "org") { 119 | if (idAnswer === "name") { 120 | printInstallationCurl( 121 | signedJWT, 122 | "https://api.github.com/orgs/:something/installation", 123 | resourceNameOrId 124 | ); 125 | response = await axios.get( 126 | `https://api.github.com/orgs/${resourceNameOrId}/installation`, 127 | config 128 | ); 129 | } else { 130 | printInstallationCurl( 131 | signedJWT, 132 | "https://api.github.com/organizations/:something/installation", 133 | resourceNameOrId 134 | ); 135 | response = await axios.get( 136 | `https://api.github.com/organizations/${resourceNameOrId}/installation`, 137 | config 138 | ); 139 | } 140 | } else { 141 | printInstallationCurl( 142 | signedJWT, 143 | "https://api.github.com/repositories/:something/installation", 144 | resourceNameOrId 145 | ); 146 | response = await axios.get( 147 | `https://api.github.com/repositories/${resourceNameOrId}/installation`, 148 | config 149 | ); 150 | } 151 | } catch (e) { 152 | console.log(e.response); 153 | process.exit(1); 154 | } 155 | installationId = response.data.id; 156 | console.log(chalk.bold("Installation id:"), installationId); 157 | } 158 | console.log( 159 | chalk.grey("\nMaking request to generate installation token:\n"), 160 | "curl -i -X POST \\\n", 161 | `-H "Authorization: Bearer ${chalk.green(signedJWT)}" \\\n`, 162 | '-H "Accept: application/vnd.github.machine-man-preview+json" \\\n', 163 | `https://api.github.com/installations/${chalk.bold( 164 | installationId 165 | )}/access_tokens` 166 | ); 167 | let data; 168 | try { 169 | ({ data } = await axios.post( 170 | `https://api.github.com/installations/${installationId}/access_tokens`, 171 | null, 172 | config 173 | )); 174 | } catch (e) { 175 | console.log(e.response); 176 | process.exit(1); 177 | } 178 | console.log( 179 | chalk.bold("\nYour installation token"), 180 | "\n", 181 | JSON.stringify(data, null, 4) 182 | ); 183 | console.log( 184 | `Go forth and make requests with your ✨ ${chalk.keyword("orange")( 185 | "tokens" 186 | )} ✨` 187 | // here is a request you can make to get you started 188 | ); 189 | } 190 | 191 | main(); 192 | -------------------------------------------------------------------------------- /lib/private-key.js: -------------------------------------------------------------------------------- 1 | // Copied from: https://github.com/probot/probot/blob/1bace4c32c681efa119992b4f44e5f8d642a6fa2/lib/private-key.js 2 | const fs = require("fs"); 3 | 4 | const hint = `please use: 5 | * \`PRIVATE_KEY\` environment variable, or 6 | * \`PRIVATE_KEY_PATH\` environment variable 7 | `; 8 | 9 | function findPrivateKey(filepath) { 10 | if (filepath) { 11 | return fs.readFileSync(filepath); 12 | } 13 | if (process.env.PRIVATE_KEY) { 14 | return process.env.PRIVATE_KEY.replace(/\\n/g, "\n"); 15 | } 16 | if (process.env.PRIVATE_KEY_PATH) { 17 | return fs.readFileSync(process.env.PRIVATE_KEY_PATH); 18 | } 19 | const pemFiles = fs 20 | .readdirSync(process.cwd()) 21 | .filter(path => path.endsWith(".pem")); 22 | if (pemFiles.length > 1) { 23 | throw new Error( 24 | `Found several private keys: ${pemFiles.join(", ")}. ` + 25 | `To avoid ambiguity ${hint}` 26 | ); 27 | } else if (pemFiles[0]) { 28 | return findPrivateKey(pemFiles[0]); 29 | } 30 | throw new Error(`Missing private key for GitHub App, ${hint}`); 31 | } 32 | 33 | module.exports = { 34 | findPrivateKey 35 | }; 36 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonwebtokenydoo", 3 | "version": "1.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-escapes": { 8 | "version": "3.1.0", 9 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", 10 | "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" 11 | }, 12 | "ansi-regex": { 13 | "version": "3.0.0", 14 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 15 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 16 | }, 17 | "ansi-styles": { 18 | "version": "3.2.1", 19 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 20 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 21 | "requires": { 22 | "color-convert": "^1.9.0" 23 | } 24 | }, 25 | "axios": { 26 | "version": "0.26.0", 27 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", 28 | "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", 29 | "requires": { 30 | "follow-redirects": "^1.14.8" 31 | } 32 | }, 33 | "base64url": { 34 | "version": "2.0.0", 35 | "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", 36 | "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" 37 | }, 38 | "buffer-equal-constant-time": { 39 | "version": "1.0.1", 40 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 41 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 42 | }, 43 | "chalk": { 44 | "version": "2.4.1", 45 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 46 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 47 | "requires": { 48 | "ansi-styles": "^3.2.1", 49 | "escape-string-regexp": "^1.0.5", 50 | "supports-color": "^5.3.0" 51 | } 52 | }, 53 | "chardet": { 54 | "version": "0.4.2", 55 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 56 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" 57 | }, 58 | "cli-cursor": { 59 | "version": "2.1.0", 60 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 61 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 62 | "requires": { 63 | "restore-cursor": "^2.0.0" 64 | } 65 | }, 66 | "cli-width": { 67 | "version": "2.2.0", 68 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 69 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" 70 | }, 71 | "color-convert": { 72 | "version": "1.9.1", 73 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", 74 | "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", 75 | "requires": { 76 | "color-name": "^1.1.1" 77 | } 78 | }, 79 | "color-name": { 80 | "version": "1.1.3", 81 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 82 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 83 | }, 84 | "dotenv": { 85 | "version": "5.0.1", 86 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", 87 | "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==" 88 | }, 89 | "ecdsa-sig-formatter": { 90 | "version": "1.0.9", 91 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", 92 | "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", 93 | "requires": { 94 | "base64url": "^2.0.0", 95 | "safe-buffer": "^5.0.1" 96 | } 97 | }, 98 | "escape-string-regexp": { 99 | "version": "1.0.5", 100 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 101 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 102 | }, 103 | "external-editor": { 104 | "version": "2.2.0", 105 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 106 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 107 | "requires": { 108 | "chardet": "^0.4.0", 109 | "iconv-lite": "^0.4.17", 110 | "tmp": "^0.0.33" 111 | } 112 | }, 113 | "figures": { 114 | "version": "2.0.0", 115 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 116 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 117 | "requires": { 118 | "escape-string-regexp": "^1.0.5" 119 | } 120 | }, 121 | "follow-redirects": { 122 | "version": "1.14.8", 123 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", 124 | "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" 125 | }, 126 | "has-flag": { 127 | "version": "3.0.0", 128 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 129 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 130 | }, 131 | "iconv-lite": { 132 | "version": "0.4.23", 133 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 134 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 135 | "requires": { 136 | "safer-buffer": ">= 2.1.2 < 3" 137 | } 138 | }, 139 | "inquirer": { 140 | "version": "5.2.0", 141 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", 142 | "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", 143 | "requires": { 144 | "ansi-escapes": "^3.0.0", 145 | "chalk": "^2.0.0", 146 | "cli-cursor": "^2.1.0", 147 | "cli-width": "^2.0.0", 148 | "external-editor": "^2.1.0", 149 | "figures": "^2.0.0", 150 | "lodash": "^4.3.0", 151 | "mute-stream": "0.0.7", 152 | "run-async": "^2.2.0", 153 | "rxjs": "^5.5.2", 154 | "string-width": "^2.1.0", 155 | "strip-ansi": "^4.0.0", 156 | "through": "^2.3.6" 157 | } 158 | }, 159 | "is-fullwidth-code-point": { 160 | "version": "2.0.0", 161 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 162 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 163 | }, 164 | "is-promise": { 165 | "version": "2.1.0", 166 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 167 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 168 | }, 169 | "jsonwebtoken": { 170 | "version": "8.2.1", 171 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.2.1.tgz", 172 | "integrity": "sha512-l8rUBr0fqYYwPc8/ZGrue7GiW7vWdZtZqelxo4Sd5lMvuEeCK8/wS54sEo6tJhdZ6hqfutsj6COgC0d1XdbHGw==", 173 | "requires": { 174 | "jws": "^3.1.4", 175 | "lodash.includes": "^4.3.0", 176 | "lodash.isboolean": "^3.0.3", 177 | "lodash.isinteger": "^4.0.4", 178 | "lodash.isnumber": "^3.0.3", 179 | "lodash.isplainobject": "^4.0.6", 180 | "lodash.isstring": "^4.0.1", 181 | "lodash.once": "^4.0.0", 182 | "ms": "^2.1.1", 183 | "xtend": "^4.0.1" 184 | } 185 | }, 186 | "jwa": { 187 | "version": "1.1.5", 188 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", 189 | "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", 190 | "requires": { 191 | "base64url": "2.0.0", 192 | "buffer-equal-constant-time": "1.0.1", 193 | "ecdsa-sig-formatter": "1.0.9", 194 | "safe-buffer": "^5.0.1" 195 | } 196 | }, 197 | "jws": { 198 | "version": "3.1.4", 199 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", 200 | "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", 201 | "requires": { 202 | "base64url": "^2.0.0", 203 | "jwa": "^1.1.4", 204 | "safe-buffer": "^5.0.1" 205 | } 206 | }, 207 | "lodash": { 208 | "version": "4.17.10", 209 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 210 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 211 | }, 212 | "lodash.includes": { 213 | "version": "4.3.0", 214 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 215 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" 216 | }, 217 | "lodash.isboolean": { 218 | "version": "3.0.3", 219 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 220 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" 221 | }, 222 | "lodash.isinteger": { 223 | "version": "4.0.4", 224 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 225 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" 226 | }, 227 | "lodash.isnumber": { 228 | "version": "3.0.3", 229 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 230 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" 231 | }, 232 | "lodash.isplainobject": { 233 | "version": "4.0.6", 234 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 235 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" 236 | }, 237 | "lodash.isstring": { 238 | "version": "4.0.1", 239 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 240 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" 241 | }, 242 | "lodash.once": { 243 | "version": "4.1.1", 244 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 245 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" 246 | }, 247 | "mimic-fn": { 248 | "version": "1.2.0", 249 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 250 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" 251 | }, 252 | "ms": { 253 | "version": "2.1.1", 254 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 255 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 256 | }, 257 | "mute-stream": { 258 | "version": "0.0.7", 259 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 260 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" 261 | }, 262 | "onetime": { 263 | "version": "2.0.1", 264 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 265 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 266 | "requires": { 267 | "mimic-fn": "^1.0.0" 268 | } 269 | }, 270 | "os-tmpdir": { 271 | "version": "1.0.2", 272 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 273 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 274 | }, 275 | "restore-cursor": { 276 | "version": "2.0.0", 277 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 278 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 279 | "requires": { 280 | "onetime": "^2.0.0", 281 | "signal-exit": "^3.0.2" 282 | } 283 | }, 284 | "run-async": { 285 | "version": "2.3.0", 286 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 287 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 288 | "requires": { 289 | "is-promise": "^2.1.0" 290 | } 291 | }, 292 | "rxjs": { 293 | "version": "5.5.10", 294 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz", 295 | "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==", 296 | "requires": { 297 | "symbol-observable": "1.0.1" 298 | } 299 | }, 300 | "safe-buffer": { 301 | "version": "5.1.2", 302 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 303 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 304 | }, 305 | "safer-buffer": { 306 | "version": "2.1.2", 307 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 308 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 309 | }, 310 | "signal-exit": { 311 | "version": "3.0.2", 312 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 313 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 314 | }, 315 | "string-width": { 316 | "version": "2.1.1", 317 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 318 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 319 | "requires": { 320 | "is-fullwidth-code-point": "^2.0.0", 321 | "strip-ansi": "^4.0.0" 322 | } 323 | }, 324 | "strip-ansi": { 325 | "version": "4.0.0", 326 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 327 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 328 | "requires": { 329 | "ansi-regex": "^3.0.0" 330 | } 331 | }, 332 | "supports-color": { 333 | "version": "5.4.0", 334 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 335 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 336 | "requires": { 337 | "has-flag": "^3.0.0" 338 | } 339 | }, 340 | "symbol-observable": { 341 | "version": "1.0.1", 342 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", 343 | "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" 344 | }, 345 | "through": { 346 | "version": "2.3.8", 347 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 348 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 349 | }, 350 | "tmp": { 351 | "version": "0.0.33", 352 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 353 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 354 | "requires": { 355 | "os-tmpdir": "~1.0.2" 356 | } 357 | }, 358 | "xtend": { 359 | "version": "4.0.1", 360 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 361 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 362 | } 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonwebtokenydoo", 3 | "version": "1.1.0", 4 | "description": "Command line utility that assists with GitHub App Authentication", 5 | "bin": { 6 | "ghtoken": "./bin/jsonwebtokenydoo.js", 7 | "jsonwebtokenydoo": "./bin/jsonwebtokenydoo.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [ 13 | "github", 14 | "app", 15 | "jwt", 16 | "json", 17 | "web", 18 | "token" 19 | ], 20 | "author": "Wilhelm Klopp", 21 | "license": "ISC", 22 | "dependencies": { 23 | "axios": "^0.26.0", 24 | "chalk": "^2.4.1", 25 | "dotenv": "^5.0.1", 26 | "inquirer": "^5.2.0", 27 | "jsonwebtoken": "^8.2.1" 28 | } 29 | } --------------------------------------------------------------------------------