Upgrade octokit to v4.1.2
This commit is contained in:
parent
dbbcbe019d
commit
c1745a9831
1214 changed files with 160765 additions and 0 deletions
22
node_modules/universal-github-app-jwt/.github/workflows/release.yml
generated
vendored
Normal file
22
node_modules/universal-github-app-jwt/.github/workflows/release.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
"on":
|
||||
push:
|
||||
branches:
|
||||
- "*.x"
|
||||
- main
|
||||
- beta
|
||||
name: Release
|
||||
jobs:
|
||||
build:
|
||||
name: release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npx semantic-release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
33
node_modules/universal-github-app-jwt/.github/workflows/test.yml
generated
vendored
Normal file
33
node_modules/universal-github-app-jwt/.github/workflows/test.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: Test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
node:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
deno:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
- uses: denoland/setup-deno@v1
|
||||
with:
|
||||
deno-version: v1.x
|
||||
- run: npm ci
|
||||
- run: npm run build:default
|
||||
- run: npm run test:deno
|
||||
46
node_modules/universal-github-app-jwt/CODE_OF_CONDUCT.md
generated
vendored
Normal file
46
node_modules/universal-github-app-jwt/CODE_OF_CONDUCT.md
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at coc@martynus.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
21
node_modules/universal-github-app-jwt/LICENSE
generated
vendored
Normal file
21
node_modules/universal-github-app-jwt/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2019 Gregor Martynus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
237
node_modules/universal-github-app-jwt/README.md
generated
vendored
Normal file
237
node_modules/universal-github-app-jwt/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
# universal-github-app-jwt
|
||||
|
||||
> Calculate GitHub App bearer tokens for Node, Deno, and modern browsers
|
||||
|
||||
[](https://www.npmjs.com/universal-github-app-jwt)
|
||||
[](https://github.com/gr2m/universal-github-app-jwt/actions?query=workflow%3ATest+branch%3Amaster)
|
||||
|
||||
## Usage
|
||||
|
||||
<table>
|
||||
<tbody valign=top align=left>
|
||||
<tr><th>
|
||||
Browsers
|
||||
</th><td width=100%>
|
||||
Load <code>universal-github-app-jwt</code> directly from <a href="https://esm.sh">esm.sh</a>
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import githubAppJwt from "https://esm.sh/universal-github-app-jwt";
|
||||
</script>
|
||||
```
|
||||
|
||||
</td></tr>
|
||||
<tr><th>
|
||||
Node
|
||||
</th><td>
|
||||
|
||||
Install with <code>npm install universal-github-app-jwt</code>
|
||||
|
||||
```js
|
||||
import githubAppJwt from "universal-github-app-jwt";
|
||||
```
|
||||
|
||||
</td></tr>
|
||||
<tr><th>
|
||||
Deno
|
||||
</th><td>
|
||||
|
||||
Load <code>universal-github-app-jwt</code> directly from <a href="https://esm.sh">esm.sh</a>, including types.
|
||||
|
||||
```js
|
||||
import githubAppJwt from "https://esm.sh/universal-github-app-jwt";
|
||||
```
|
||||
|
||||
</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
```js
|
||||
const { token, appId, expiration } = await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATE_KEY,
|
||||
});
|
||||
```
|
||||
|
||||
The retrieved `token` can now be used in Authorization request header, e.g. with [`@octokit/request`](https://github.com/octokit/request.js/#readme):
|
||||
|
||||
```js
|
||||
request("GET /app", {
|
||||
headers: {
|
||||
authorization: `bearer ${token}`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
For a complete implementation of GitHub App authentication strategies, see [`@octokit/auth-app.js`](https://github.com/octokit/auth-app.js/#readme).
|
||||
|
||||
## `githubAppJwt(options)`
|
||||
|
||||
<table width="100%">
|
||||
<thead align=left>
|
||||
<tr>
|
||||
<th width=150>
|
||||
name
|
||||
</th>
|
||||
<th width=70>
|
||||
type
|
||||
</th>
|
||||
<th>
|
||||
description
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody align=left valign=top>
|
||||
<tr>
|
||||
<th>
|
||||
<code>options.id</code>
|
||||
</th>
|
||||
<th>
|
||||
<code>number | string</code>
|
||||
</th>
|
||||
<td>
|
||||
<strong>Required</strong>. The GitHub App's ID or Client ID. For <code>github.com</code> and GHES 3.14+, it is recommended to use the Client ID.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<code>options.privateKey</code>
|
||||
</th>
|
||||
<th>
|
||||
<code>string</code>
|
||||
</th>
|
||||
<td>
|
||||
<strong>Required</strong>. Content of the <code>*.pem</code> file you downloaded from the app’s about page. You can generate a new private key if needed. Make sure to preserve the line breaks. If your private key contains escaped newlines (`\\n`), they will be automatically replaced with actual newlines.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<code>options.now</code>
|
||||
</th>
|
||||
<th>
|
||||
<code>number</code>
|
||||
</th>
|
||||
<td>
|
||||
An optional override for the current time in seconds since the UNIX epoch. Defaults to <code>Math.floor(Date.now() / 1000))</code>. This value can be overridden to account for a time skew between the local machine and the authentication server.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
`githubAppJwt(options)` resolves with an object with the following keys
|
||||
|
||||
<table width="100%">
|
||||
<thead align=left>
|
||||
<tr>
|
||||
<th width=150>
|
||||
name
|
||||
</th>
|
||||
<th width=70>
|
||||
type
|
||||
</th>
|
||||
<th>
|
||||
description
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody align=left valign=top>
|
||||
<tr>
|
||||
<th>
|
||||
<code>token</code>
|
||||
</th>
|
||||
<th>
|
||||
<code>string</code>
|
||||
</th>
|
||||
<td>
|
||||
The JSON Web Token (JWT) to authenticate as the app.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<code>appId</code>
|
||||
</th>
|
||||
<th>
|
||||
<code>number</code>
|
||||
</th>
|
||||
<td>
|
||||
The GitHub App database ID or Client ID passed in <code>options.id</code>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<code>expiration</code>
|
||||
</th>
|
||||
<th>
|
||||
<code>number</code>
|
||||
</th>
|
||||
<td>
|
||||
Timestamp as UNIX epoch, e.g. <code>1530922170</code>. A Date object can be created using <code>new Date(authentication.expiration)</code>.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- do not remove this anchor, it's used in error messages -->
|
||||
|
||||
<a name="private-key-formats"></a>
|
||||
|
||||
## About Private Key formats
|
||||
|
||||
When downloading a `private-key.pem` file from GitHub, the format is in `PKCS#1` format. Unfortunately, the WebCrypto API only supports `PKCS#8`.
|
||||
|
||||
If you use 1Password to store a private key as an SSH key, it will be transformed to the `OpenSSH` format, which is also not supported by WebCrypto.
|
||||
|
||||
You can identify the format based on the the first line
|
||||
|
||||
| First Line | Format |
|
||||
| ------------------------------------- | ------- |
|
||||
| `-----BEGIN RSA PRIVATE KEY-----` | PKCS#1 |
|
||||
| `-----BEGIN PRIVATE KEY-----` | PKCS#8 |
|
||||
| `-----BEGIN OPENSSH PRIVATE KEY-----` | OpenSSH |
|
||||
|
||||
### Converting `PKCS#1` to `PKCS#8`
|
||||
|
||||
- #### Using an Online Private Key Converter
|
||||
|
||||
Convert quickly using the Web interface at https://private-key-converter.vercel.app
|
||||
|
||||
- #### Using Node.js
|
||||
|
||||
If you use Node.js, you can convert the format before passing it to `universal-github-app-jwt`:
|
||||
|
||||
```js
|
||||
import crypto from "node:crypto";
|
||||
import githubAppJwt from "universal-github-app-jwt";
|
||||
|
||||
const privateKeyPkcs8 = crypto
|
||||
.createPrivateKey(process.env.PRIVATE_KEY)
|
||||
.export({
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
});
|
||||
|
||||
const { token, appId, expiration } = await githubAppJwt({
|
||||
id: process.env.APP_ID,
|
||||
privateKey: privateKeyPkcs8,
|
||||
});
|
||||
```
|
||||
|
||||
- #### Using OpenSSL
|
||||
|
||||
Convert the format using `openssl` before passing it to your app.
|
||||
|
||||
```
|
||||
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private-key.pem -out private-key-pkcs8.key
|
||||
```
|
||||
|
||||
### Converting `OpenSSH` to `PKCS#8`
|
||||
|
||||
```
|
||||
cp private-key.pem private-key-pkcs8.key && ssh-keygen -m PKCS8 -N "" -f private-key-pkcs8.key
|
||||
```
|
||||
|
||||
I'm looking for help to create a minimal `OpenSSH` to `PKCS` convert library that I can recommend people to use before passing the private key to `githubAppJwt`. Please create an issue if you'd like to help.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
13
node_modules/universal-github-app-jwt/index.d.ts
generated
vendored
Normal file
13
node_modules/universal-github-app-jwt/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export type Options<IdType extends number | string = number> = {
|
||||
id: IdType;
|
||||
privateKey: string;
|
||||
now?: number;
|
||||
};
|
||||
|
||||
export type Result<IdType extends number | string = number> = {
|
||||
appId: IdType extends string ? string : number;
|
||||
expiration: number;
|
||||
token: string;
|
||||
};
|
||||
|
||||
export default function githubAppJwt<T extends number | string = number>(options: Options<T>): Promise<Result<T>>;
|
||||
42
node_modules/universal-github-app-jwt/index.js
generated
vendored
Normal file
42
node_modules/universal-github-app-jwt/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// @ts-check
|
||||
|
||||
// @ts-ignore - #get-token is defined in "imports" in package.json
|
||||
import { getToken } from "./lib/get-token.js";
|
||||
|
||||
/**
|
||||
* @param {import(".").Options} options
|
||||
* @returns {Promise<import(".").Result>}
|
||||
*/
|
||||
export default async function githubAppJwt({
|
||||
id,
|
||||
privateKey,
|
||||
now = Math.floor(Date.now() / 1000),
|
||||
}) {
|
||||
// Private keys are often times configured as environment variables, in which case line breaks are escaped using `\\n`.
|
||||
// Replace these here for convenience.
|
||||
const privateKeyWithNewlines = privateKey.replace(/\\n/g, '\n');
|
||||
|
||||
// When creating a JSON Web Token, it sets the "issued at time" (iat) to 30s
|
||||
// in the past as we have seen people running situations where the GitHub API
|
||||
// claimed the iat would be in future. It turned out the clocks on the
|
||||
// different machine were not in sync.
|
||||
const nowWithSafetyMargin = now - 30;
|
||||
const expiration = nowWithSafetyMargin + 60 * 10; // JWT expiration time (10 minute maximum)
|
||||
|
||||
const payload = {
|
||||
iat: nowWithSafetyMargin, // Issued at time
|
||||
exp: expiration,
|
||||
iss: id,
|
||||
};
|
||||
|
||||
const token = await getToken({
|
||||
privateKey: privateKeyWithNewlines,
|
||||
payload,
|
||||
});
|
||||
|
||||
return {
|
||||
appId: id,
|
||||
expiration,
|
||||
token,
|
||||
};
|
||||
}
|
||||
25
node_modules/universal-github-app-jwt/index.test-d.ts
generated
vendored
Normal file
25
node_modules/universal-github-app-jwt/index.test-d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { expectType } from "tsd";
|
||||
import githubAppJwt from ".";
|
||||
|
||||
export async function test() {
|
||||
const result = await githubAppJwt({
|
||||
id: 123,
|
||||
privateKey: "",
|
||||
});
|
||||
|
||||
expectType<number>(result.appId);
|
||||
expectType<number>(result.expiration);
|
||||
expectType<string>(result.token);
|
||||
}
|
||||
|
||||
// Test case to verify `id` can be set to a string
|
||||
export async function testWithStringId() {
|
||||
const resultWithStringId = await githubAppJwt({
|
||||
id: "client_id_string",
|
||||
privateKey: "",
|
||||
});
|
||||
|
||||
expectType<string>(resultWithStringId.appId);
|
||||
expectType<number>(resultWithStringId.expiration);
|
||||
expectType<string>(resultWithStringId.token);
|
||||
}
|
||||
16
node_modules/universal-github-app-jwt/internals.d.ts
generated
vendored
Normal file
16
node_modules/universal-github-app-jwt/internals.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
export type Payload = {
|
||||
iat: number;
|
||||
exp: number;
|
||||
iss: number | string;
|
||||
};
|
||||
|
||||
export type Header = { alg: "RS256"; typ: "JWT" };
|
||||
|
||||
export type GetTokenOptions = {
|
||||
privateKey: string;
|
||||
payload: Payload;
|
||||
};
|
||||
|
||||
export interface GetToken {
|
||||
(options: GetTokenOptions): Promise<string>;
|
||||
}
|
||||
5
node_modules/universal-github-app-jwt/jsconfig.json
generated
vendored
Normal file
5
node_modules/universal-github-app-jwt/jsconfig.json
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}
|
||||
8
node_modules/universal-github-app-jwt/lib/crypto-native.js
generated
vendored
Normal file
8
node_modules/universal-github-app-jwt/lib/crypto-native.js
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
const { subtle } = globalThis.crypto;
|
||||
|
||||
// no-op, unfortunately there is no way to transform from PKCS8 or OpenSSH to PKCS1 with WebCrypto
|
||||
function convertPrivateKey(privateKey) {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
export { subtle, convertPrivateKey };
|
||||
15
node_modules/universal-github-app-jwt/lib/crypto-node.js
generated
vendored
Normal file
15
node_modules/universal-github-app-jwt/lib/crypto-node.js
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// this can be removed once we only support Node 20+
|
||||
export * from "node:crypto";
|
||||
import { createPrivateKey } from "node:crypto";
|
||||
|
||||
import { isPkcs1 } from "./utils.js";
|
||||
|
||||
// no-op, unfortunately there is no way to transform from PKCS8 or OpenSSH to PKCS1 with WebCrypto
|
||||
export function convertPrivateKey(privateKey) {
|
||||
if (!isPkcs1(privateKey)) return privateKey;
|
||||
|
||||
return createPrivateKey(privateKey).export({
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
});
|
||||
}
|
||||
66
node_modules/universal-github-app-jwt/lib/get-token.js
generated
vendored
Normal file
66
node_modules/universal-github-app-jwt/lib/get-token.js
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// we don't @ts-check here because it chokes crypto which is a global API in modern JS runtime environments
|
||||
|
||||
import {
|
||||
isPkcs1,
|
||||
isOpenSsh,
|
||||
getEncodedMessage,
|
||||
getDERfromPEM,
|
||||
string2ArrayBuffer,
|
||||
base64encode,
|
||||
} from "./utils.js";
|
||||
|
||||
import { subtle, convertPrivateKey } from "#crypto";
|
||||
|
||||
/**
|
||||
* @param {import('../internals').GetTokenOptions} options
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export async function getToken({ privateKey, payload }) {
|
||||
const convertedPrivateKey = convertPrivateKey(privateKey);
|
||||
|
||||
// WebCrypto only supports PKCS#8, unfortunately
|
||||
/* c8 ignore start */
|
||||
if (isPkcs1(convertedPrivateKey)) {
|
||||
throw new Error(
|
||||
"[universal-github-app-jwt] Private Key is in PKCS#1 format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats"
|
||||
);
|
||||
}
|
||||
/* c8 ignore stop */
|
||||
|
||||
// WebCrypto does not support OpenSSH, unfortunately
|
||||
if (isOpenSsh(convertedPrivateKey)) {
|
||||
throw new Error(
|
||||
"[universal-github-app-jwt] Private Key is in OpenSSH format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats"
|
||||
);
|
||||
}
|
||||
|
||||
const algorithm = {
|
||||
name: "RSASSA-PKCS1-v1_5",
|
||||
hash: { name: "SHA-256" },
|
||||
};
|
||||
|
||||
/** @type {import('../internals').Header} */
|
||||
const header = { alg: "RS256", typ: "JWT" };
|
||||
|
||||
const privateKeyDER = getDERfromPEM(convertedPrivateKey);
|
||||
const importedKey = await subtle.importKey(
|
||||
"pkcs8",
|
||||
privateKeyDER,
|
||||
algorithm,
|
||||
false,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const encodedMessage = getEncodedMessage(header, payload);
|
||||
const encodedMessageArrBuf = string2ArrayBuffer(encodedMessage);
|
||||
|
||||
const signatureArrBuf = await subtle.sign(
|
||||
algorithm.name,
|
||||
importedKey,
|
||||
encodedMessageArrBuf
|
||||
);
|
||||
|
||||
const encodedSignature = base64encode(signatureArrBuf);
|
||||
|
||||
return `${encodedMessage}.${encodedSignature}`;
|
||||
}
|
||||
85
node_modules/universal-github-app-jwt/lib/utils.js
generated
vendored
Normal file
85
node_modules/universal-github-app-jwt/lib/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// we don't @ts-check here because it chokes on atob and btoa which are available in all modern JS runtime environments
|
||||
|
||||
/**
|
||||
* @param {string} privateKey
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPkcs1(privateKey) {
|
||||
return privateKey.includes("-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} privateKey
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isOpenSsh(privateKey) {
|
||||
return privateKey.includes("-----BEGIN OPENSSH PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
export function string2ArrayBuffer(str) {
|
||||
const buf = new ArrayBuffer(str.length);
|
||||
const bufView = new Uint8Array(buf);
|
||||
for (let i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} pem
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
export function getDERfromPEM(pem) {
|
||||
const pemB64 = pem
|
||||
.trim()
|
||||
.split("\n")
|
||||
.slice(1, -1) // Remove the --- BEGIN / END PRIVATE KEY ---
|
||||
.join("");
|
||||
|
||||
const decoded = atob(pemB64);
|
||||
return string2ArrayBuffer(decoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../internals').Header} header
|
||||
* @param {import('../internals').Payload} payload
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getEncodedMessage(header, payload) {
|
||||
return `${base64encodeJSON(header)}.${base64encodeJSON(payload)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} buffer
|
||||
* @returns {string}
|
||||
*/
|
||||
export function base64encode(buffer) {
|
||||
var binary = "";
|
||||
var bytes = new Uint8Array(buffer);
|
||||
var len = bytes.byteLength;
|
||||
for (var i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
|
||||
return fromBase64(btoa(binary));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} base64
|
||||
* @returns {string}
|
||||
*/
|
||||
function fromBase64(base64) {
|
||||
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string,unknown>} obj
|
||||
* @returns {string}
|
||||
*/
|
||||
function base64encodeJSON(obj) {
|
||||
return fromBase64(btoa(JSON.stringify(obj)));
|
||||
}
|
||||
62
node_modules/universal-github-app-jwt/package.json
generated
vendored
Normal file
62
node_modules/universal-github-app-jwt/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"name": "universal-github-app-jwt",
|
||||
"type": "module",
|
||||
"version": "2.2.0",
|
||||
"exports": "./index.js",
|
||||
"imports": {
|
||||
"#crypto": {
|
||||
"node": "./lib/crypto-node.js",
|
||||
"default": "./lib/crypto-native.js"
|
||||
}
|
||||
},
|
||||
"description": "Calculate GitHub App bearer tokens for Node & modern browsers",
|
||||
"repository": "github:gr2m/universal-github-app-jwt",
|
||||
"keywords": [
|
||||
"github",
|
||||
"authentication",
|
||||
"app",
|
||||
"jwt",
|
||||
"webcrypto"
|
||||
],
|
||||
"author": "Gregor Martynus (https://github.com/gr2m)",
|
||||
"scripts": {
|
||||
"test": "npm run test:code && npm run test:tsc && npm run test:tsd && npm run lint",
|
||||
"test:code": "c8 --100 ava test/node.test.js",
|
||||
"test:deno": "deno test test/deno.test.js",
|
||||
"test:tsc": "tsc --allowJs --noEmit --esModuleInterop --skipLibCheck --lib es2020 index.js",
|
||||
"test:tsd": "tsd",
|
||||
"lint": "prettier --check '{src,test}/**/*' README.md package.json",
|
||||
"lint:fix": "prettier --write '{src,test}/**/*' README.md package.json",
|
||||
"coverage": "c8 report --reporter html",
|
||||
"postcoverage": "open-cli coverage/index.html",
|
||||
"build": "npm run build:default && npm run build:node",
|
||||
"build:default": "esbuild index.js --bundle --outfile=dist/default.js --platform=browser --target=es2020 --format=esm",
|
||||
"build:node": "esbuild index.js --bundle --outfile=dist/node.js --platform=node --target=es2020 --format=esm"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"ava": "^6.0.0",
|
||||
"c8": "^9.0.0",
|
||||
"esbuild": "^0.20.0",
|
||||
"mockdate": "^3.0.5",
|
||||
"open-cli": "^8.0.0",
|
||||
"prettier": "^3.0.0",
|
||||
"tsd": "^0.31.0",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"release": {
|
||||
"branches": [
|
||||
"+([0-9]).x",
|
||||
"main",
|
||||
{
|
||||
"name": "beta",
|
||||
"prerelease": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"renovate": {
|
||||
"extends": [
|
||||
"github>gr2m/.github"
|
||||
]
|
||||
}
|
||||
}
|
||||
49
node_modules/universal-github-app-jwt/test/deno.test.js
generated
vendored
Normal file
49
node_modules/universal-github-app-jwt/test/deno.test.js
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import githubAppJwt from "../dist/default.js";
|
||||
|
||||
const APP_ID = 1;
|
||||
const PRIVATE_KEY = `-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDVzv73Pk9p3s56
|
||||
N5yxDRu7dqjM3e2KE+aWOee51v0bccQJ2ceVa7b9rWAH0lblMFD4BWm6b06THsp+
|
||||
qR8Eov2ZweBIvTJYx2Mx806o22tCoqU3iQSnpEP77uwZvNt9n1qvCuUP8dIMBYZ0
|
||||
YYlNI4Ezqkd6HIuZILcMmhH8JO7S9MZNZdCs7rhny3JdA+1U9v9hetxSFsGnyLvZ
|
||||
v1eTLR8Po+QR5s7LQinnxdUCfZQ82U05I9LJ75CO2K6zQx3g2J7j5fyTBUjZCOTd
|
||||
1KbSzD/vbQomR1UOatrJ6WO0oHHoC01CxJeDNBt4yaKoUWTCsbX7PHoTsfuOohD0
|
||||
Hpu9YpcbAgMBAAECggEAPyQEE8vo8+ECpQErWvX+DJx8ORQJBE/gNtke37jnwmUU
|
||||
ebxAvpWy0rOSunyZgNGF99jRYmdgkv3y2vji2iGwNuoUbCbDaYhoeOXbgu5ZfLI/
|
||||
jGkAYOmX0hy6yNcHEtAunabgApdtanNvQ4tSWt9zVmig9yTa7PvGUwhk60uU4+Mv
|
||||
PYO56NV7bglzDAfOtBYo58DXVH/17nQNWx6GdIf/DjpDvrfLgjQTcEihQyyiUQrO
|
||||
HbJ0ADLOSBpsZAFS5qZmi01+8mgNd4KLUsPzI0JbJOViklkkMNeigFTkQCwK+E3W
|
||||
xJGhpdauUxIMHuv8T5pDIq5rgo42q+agm4LbW9Ip4QKBgQDvJbrAGRWg2GBeeTxd
|
||||
Jm/db5DTG11WmJ0l40YFadzOVmu6aa3jHDfGzrNX6sZQPLn3IOQrAEqMwxrjYyeL
|
||||
tP0XHz4QpS6FUrc9VDJqOjJCoXBPUY5Ek3Nz95hDpVg4JILw7JmawEzan7QPgUXb
|
||||
9pvBI8ybLQ2DIUsJQVVzc4QKmQKBgQDk4CYjfC3mz5yWDXypLsEpHYO44VavM1Vw
|
||||
dheGPHy85JZXTfc7LfK91QECG70DUtSqnDIxr66ciDGa+ZQxAR3IdAxyAGxWzXR1
|
||||
H+DbEaMwtzCPqSf7GvclUhmdtFPnRi4+F/6ezVJx2E/q6mj0jT+xGwi433oZvrkk
|
||||
nH3iBDiT0wKBgE7lXqADZoxC9kAUtSJyDNO7+8Z5r6hi/u1B9pbQnwT/o9jDBpf3
|
||||
djtDdA1cKgLMlfl+w2egV/fqYhOEYcaIdjrLltk89YUMjeFQxrUe7/fldLzmRg4/
|
||||
qwYmN/iRMvKKsRw0olRYfsJdj7TRzC9OQ4JLgjPrgBqzwCKUiFFnWbd5AoGBAJRb
|
||||
Wz1rNBHGB5kYWvMLdHfjQsvnfRoJ61r/oVYJBU4n2e/zgMtiiFNWq9WjB00NNv70
|
||||
SnD8kPG0MntjRhTRxW13E84dyhwmB1QYetdlwmNEi3zDyD+zhfoyEpqwFib2zejA
|
||||
AvMK4mMbNQpwMeI7YMq7XFcBvRLNFxPNQKft1oKzAoGBAM5g9nYkaaGJuoqOMsWb
|
||||
SrOlxDpE+88rX/uDQ0ieaM8x5s/Qrp5I/HT3/j0npZMP74RqM3sWGS1RJjG6R1Zo
|
||||
KhwBAlMM1g/Qrzwbiu0LYhjLkkWf1JbPmiHH//S77N39H9BFTMs7Dg3vb8e75Qbo
|
||||
w23mINkUK1qlFoq3o69IHDLz
|
||||
-----END PRIVATE KEY-----`;
|
||||
// see https://runkit.com/gr2m/reproducable-jwt
|
||||
const BEARER =
|
||||
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOi0zMCwiZXhwIjo1NzAsImlzcyI6MX0.q3foRa78U3WegM5PrWLEh5N0bH1SD62OqW66ZYzArp95JBNiCbo8KAlGtiRENCIfBZT9ibDUWy82cI4g3F09mdTq3bD1xLavIfmTksIQCz5EymTWR5v6gL14LSmQdWY9lSqkgUG0XCFljWUglEP39H4yeHbFgdjvAYg3ifDS12z9oQz2ACdSpvxPiTuCC804HkPVw8Qoy0OSXvCkFU70l7VXCVUxnuhHnk8-oCGcKUspmeP6UdDnXk-Aus-eGwDfJbU2WritxxaXw6B4a3flTPojkYLSkPBr6Pi0H2-mBsW_Nvs0aLPVLKobQd4gqTkosX3967DoAG8luUMhrnxe8Q";
|
||||
|
||||
// url_test.ts
|
||||
import { assertEquals } from "https://deno.land/std@0.168.0/testing/asserts.ts";
|
||||
|
||||
Deno.test("url test", async () => {
|
||||
const result = await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATE_KEY,
|
||||
now: 0,
|
||||
});
|
||||
|
||||
assertEquals(result.appId, 1);
|
||||
assertEquals(result.expiration, 570);
|
||||
assertEquals(result.token, BEARER);
|
||||
});
|
||||
192
node_modules/universal-github-app-jwt/test/node.test.js
generated
vendored
Normal file
192
node_modules/universal-github-app-jwt/test/node.test.js
generated
vendored
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
import test from "ava";
|
||||
import MockDate from "mockdate";
|
||||
|
||||
import githubAppJwt from "../index.js";
|
||||
|
||||
const APP_ID = 1;
|
||||
|
||||
// private key in pkcs1 format, as it's provided by GitHub
|
||||
const PRIVATE_KEY_PKCS1 = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA1c7+9z5Pad7OejecsQ0bu3aozN3tihPmljnnudb9G3HECdnH
|
||||
lWu2/a1gB9JW5TBQ+AVpum9Okx7KfqkfBKL9mcHgSL0yWMdjMfNOqNtrQqKlN4kE
|
||||
p6RD++7sGbzbfZ9arwrlD/HSDAWGdGGJTSOBM6pHehyLmSC3DJoR/CTu0vTGTWXQ
|
||||
rO64Z8tyXQPtVPb/YXrcUhbBp8i72b9Xky0fD6PkEebOy0Ip58XVAn2UPNlNOSPS
|
||||
ye+Qjtius0Md4Nie4+X8kwVI2Qjk3dSm0sw/720KJkdVDmrayeljtKBx6AtNQsSX
|
||||
gzQbeMmiqFFkwrG1+zx6E7H7jqIQ9B6bvWKXGwIDAQABAoIBAD8kBBPL6PPhAqUB
|
||||
K1r1/gycfDkUCQRP4DbZHt+458JlFHm8QL6VstKzkrp8mYDRhffY0WJnYJL98tr4
|
||||
4tohsDbqFGwmw2mIaHjl24LuWXyyP4xpAGDpl9IcusjXBxLQLp2m4AKXbWpzb0OL
|
||||
Ulrfc1ZooPck2uz7xlMIZOtLlOPjLz2DuejVe24JcwwHzrQWKOfA11R/9e50DVse
|
||||
hnSH/w46Q763y4I0E3BIoUMsolEKzh2ydAAyzkgabGQBUuamZotNfvJoDXeCi1LD
|
||||
8yNCWyTlYpJZJDDXooBU5EAsCvhN1sSRoaXWrlMSDB7r/E+aQyKua4KONqvmoJuC
|
||||
21vSKeECgYEA7yW6wBkVoNhgXnk8XSZv3W+Q0xtdVpidJeNGBWnczlZrummt4xw3
|
||||
xs6zV+rGUDy59yDkKwBKjMMa42Mni7T9Fx8+EKUuhVK3PVQyajoyQqFwT1GORJNz
|
||||
c/eYQ6VYOCSC8OyZmsBM2p+0D4FF2/abwSPMmy0NgyFLCUFVc3OECpkCgYEA5OAm
|
||||
I3wt5s+clg18qS7BKR2DuOFWrzNVcHYXhjx8vOSWV033Oy3yvdUBAhu9A1LUqpwy
|
||||
Ma+unIgxmvmUMQEdyHQMcgBsVs10dR/g2xGjMLcwj6kn+xr3JVIZnbRT50YuPhf+
|
||||
ns1ScdhP6upo9I0/sRsIuN96Gb65JJx94gQ4k9MCgYBO5V6gA2aMQvZAFLUicgzT
|
||||
u/vGea+oYv7tQfaW0J8E/6PYwwaX93Y7Q3QNXCoCzJX5fsNnoFf36mIThGHGiHY6
|
||||
y5bZPPWFDI3hUMa1Hu/35XS85kYOP6sGJjf4kTLyirEcNKJUWH7CXY+00cwvTkOC
|
||||
S4Iz64Aas8AilIhRZ1m3eQKBgQCUW1s9azQRxgeZGFrzC3R340LL530aCeta/6FW
|
||||
CQVOJ9nv84DLYohTVqvVowdNDTb+9Epw/JDxtDJ7Y0YU0cVtdxPOHcocJgdUGHrX
|
||||
ZcJjRIt8w8g/s4X6MhKasBYm9s3owALzCuJjGzUKcDHiO2DKu1xXAb0SzRcTzUCn
|
||||
7daCswKBgQDOYPZ2JGmhibqKjjLFm0qzpcQ6RPvPK1/7g0NInmjPMebP0K6eSPx0
|
||||
9/49J6WTD++EajN7FhktUSYxukdWaCocAQJTDNYP0K88G4rtC2IYy5JFn9SWz5oh
|
||||
x//0u+zd/R/QRUzLOw4N72/Hu+UG6MNt5iDZFCtapRaKt6OvSBwy8w==
|
||||
-----END RSA PRIVATE KEY-----`;
|
||||
|
||||
// pkcs8 version of the key above, which is pkcs1
|
||||
// see https://stackoverflow.com/questions/51033786/how-can-i-import-an-rsa-private-key-in-pem-format-for-use-with-webcrypto/51035703#51035703
|
||||
const PRIVATE_KEY_PKCS8 = `-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDVzv73Pk9p3s56
|
||||
N5yxDRu7dqjM3e2KE+aWOee51v0bccQJ2ceVa7b9rWAH0lblMFD4BWm6b06THsp+
|
||||
qR8Eov2ZweBIvTJYx2Mx806o22tCoqU3iQSnpEP77uwZvNt9n1qvCuUP8dIMBYZ0
|
||||
YYlNI4Ezqkd6HIuZILcMmhH8JO7S9MZNZdCs7rhny3JdA+1U9v9hetxSFsGnyLvZ
|
||||
v1eTLR8Po+QR5s7LQinnxdUCfZQ82U05I9LJ75CO2K6zQx3g2J7j5fyTBUjZCOTd
|
||||
1KbSzD/vbQomR1UOatrJ6WO0oHHoC01CxJeDNBt4yaKoUWTCsbX7PHoTsfuOohD0
|
||||
Hpu9YpcbAgMBAAECggEAPyQEE8vo8+ECpQErWvX+DJx8ORQJBE/gNtke37jnwmUU
|
||||
ebxAvpWy0rOSunyZgNGF99jRYmdgkv3y2vji2iGwNuoUbCbDaYhoeOXbgu5ZfLI/
|
||||
jGkAYOmX0hy6yNcHEtAunabgApdtanNvQ4tSWt9zVmig9yTa7PvGUwhk60uU4+Mv
|
||||
PYO56NV7bglzDAfOtBYo58DXVH/17nQNWx6GdIf/DjpDvrfLgjQTcEihQyyiUQrO
|
||||
HbJ0ADLOSBpsZAFS5qZmi01+8mgNd4KLUsPzI0JbJOViklkkMNeigFTkQCwK+E3W
|
||||
xJGhpdauUxIMHuv8T5pDIq5rgo42q+agm4LbW9Ip4QKBgQDvJbrAGRWg2GBeeTxd
|
||||
Jm/db5DTG11WmJ0l40YFadzOVmu6aa3jHDfGzrNX6sZQPLn3IOQrAEqMwxrjYyeL
|
||||
tP0XHz4QpS6FUrc9VDJqOjJCoXBPUY5Ek3Nz95hDpVg4JILw7JmawEzan7QPgUXb
|
||||
9pvBI8ybLQ2DIUsJQVVzc4QKmQKBgQDk4CYjfC3mz5yWDXypLsEpHYO44VavM1Vw
|
||||
dheGPHy85JZXTfc7LfK91QECG70DUtSqnDIxr66ciDGa+ZQxAR3IdAxyAGxWzXR1
|
||||
H+DbEaMwtzCPqSf7GvclUhmdtFPnRi4+F/6ezVJx2E/q6mj0jT+xGwi433oZvrkk
|
||||
nH3iBDiT0wKBgE7lXqADZoxC9kAUtSJyDNO7+8Z5r6hi/u1B9pbQnwT/o9jDBpf3
|
||||
djtDdA1cKgLMlfl+w2egV/fqYhOEYcaIdjrLltk89YUMjeFQxrUe7/fldLzmRg4/
|
||||
qwYmN/iRMvKKsRw0olRYfsJdj7TRzC9OQ4JLgjPrgBqzwCKUiFFnWbd5AoGBAJRb
|
||||
Wz1rNBHGB5kYWvMLdHfjQsvnfRoJ61r/oVYJBU4n2e/zgMtiiFNWq9WjB00NNv70
|
||||
SnD8kPG0MntjRhTRxW13E84dyhwmB1QYetdlwmNEi3zDyD+zhfoyEpqwFib2zejA
|
||||
AvMK4mMbNQpwMeI7YMq7XFcBvRLNFxPNQKft1oKzAoGBAM5g9nYkaaGJuoqOMsWb
|
||||
SrOlxDpE+88rX/uDQ0ieaM8x5s/Qrp5I/HT3/j0npZMP74RqM3sWGS1RJjG6R1Zo
|
||||
KhwBAlMM1g/Qrzwbiu0LYhjLkkWf1JbPmiHH//S77N39H9BFTMs7Dg3vb8e75Qbo
|
||||
w23mINkUK1qlFoq3o69IHDLz
|
||||
-----END PRIVATE KEY-----`;
|
||||
|
||||
// openssh version of the key above
|
||||
// see https://github.com/gr2m/universal-github-app-jwt/issues/72
|
||||
const PRIVATEY_KEY_OPENSSH = `-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAQEA1c7+9z5Pad7OejecsQ0bu3aozN3tihPmljnnudb9G3HECdnHlWu2
|
||||
/a1gB9JW5TBQ+AVpum9Okx7KfqkfBKL9mcHgSL0yWMdjMfNOqNtrQqKlN4kEp6RD++7sGb
|
||||
zbfZ9arwrlD/HSDAWGdGGJTSOBM6pHehyLmSC3DJoR/CTu0vTGTWXQrO64Z8tyXQPtVPb/
|
||||
YXrcUhbBp8i72b9Xky0fD6PkEebOy0Ip58XVAn2UPNlNOSPSye+Qjtius0Md4Nie4+X8kw
|
||||
VI2Qjk3dSm0sw/720KJkdVDmrayeljtKBx6AtNQsSXgzQbeMmiqFFkwrG1+zx6E7H7jqIQ
|
||||
9B6bvWKXGwAAA7hJqTyJSak8iQAAAAdzc2gtcnNhAAABAQDVzv73Pk9p3s56N5yxDRu7dq
|
||||
jM3e2KE+aWOee51v0bccQJ2ceVa7b9rWAH0lblMFD4BWm6b06THsp+qR8Eov2ZweBIvTJY
|
||||
x2Mx806o22tCoqU3iQSnpEP77uwZvNt9n1qvCuUP8dIMBYZ0YYlNI4Ezqkd6HIuZILcMmh
|
||||
H8JO7S9MZNZdCs7rhny3JdA+1U9v9hetxSFsGnyLvZv1eTLR8Po+QR5s7LQinnxdUCfZQ8
|
||||
2U05I9LJ75CO2K6zQx3g2J7j5fyTBUjZCOTd1KbSzD/vbQomR1UOatrJ6WO0oHHoC01CxJ
|
||||
eDNBt4yaKoUWTCsbX7PHoTsfuOohD0Hpu9YpcbAAAAAwEAAQAAAQA/JAQTy+jz4QKlASta
|
||||
9f4MnHw5FAkET+A22R7fuOfCZRR5vEC+lbLSs5K6fJmA0YX32NFiZ2CS/fLa+OLaIbA26h
|
||||
RsJsNpiGh45duC7ll8sj+MaQBg6ZfSHLrI1wcS0C6dpuACl21qc29Di1Ja33NWaKD3JNrs
|
||||
+8ZTCGTrS5Tj4y89g7no1XtuCXMMB860FijnwNdUf/XudA1bHoZ0h/8OOkO+t8uCNBNwSK
|
||||
FDLKJRCs4dsnQAMs5IGmxkAVLmpmaLTX7yaA13gotSw/MjQlsk5WKSWSQw16KAVORALAr4
|
||||
TdbEkaGl1q5TEgwe6/xPmkMirmuCjjar5qCbgttb0inhAAAAgQDOYPZ2JGmhibqKjjLFm0
|
||||
qzpcQ6RPvPK1/7g0NInmjPMebP0K6eSPx09/49J6WTD++EajN7FhktUSYxukdWaCocAQJT
|
||||
DNYP0K88G4rtC2IYy5JFn9SWz5ohx//0u+zd/R/QRUzLOw4N72/Hu+UG6MNt5iDZFCtapR
|
||||
aKt6OvSBwy8wAAAIEA7yW6wBkVoNhgXnk8XSZv3W+Q0xtdVpidJeNGBWnczlZrummt4xw3
|
||||
xs6zV+rGUDy59yDkKwBKjMMa42Mni7T9Fx8+EKUuhVK3PVQyajoyQqFwT1GORJNzc/eYQ6
|
||||
VYOCSC8OyZmsBM2p+0D4FF2/abwSPMmy0NgyFLCUFVc3OECpkAAACBAOTgJiN8LebPnJYN
|
||||
fKkuwSkdg7jhVq8zVXB2F4Y8fLzklldN9zst8r3VAQIbvQNS1KqcMjGvrpyIMZr5lDEBHc
|
||||
h0DHIAbFbNdHUf4NsRozC3MI+pJ/sa9yVSGZ20U+dGLj4X/p7NUnHYT+rqaPSNP7EbCLjf
|
||||
ehm+uSScfeIEOJPTAAAAAAEC
|
||||
-----END OPENSSH PRIVATE KEY-----`;
|
||||
|
||||
// see https://runkit.com/gr2m/reproducable-jwt
|
||||
const BEARER =
|
||||
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOi0zMCwiZXhwIjo1NzAsImlzcyI6MX0.q3foRa78U3WegM5PrWLEh5N0bH1SD62OqW66ZYzArp95JBNiCbo8KAlGtiRENCIfBZT9ibDUWy82cI4g3F09mdTq3bD1xLavIfmTksIQCz5EymTWR5v6gL14LSmQdWY9lSqkgUG0XCFljWUglEP39H4yeHbFgdjvAYg3ifDS12z9oQz2ACdSpvxPiTuCC804HkPVw8Qoy0OSXvCkFU70l7VXCVUxnuhHnk8-oCGcKUspmeP6UdDnXk-Aus-eGwDfJbU2WritxxaXw6B4a3flTPojkYLSkPBr6Pi0H2-mBsW_Nvs0aLPVLKobQd4gqTkosX3967DoAG8luUMhrnxe8Q";
|
||||
|
||||
test("README example for app auth with private key in PKCS#8 format", async (t) => {
|
||||
MockDate.set(0);
|
||||
|
||||
const result = await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATE_KEY_PKCS8,
|
||||
});
|
||||
|
||||
t.deepEqual(result, {
|
||||
appId: APP_ID,
|
||||
expiration: 570,
|
||||
token: BEARER,
|
||||
});
|
||||
});
|
||||
|
||||
test("README example for app auth with private key in PKCS#1 format", async (t) => {
|
||||
MockDate.set(0);
|
||||
|
||||
const result = await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATE_KEY_PKCS1,
|
||||
});
|
||||
|
||||
t.deepEqual(result, {
|
||||
appId: APP_ID,
|
||||
expiration: 570,
|
||||
token: BEARER,
|
||||
});
|
||||
});
|
||||
|
||||
test("Throws error if key is OpenSSH", async (t) => {
|
||||
MockDate.set(0);
|
||||
|
||||
try {
|
||||
await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATEY_KEY_OPENSSH,
|
||||
});
|
||||
t.fail("should throw");
|
||||
} catch (error) {
|
||||
t.is(
|
||||
error.message,
|
||||
"[universal-github-app-jwt] Private Key is in OpenSSH format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats",
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("Include the time difference in the expiration and issued_at field", async (t) => {
|
||||
MockDate.set(0);
|
||||
|
||||
const result = await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATE_KEY_PKCS8,
|
||||
now: 10,
|
||||
});
|
||||
|
||||
t.is(result.appId, APP_ID);
|
||||
t.is(result.expiration, 580);
|
||||
|
||||
const resultPayload = JSON.parse(atob(result.token.split(".")[1]));
|
||||
t.is(resultPayload.exp, 580);
|
||||
t.is(resultPayload.iat, -20);
|
||||
});
|
||||
|
||||
test("Replace escaped line breaks with actual linebreaks", async (t) => {
|
||||
MockDate.set(0);
|
||||
|
||||
const result = await githubAppJwt({
|
||||
id: APP_ID,
|
||||
privateKey: PRIVATE_KEY_PKCS8.replace(/\n/g, "\\n"),
|
||||
});
|
||||
|
||||
t.deepEqual(result, {
|
||||
appId: APP_ID,
|
||||
expiration: 570,
|
||||
token: BEARER,
|
||||
});
|
||||
});
|
||||
|
||||
// New test for id set to Client ID
|
||||
test("id set to Client ID", async (t) => {
|
||||
MockDate.set(0);
|
||||
|
||||
const result = await githubAppJwt({
|
||||
id: "client_id_string",
|
||||
privateKey: PRIVATE_KEY_PKCS8,
|
||||
});
|
||||
|
||||
t.is(typeof result.token, "string");
|
||||
t.is(result.appId, "client_id_string");
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue