Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
06c5605bf2
|
|||
|
a4edaba6f0
|
|||
|
b2a3b4c25f
|
|||
|
c691324515
|
|||
|
66385f323c
|
|||
|
1b6ac02f7c
|
@@ -24,8 +24,9 @@ npm i @tsndr/cloudflare-worker-jwt
|
|||||||
### Basic Example
|
### Basic Example
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
import jwt from "@tsndr/cloudflare-worker-jwt"
|
||||||
|
|
||||||
async () => {
|
async () => {
|
||||||
import jwt from "@tsndr/cloudflare-worker-jwt"
|
|
||||||
|
|
||||||
// Create a token
|
// Create a token
|
||||||
const token = await jwt.sign({
|
const token = await jwt.sign({
|
||||||
@@ -52,8 +53,9 @@ async () => {
|
|||||||
### Restrict Timeframe
|
### Restrict Timeframe
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
import jwt from "@tsndr/cloudflare-worker-jwt"
|
||||||
|
|
||||||
async () => {
|
async () => {
|
||||||
import jwt from "@tsndr/cloudflare-worker-jwt"
|
|
||||||
|
|
||||||
// Create a token
|
// Create a token
|
||||||
const token = await jwt.sign({
|
const token = await jwt.sign({
|
||||||
|
|||||||
590
package-lock.json
generated
590
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@tsndr/cloudflare-worker-jwt",
|
"name": "@tsndr/cloudflare-worker-jwt",
|
||||||
"version": "3.1.4",
|
"version": "3.1.7",
|
||||||
"description": "A lightweight JWT implementation with ZERO dependencies for Cloudflare Worker",
|
"description": "A lightweight JWT implementation with ZERO dependencies for Cloudflare Worker",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./index.js",
|
"exports": "./index.js",
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/tsndr/cloudflare-worker-jwt#readme",
|
"homepage": "https://github.com/tsndr/cloudflare-worker-jwt#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20250313.0",
|
"@cloudflare/workers-types": "^4.20250525.0",
|
||||||
"@edge-runtime/vm": "^5.0.0",
|
"@edge-runtime/vm": "^5.0.0",
|
||||||
"esbuild": "^0.25.1",
|
"esbuild": "^0.25.4",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.3",
|
||||||
"vitest": "^3.0.8"
|
"vitest": "^3.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ const algorithms: JwtAlgorithms = {
|
|||||||
* @throws If there"s a validation issue.
|
* @throws If there"s a validation issue.
|
||||||
* @returns Returns token as a `string`.
|
* @returns Returns token as a `string`.
|
||||||
*/
|
*/
|
||||||
export async function sign<Payload = {}, Header = {}>(payload: JwtPayload<Payload>, secret: string | JsonWebKey | CryptoKey, options: JwtSignOptions<Header> | JwtAlgorithm = "HS256"): Promise<string> {
|
export async function sign<Payload = {}, Header = {}>(payload: JwtPayload<Payload>, secret: string | JsonWebKeyWithKid | CryptoKey, options: JwtSignOptions<Header> | JwtAlgorithm = "HS256"): Promise<string> {
|
||||||
if (typeof options === "string")
|
if (typeof options === "string")
|
||||||
options = { algorithm: options }
|
options = { algorithm: options }
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ export async function sign<Payload = {}, Header = {}>(payload: JwtPayload<Payloa
|
|||||||
* @throws Throws integration errors and if `options.throwError` is set to `true` also throws `NOT_YET_VALID`, `EXPIRED` or `INVALID_SIGNATURE`.
|
* @throws Throws integration errors and if `options.throwError` is set to `true` also throws `NOT_YET_VALID`, `EXPIRED` or `INVALID_SIGNATURE`.
|
||||||
* @returns Returns the decoded token or `undefined`.
|
* @returns Returns the decoded token or `undefined`.
|
||||||
*/
|
*/
|
||||||
export async function verify<Payload = {}, Header = {}>(token: string, secret: string | JsonWebKey | CryptoKey, options: JwtVerifyOptions | JwtAlgorithm = "HS256"): Promise<JwtData<Payload, Header> | undefined> {
|
export async function verify<Payload = {}, Header = {}>(token: string, secret: string | JsonWebKeyWithKid | CryptoKey, options: JwtVerifyOptions | JwtAlgorithm = "HS256"): Promise<JwtData<Payload, Header> | undefined> {
|
||||||
if (typeof options === "string")
|
if (typeof options === "string")
|
||||||
options = { algorithm: options }
|
options = { algorithm: options }
|
||||||
options = { algorithm: "HS256", clockTolerance: 0, throwError: false, ...options }
|
options = { algorithm: "HS256", clockTolerance: 0, throwError: false, ...options }
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export async function importTextSecret(key: string, algorithm: SubtleCryptoImpor
|
|||||||
return await crypto.subtle.importKey("raw", textToUint8Array(key), algorithm, true, keyUsages)
|
return await crypto.subtle.importKey("raw", textToUint8Array(key), algorithm, true, keyUsages)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function importJwk(key: JsonWebKey, algorithm: SubtleCryptoImportKeyAlgorithm, keyUsages: KeyUsages[]): Promise<CryptoKey> {
|
export async function importJwk(key: JsonWebKeyWithKid, algorithm: SubtleCryptoImportKeyAlgorithm, keyUsages: KeyUsages[]): Promise<CryptoKey> {
|
||||||
return await crypto.subtle.importKey("jwk", key, algorithm, true, keyUsages)
|
return await crypto.subtle.importKey("jwk", key, algorithm, true, keyUsages)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ export async function importPrivateKey(key: string, algorithm: SubtleCryptoImpor
|
|||||||
return await crypto.subtle.importKey("pkcs8", pemToBinary(key), algorithm, true, keyUsages)
|
return await crypto.subtle.importKey("pkcs8", pemToBinary(key), algorithm, true, keyUsages)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function importKey(key: string | JsonWebKey, algorithm: SubtleCryptoImportKeyAlgorithm, keyUsages: KeyUsages[]): Promise<CryptoKey> {
|
export async function importKey(key: string | JsonWebKeyWithKid, algorithm: SubtleCryptoImportKeyAlgorithm, keyUsages: KeyUsages[]): Promise<CryptoKey> {
|
||||||
if (typeof key === "object")
|
if (typeof key === "object")
|
||||||
return importJwk(key, algorithm, keyUsages)
|
return importJwk(key, algorithm, keyUsages)
|
||||||
|
|
||||||
|
|||||||
@@ -13,27 +13,27 @@ describe("Verify", async () => {
|
|||||||
const notYetValidToken = await jwt.sign({ sub: "me", nbf: now + offset }, secret)
|
const notYetValidToken = await jwt.sign({ sub: "me", nbf: now + offset }, secret)
|
||||||
const expiredToken = await jwt.sign({ sub: "me", exp: now - offset }, secret)
|
const expiredToken = await jwt.sign({ sub: "me", exp: now - offset }, secret)
|
||||||
|
|
||||||
test("Valid", () => {
|
test("Valid", async () => {
|
||||||
expect(jwt.verify(validToken, secret, { throwError: true })).resolves.toBeTruthy()
|
await expect(jwt.verify(validToken, secret, { throwError: true })).resolves.toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Not yet expired", () => {
|
test("Not yet expired", async () => {
|
||||||
expect(jwt.verify(notYetExpired, secret, { throwError: true })).resolves.toBeTruthy()
|
await expect(jwt.verify(notYetExpired, secret, { throwError: true })).resolves.toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Not yet valid", () => {
|
test("Not yet valid", async () => {
|
||||||
expect(jwt.verify(notYetValidToken, secret, { throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
await expect(jwt.verify(notYetValidToken, secret, { throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Expired", () => {
|
test("Expired", async () => {
|
||||||
expect(jwt.verify(expiredToken, secret, { throwError: true })).rejects.toThrowError("EXPIRED")
|
await expect(jwt.verify(expiredToken, secret, { throwError: true })).rejects.toThrowError("EXPIRED")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("Clock offset", () => {
|
test("Clock offset", async () => {
|
||||||
expect(jwt.verify(notYetValidToken, secret, { clockTolerance: offset, throwError: true })).resolves.toBeTruthy()
|
await expect(jwt.verify(notYetValidToken, secret, { clockTolerance: offset, throwError: true })).resolves.toBeTruthy()
|
||||||
expect(jwt.verify(expiredToken, secret, { clockTolerance: offset, throwError: true })).resolves.toBeTruthy()
|
await expect(jwt.verify(expiredToken, secret, { clockTolerance: offset, throwError: true })).resolves.toBeTruthy()
|
||||||
|
|
||||||
expect(jwt.verify(notYetValidToken, secret, { clockTolerance: offset - 1, throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
await expect(jwt.verify(notYetValidToken, secret, { clockTolerance: offset - 1, throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
||||||
expect(jwt.verify(expiredToken, secret, { clockTolerance: offset - 1, throwError: true })).rejects.toThrowError("EXPIRED")
|
await expect(jwt.verify(expiredToken, secret, { clockTolerance: offset - 1, throwError: true })).rejects.toThrowError("EXPIRED")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -67,7 +67,7 @@ describe("Imports", () => {
|
|||||||
const testAlgorithm = { name: "HMAC", hash: { name: "SHA-256" } }
|
const testAlgorithm = { name: "HMAC", hash: { name: "SHA-256" } }
|
||||||
const testCryptoKey = { type: "secret", extractable: true, algorithm: { ...testAlgorithm, length: 168 }, usages: ["verify", "sign"] }
|
const testCryptoKey = { type: "secret", extractable: true, algorithm: { ...testAlgorithm, length: 168 }, usages: ["verify", "sign"] }
|
||||||
|
|
||||||
expect(await importTextSecret(testKey, testAlgorithm, ["verify", "sign"])).toMatchObject(testCryptoKey)
|
await expect(importTextSecret(testKey, testAlgorithm, ["verify", "sign"])).resolves.toMatchObject(testCryptoKey)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.todo("importJwk")
|
test.todo("importJwk")
|
||||||
|
|||||||
Reference in New Issue
Block a user