Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e244ff0618 | |||
|
|
13943f64d7 | ||
| 8952a12e4f | |||
| af3ea4cf8d | |||
| d99e361d65 | |||
| 79f030a35a | |||
| 5fd472c33d | |||
| 54ad90f6fd | |||
| 8d9f70ca36 | |||
| e34e1aedab | |||
| d31254de78 | |||
| 8fadfab966 | |||
| 187bd60b57 | |||
| f905176573 | |||
| 39c3fb790d | |||
| 5d8345996a | |||
| eebc0e988a | |||
| bf90a7c855 | |||
| 6e0ce1cf82 | |||
| 4ed24b18c5 | |||
| d12809e15d | |||
| 7a093c2c85 | |||
| 14a9631b8b | |||
| c247675832 | |||
| 0d3c7d621a | |||
| 62479197f5 | |||
| 0a3a9b58d1 | |||
| 959a7c9490 | |||
| e7be1ed840 | |||
| f2adb27218 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
github: tsndr
|
||||||
19
.github/workflows/lint.yml
vendored
Normal file
19
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 15.x
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run lint --if-present
|
||||||
30
.github/workflows/publish.yml
vendored
Normal file
30
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-npm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
- run: npm publish --access public
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||||
|
|
||||||
|
publish-gpr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12
|
||||||
|
registry-url: https://npm.pkg.github.com/
|
||||||
|
- run: npm publish --access public
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
144
.gitignore
vendored
Normal file
144
.gitignore
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# node.js
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Tobias Schneider
|
||||||
|
|
||||||
|
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.
|
||||||
163
README.md
163
README.md
@@ -2,66 +2,121 @@
|
|||||||
|
|
||||||
A lightweight JWT implementation with ZERO dependencies for Cloudflare Workers.
|
A lightweight JWT implementation with ZERO dependencies for Cloudflare Workers.
|
||||||
|
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Install](#install)
|
- [Install](#install)
|
||||||
|
- [Examples](#examples)
|
||||||
## Usage
|
- [Usage](#usage)
|
||||||
|
|
||||||
### Simple Example
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const jwt = require('@tsndr/cloudflare-worker-jwt')
|
|
||||||
|
|
||||||
// Creating a token
|
|
||||||
const token = jwt.sign({ name: 'John Doe', email: 'john.doe@gmail.com' }, 'secret')
|
|
||||||
|
|
||||||
// Verifing token
|
|
||||||
const isValid = jwt.verify(token, secret)
|
|
||||||
|
|
||||||
// Decoding token
|
|
||||||
const payload = jwt.decode(token)
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### `jwt.sign(payload, secret, [algorithm])`
|
|
||||||
|
|
||||||
Signs a payload and returns the token.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
`payload`
|
|
||||||
Can be an object, buffer or a string.
|
|
||||||
|
|
||||||
`secret`
|
|
||||||
A string which is used to sign the payload.
|
|
||||||
|
|
||||||
`algorithm` (optional, default: `HS256`)
|
|
||||||
The algorithm used to sign the payload, possible values: `HS256`(default) or `HS512`
|
|
||||||
|
|
||||||
|
|
||||||
### `jwt.verify(token, secret, [algorithm])`
|
|
||||||
|
|
||||||
Verifies the integrity of the token and returns a boolean value.
|
|
||||||
|
|
||||||
`token`
|
|
||||||
The token string generated by `jwt.sign()`.
|
|
||||||
|
|
||||||
`secret`
|
|
||||||
A string which is used to sign the payload.
|
|
||||||
|
|
||||||
`algorithm` (optional, default: `HS256`)
|
|
||||||
The algorithm used to sign the payload, possible values: `HS256`(default) or `HS512`
|
|
||||||
|
|
||||||
### `jwt.decode(token)`
|
|
||||||
Returns the payload without verifying the integrity of the token.
|
|
||||||
|
|
||||||
`token`
|
|
||||||
The token string generated by `jwt.sign()`.
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
```
|
```
|
||||||
npm i @tsndr/cloudflare-worker-jwt
|
npm i -D @tsndr/cloudflare-worker-jwt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async () => {
|
||||||
|
const jwt = require('@tsndr/cloudflare-worker-jwt')
|
||||||
|
|
||||||
|
// Creating a token
|
||||||
|
const token = await jwt.sign({ name: 'John Doe', email: 'john.doe@gmail.com' }, 'secret')
|
||||||
|
|
||||||
|
// Verifing token
|
||||||
|
const isValid = await jwt.verify(token, 'secret')
|
||||||
|
|
||||||
|
// Check for validity
|
||||||
|
if (!isValid)
|
||||||
|
return
|
||||||
|
|
||||||
|
// Decoding token
|
||||||
|
const payload = jwt.decode(token)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restrict Timeframe
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async () => {
|
||||||
|
const jwt = require('@tsndr/cloudflare-worker-jwt')
|
||||||
|
|
||||||
|
// Creating a token
|
||||||
|
const token = await jwt.sign({
|
||||||
|
name: 'John Doe',
|
||||||
|
email: 'john.doe@gmail.com',
|
||||||
|
nbf: Math.floor(Date.now() / 1000) + (60 * 60), // Not before: Now + 1h
|
||||||
|
exp: Math.floor(Date.now() / 1000) + (2 * (60 * 60)) // Expires: Now + 2h
|
||||||
|
}, 'secret')
|
||||||
|
|
||||||
|
// Verifing token
|
||||||
|
const isValid = await jwt.verify(token, 'secret') // false
|
||||||
|
|
||||||
|
// Check for validity
|
||||||
|
if (!isValid)
|
||||||
|
return
|
||||||
|
|
||||||
|
// Decoding token
|
||||||
|
const payload = jwt.decode(token) // { name: 'John Doe', email: 'john.doe@gmail.com', ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
### `jwt.sign(payload, secret, [options])`
|
||||||
|
|
||||||
|
Signs a payload and returns the token.
|
||||||
|
|
||||||
|
#### Arguments
|
||||||
|
|
||||||
|
Argument | Type | Satus | Default | Description
|
||||||
|
----------- | -------- | -------- | ------- | -----------
|
||||||
|
`payload` | `object` | required | - | The payload object. To use `nbf` (Not Before) and/or `exp` (Expiration Time) add `nbf` and/or `exp` to the payload.
|
||||||
|
`secret` | `string` | required | - | A string which is used to sign the payload.
|
||||||
|
`options` | `object`, `string` | optional | `{ algorithm: 'HS256' }` | The options object supporting `algorithm` and `keyid` or just the algorithm string. (See [Available Algorithms](#available-algorithms))
|
||||||
|
|
||||||
|
#### `return`
|
||||||
|
Returns token as a `string`.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
### `jwt.verify(token, secret, [options])`
|
||||||
|
|
||||||
|
Verifies the integrity of the token and returns a boolean value.
|
||||||
|
|
||||||
|
Argument | Type | Satus | Default | Description
|
||||||
|
----------- | -------- | -------- | ------- | -----------
|
||||||
|
`token` | `string` | required | - | The token string generated by `jwt.sign()`.
|
||||||
|
`secret` | `string` | required | - | The string which was used to sign the payload.
|
||||||
|
`algorithm` | `object`, `string` | optional | `{ algorithm: 'HS256' }` | The options object supporting `algorithm` or just the algorithm string. (See [Available Algorithms](#available-algorithms))
|
||||||
|
|
||||||
|
#### `return`
|
||||||
|
Returns `true` if signature, `nbf` (if set) and `exp` (if set) are valid, otherwise returns `false`.
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
### `jwt.decode(token)`
|
||||||
|
|
||||||
|
Returns the payload **without** verifying the integrity of the token. Please use `jwt.verify()` first to keep your application secure!
|
||||||
|
|
||||||
|
Argument | Type | Satus | Default | Description
|
||||||
|
----------- | -------- | -------- | ------- | -----------
|
||||||
|
`token` | `string` | required | - | The token string generated by `jwt.sign()`.
|
||||||
|
|
||||||
|
#### `return`
|
||||||
|
Returns payload `object`.
|
||||||
|
|
||||||
|
### Available Algorithms
|
||||||
|
- ES256
|
||||||
|
- ES384
|
||||||
|
- ES512
|
||||||
|
- HS256
|
||||||
|
- HS384
|
||||||
|
- HS512
|
||||||
51
index.d.ts
vendored
Normal file
51
index.d.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* JWT
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
* @constructor
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
declare class JWT {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs a payload and returns the token
|
||||||
|
*
|
||||||
|
* @param {object} payload The payload object. To use `nbf` (Not Before) and/or `exp` (Expiration Time) add `nbf` and/or `exp` to the payload.
|
||||||
|
* @param {string} secret A string which is used to sign the payload.
|
||||||
|
* @param {JWTSignOptions | JWTAlgorithm} options The options object or the algorithm.
|
||||||
|
* @returns {Promise<string>} Returns token as a `string`.
|
||||||
|
*/
|
||||||
|
sign(payload: object, secret: string, options?: JWTSignOptions | JWTAlgorithm): Promise<string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the integrity of the token and returns a boolean value.
|
||||||
|
*
|
||||||
|
* @param {string} token The token string generated by `jwt.sign()`.
|
||||||
|
* @param {string} secret The string which was used to sign the payload.
|
||||||
|
* @param {JWTVerifyOptions | JWTAlgorithm} options The options object or the algorithm.
|
||||||
|
* @returns {Promise<boolean>} Returns `true` if signature, `nbf` (if set) and `exp` (if set) are valid, otherwise returns `false`.
|
||||||
|
*/
|
||||||
|
verify(token: string, secret: string, options?: JWTVerifyOptions | JWTAlgorithm): Promise<boolean>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the payload **without** verifying the integrity of the token. Please use `jwt.verify()` first to keep your application secure!
|
||||||
|
*
|
||||||
|
* @param {string} token The token string generated by `jwt.sign()`.
|
||||||
|
* @returns {object | null} Returns payload `object`.
|
||||||
|
*/
|
||||||
|
decode(token: string): object | null
|
||||||
|
}
|
||||||
|
declare const _exports: JWT
|
||||||
|
|
||||||
|
type JWTAlgorithm = 'ES256' | 'ES384' | 'ES512' | 'HS256' | 'HS384' | 'HS512'
|
||||||
|
|
||||||
|
type JWTSignOptions = {
|
||||||
|
algorithm?: JWTAlgorithm,
|
||||||
|
keyid?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type JWTVerifyOptions = {
|
||||||
|
algorithm?: JWTAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
export = _exports
|
||||||
145
index.js
145
index.js
@@ -12,91 +12,104 @@ class JWT {
|
|||||||
if (!crypto || !crypto.subtle)
|
if (!crypto || !crypto.subtle)
|
||||||
throw new Error('Crypto not supported!')
|
throw new Error('Crypto not supported!')
|
||||||
this.algorithms = {
|
this.algorithms = {
|
||||||
HS256: {
|
ES256: { name: 'ECDSA', namedCurve: 'P-256', hash: { name: 'SHA-256' } },
|
||||||
name: 'HMAC',
|
ES384: { name: 'ECDSA', namedCurve: 'P-384', hash: { name: 'SHA-384' } },
|
||||||
hash: {
|
ES512: { name: 'ECDSA', namedCurve: 'P-512', hash: { name: 'SHA-512' } },
|
||||||
name: 'SHA-256'
|
HS256: { name: 'HMAC', hash: { name: 'SHA-256' } },
|
||||||
}
|
HS384: { name: 'HMAC', hash: { name: 'SHA-384' } },
|
||||||
},
|
HS512: { name: 'HMAC', hash: { name: 'SHA-512' } }
|
||||||
HS512: {
|
|
||||||
name: 'HMAC',
|
|
||||||
hash: {
|
|
||||||
name: 'SHA-512'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_utf8ToUint8Array(str) {
|
||||||
|
return Base64URL.parse(btoa(unescape(encodeURIComponent(str))))
|
||||||
}
|
}
|
||||||
|
_str2ab(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);
|
||||||
}
|
}
|
||||||
utf8ToUint8Array(str) {
|
return buf;
|
||||||
const chars = []
|
|
||||||
str = btoa(unescape(encodeURIComponent(str)))
|
|
||||||
return Base64URL.parse(str)
|
|
||||||
}
|
}
|
||||||
async sign(payload, secret, alg = 'HS256') {
|
_decodePayload(raw) {
|
||||||
if (payload === null || typeof payload !== 'object')
|
switch (raw.length % 4) {
|
||||||
throw new Error('payload must be an object')
|
|
||||||
if (typeof secret !== 'string')
|
|
||||||
throw new Error('secret must be a string')
|
|
||||||
if (typeof alg !== 'string')
|
|
||||||
throw new Error('alg must be a string')
|
|
||||||
const importAlgorithm = this.algorithms[alg]
|
|
||||||
if (!importAlgorithm)
|
|
||||||
throw new Error('algorithm not found')
|
|
||||||
const payloadAsJSON = JSON.stringify(payload)
|
|
||||||
const partialToken = `${Base64URL.stringify(this.utf8ToUint8Array(JSON.stringify({ alg, typ: 'JWT' })))}.${Base64URL.stringify(this.utf8ToUint8Array(payloadAsJSON))}`
|
|
||||||
const key = await crypto.subtle.importKey('raw', this.utf8ToUint8Array(secret), importAlgorithm, false, ['sign'])
|
|
||||||
const characters = payloadAsJSON.split('')
|
|
||||||
const it = this.utf8ToUint8Array(payloadAsJSON).entries()
|
|
||||||
let i = 0
|
|
||||||
const result = []
|
|
||||||
let current
|
|
||||||
while (!(current = it.next()).done) {
|
|
||||||
result.push([current.value[1], characters[i]])
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
const signature = await crypto.subtle.sign(importAlgorithm.name, key, this.utf8ToUint8Array(partialToken))
|
|
||||||
return `${partialToken}.${Base64URL.stringify(new Uint8Array(signature))}`
|
|
||||||
}
|
|
||||||
async verify(token, secret, alg = 'HS256') {
|
|
||||||
if (typeof token !== 'string')
|
|
||||||
throw new Error('token must be a string')
|
|
||||||
if (typeof secret !== 'string')
|
|
||||||
throw new Error('secret must be a string')
|
|
||||||
if (typeof alg !== 'string')
|
|
||||||
throw new Error('alg must be a string')
|
|
||||||
const tokenParts = token.split('.')
|
|
||||||
if (tokenParts.length !== 3)
|
|
||||||
throw new Error('token must have 3 parts')
|
|
||||||
const importAlgorithm = this.algorithms[alg]
|
|
||||||
if (!importAlgorithm)
|
|
||||||
throw new Error('algorithm not found')
|
|
||||||
const keyData = this.utf8ToUint8Array(secret)
|
|
||||||
const key = await crypto.subtle.importKey('raw', keyData, importAlgorithm, false, ['sign'])
|
|
||||||
const partialToken = tokenParts.slice(0, 2).join('.')
|
|
||||||
const signaturePart = tokenParts[2]
|
|
||||||
const messageAsUint8Array = this.utf8ToUint8Array(partialToken)
|
|
||||||
const res = await crypto.subtle.sign(importAlgorithm.name, key, messageAsUint8Array)
|
|
||||||
return Base64URL.stringify(new Uint8Array(res)) === signaturePart
|
|
||||||
}
|
|
||||||
decode(token) {
|
|
||||||
let output = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')
|
|
||||||
switch (output.length % 4) {
|
|
||||||
case 0:
|
case 0:
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
output += '=='
|
raw += '=='
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
output += '='
|
raw += '='
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error('Illegal base64url string!')
|
throw new Error('Illegal base64url string!')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return JSON.parse(decodeURIComponent(escape(atob(output))))
|
return JSON.parse(decodeURIComponent(escape(atob(raw))))
|
||||||
} catch {
|
} catch {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async sign(payload, secret, options = { algorithm: 'HS256' }) {
|
||||||
|
if (typeof options === 'string')
|
||||||
|
options = { algorithm: options }
|
||||||
|
if (payload === null || typeof payload !== 'object')
|
||||||
|
throw new Error('payload must be an object')
|
||||||
|
if (typeof secret !== 'string')
|
||||||
|
throw new Error('secret must be a string')
|
||||||
|
if (typeof options.algorithm !== 'string')
|
||||||
|
throw new Error('options.algorithm must be a string')
|
||||||
|
const importAlgorithm = this.algorithms[options.algorithm]
|
||||||
|
if (!importAlgorithm)
|
||||||
|
throw new Error('algorithm not found')
|
||||||
|
payload.iat = Math.floor(Date.now() / 1000)
|
||||||
|
const payloadAsJSON = JSON.stringify(payload)
|
||||||
|
const partialToken = `${Base64URL.stringify(this._utf8ToUint8Array(JSON.stringify({ alg: options.algorithm, kid: options.keyid })))}.${Base64URL.stringify(this._utf8ToUint8Array(payloadAsJSON))}`
|
||||||
|
let keyFormat = 'raw'
|
||||||
|
let keyData
|
||||||
|
if (secret.startsWith('-----BEGIN')) {
|
||||||
|
keyFormat = 'pkcs8'
|
||||||
|
keyData = this._str2ab(atob(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, '')))
|
||||||
|
} else
|
||||||
|
keyData = this._utf8ToUint8Array(secret)
|
||||||
|
const key = await crypto.subtle.importKey(keyFormat, keyData, importAlgorithm, false, ['sign'])
|
||||||
|
const signature = await crypto.subtle.sign(importAlgorithm, key, this._utf8ToUint8Array(partialToken))
|
||||||
|
return `${partialToken}.${Base64URL.stringify(new Uint8Array(signature))}`
|
||||||
|
}
|
||||||
|
async verify(token, secret, options = { algorithm: 'HS256' }) {
|
||||||
|
if (typeof options === 'string')
|
||||||
|
options = { algorithm: options }
|
||||||
|
if (typeof token !== 'string')
|
||||||
|
throw new Error('token must be a string')
|
||||||
|
if (typeof secret !== 'string')
|
||||||
|
throw new Error('secret must be a string')
|
||||||
|
if (typeof options.algorithm !== 'string')
|
||||||
|
throw new Error('options.algorithm must be a string')
|
||||||
|
const tokenParts = token.split('.')
|
||||||
|
if (tokenParts.length !== 3)
|
||||||
|
throw new Error('token must have 3 parts')
|
||||||
|
const importAlgorithm = this.algorithms[options.algorithm]
|
||||||
|
if (!importAlgorithm)
|
||||||
|
throw new Error('algorithm not found')
|
||||||
|
const payload = this.decode(token)
|
||||||
|
if (payload.nbf && payload.nbf >= Math.floor(Date.now() / 1000))
|
||||||
|
return false
|
||||||
|
if (payload.exp && payload.exp < Math.floor(Date.now() / 1000))
|
||||||
|
return false
|
||||||
|
let keyFormat = 'raw'
|
||||||
|
let keyData
|
||||||
|
if (secret.startsWith('-----BEGIN')) {
|
||||||
|
keyFormat = 'pkcs8'
|
||||||
|
keyData = this._str2ab(atob(secret.replace(/-----BEGIN.*?-----/g, '').replace(/-----END.*?-----/g, '').replace(/\s/g, '')))
|
||||||
|
} else
|
||||||
|
keyData = this._utf8ToUint8Array(secret)
|
||||||
|
const key = await crypto.subtle.importKey(keyFormat, keyData, importAlgorithm, false, ['sign'])
|
||||||
|
const res = await crypto.subtle.sign(importAlgorithm, key, this._utf8ToUint8Array(tokenParts.slice(0, 2).join('.')))
|
||||||
|
return Base64URL.stringify(new Uint8Array(res)) === tokenParts[2]
|
||||||
|
}
|
||||||
|
decode(token) {
|
||||||
|
return this._decodePayload(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new JWT
|
module.exports = new JWT
|
||||||
|
|||||||
330
package-lock.json
generated
Normal file
330
package-lock.json
generated
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
{
|
||||||
|
"name": "@tsndr/cloudflare-worker-jwt",
|
||||||
|
"version": "1.1.4",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": {
|
||||||
|
"version": "7.12.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
|
||||||
|
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/highlight": "^7.12.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@babel/helper-validator-identifier": {
|
||||||
|
"version": "7.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
|
||||||
|
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@babel/highlight": {
|
||||||
|
"version": "7.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
|
||||||
|
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/helper-validator-identifier": "^7.14.0",
|
||||||
|
"chalk": "^2.0.0",
|
||||||
|
"js-tokens": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"argparse": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"sprintf-js": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"builtin-modules": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"diff": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"escape-string-regexp": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"esprima": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"function-bind": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
|
||||||
|
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-core-module": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"js-tokens": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"version": "3.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||||
|
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"esprima": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimist": {
|
||||||
|
"version": "1.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||||
|
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"mkdirp": {
|
||||||
|
"version": "0.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||||
|
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minimist": "^1.2.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"path-parse": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"resolve": {
|
||||||
|
"version": "1.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||||
|
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-core-module": "^2.2.0",
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"sprintf-js": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"tslint": {
|
||||||
|
"version": "6.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
|
||||||
|
"integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.0.0",
|
||||||
|
"builtin-modules": "^1.1.1",
|
||||||
|
"chalk": "^2.3.0",
|
||||||
|
"commander": "^2.12.1",
|
||||||
|
"diff": "^4.0.1",
|
||||||
|
"glob": "^7.1.1",
|
||||||
|
"js-yaml": "^3.13.1",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"mkdirp": "^0.5.3",
|
||||||
|
"resolve": "^1.3.2",
|
||||||
|
"semver": "^5.3.0",
|
||||||
|
"tslib": "^1.13.0",
|
||||||
|
"tsutils": "^2.29.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tsutils": {
|
||||||
|
"version": "2.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
||||||
|
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
package.json
11
package.json
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@tsndr/cloudflare-worker-jwt",
|
"name": "@tsndr/cloudflare-worker-jwt",
|
||||||
"version": "1.0.0",
|
"version": "1.1.4",
|
||||||
"description": "A lightweight JWT implementation with ZERO dependencies for Cloudflare Worker",
|
"description": "A lightweight JWT implementation with ZERO dependencies for Cloudflare Worker",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"lint": "tslint index.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -18,9 +18,12 @@
|
|||||||
"cloudflare-worker"
|
"cloudflare-worker"
|
||||||
],
|
],
|
||||||
"author": "Tobias Schneider",
|
"author": "Tobias Schneider",
|
||||||
"license": "ISC",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/tsndr/cloudflare-worker-jwt/issues"
|
"url": "https://github.com/tsndr/cloudflare-worker-jwt/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/tsndr/cloudflare-worker-jwt#readme"
|
"homepage": "https://github.com/tsndr/cloudflare-worker-jwt#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"tslint": "^6.1.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
tslint.json
Normal file
53
tslint.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"jsRules": {
|
||||||
|
"arrow-return-shorthand": [true, "multiline"],
|
||||||
|
"binary-expression-operand-order": true,
|
||||||
|
"class-name": true,
|
||||||
|
"comment-format": [true, "check-space"],
|
||||||
|
"curly": [true, "as-needed"],
|
||||||
|
"encoding": true,
|
||||||
|
"increment-decrement": [true, "allow-post"],
|
||||||
|
"indent": [true, "spaces", 2],
|
||||||
|
"linebreak-style": [true, "LF"],
|
||||||
|
"no-async-without-await": true,
|
||||||
|
"no-consecutive-blank-lines": [true, 2],
|
||||||
|
"no-duplicate-switch-case": true,
|
||||||
|
"no-duplicate-variable": [true, "check-parameters"],
|
||||||
|
"no-empty": true,
|
||||||
|
"no-eval": true,
|
||||||
|
"no-invalid-template-strings": true,
|
||||||
|
"no-invalid-this": true,
|
||||||
|
"no-irregular-whitespace": true,
|
||||||
|
"no-return-await": true,
|
||||||
|
"no-shadowed-variable": true,
|
||||||
|
"no-sparse-arrays": true,
|
||||||
|
"no-string-throw": true,
|
||||||
|
"no-tautology-expression": true,
|
||||||
|
"no-this-assignment": [true, {"allowed-names": ["^self$"], "allow-destructuring": true}],
|
||||||
|
"no-trailing-whitespace": [true, "ignore-comments", "ignore-jsdoc"],
|
||||||
|
"no-unnecessary-callback-wrapper": true,
|
||||||
|
"no-unnecessary-initializer": true,
|
||||||
|
"no-unsafe-finally": true,
|
||||||
|
"no-var-keyword": true,
|
||||||
|
"object-literal-key-quotes": [true, "consistent-as-needed"],
|
||||||
|
"one-line": [true, "check-catch", "check-finally", "check-else", "check-open-brace", "check-whitespace"],
|
||||||
|
"one-variable-per-declaration": [true, "ignore-for-loop"],
|
||||||
|
"ordered-imports": true,
|
||||||
|
"prefer-conditional-expression": [true, "check-else-if"],
|
||||||
|
"prefer-const": true,
|
||||||
|
"prefer-object-spread": true,
|
||||||
|
"prefer-switch": [true, {"min-cases": 3}],
|
||||||
|
"prefer-template": [true, "allow-single-concat"],
|
||||||
|
"prefer-while": true,
|
||||||
|
"quotemark": [true, "single"],
|
||||||
|
"semicolon": [true, "never"],
|
||||||
|
"space-before-function-paren": [true, "never"],
|
||||||
|
"static-this": true,
|
||||||
|
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}],
|
||||||
|
"triple-equals": true,
|
||||||
|
"unnecessary-constructor": [true, {"check-super-calls": true}],
|
||||||
|
"unnecessary-else": [true, {"allow-else-if": true}],
|
||||||
|
"use-isnan": true,
|
||||||
|
"whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-rest-spread", "check-type", "check-typecast", "check-type-operator", "check-preblock", "check-postbrace"]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user