Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
06c5605bf2
|
|||
|
a4edaba6f0
|
|||
|
b2a3b4c25f
|
|||
|
c691324515
|
|||
|
66385f323c
|
|||
|
1b6ac02f7c
|
@@ -24,9 +24,10 @@ npm i @tsndr/cloudflare-worker-jwt
|
||||
### Basic Example
|
||||
|
||||
```typescript
|
||||
async () => {
|
||||
import jwt from "@tsndr/cloudflare-worker-jwt"
|
||||
|
||||
async () => {
|
||||
|
||||
// Create a token
|
||||
const token = await jwt.sign({
|
||||
sub: "1234",
|
||||
@@ -52,9 +53,10 @@ async () => {
|
||||
### Restrict Timeframe
|
||||
|
||||
```typescript
|
||||
async () => {
|
||||
import jwt from "@tsndr/cloudflare-worker-jwt"
|
||||
|
||||
async () => {
|
||||
|
||||
// Create a token
|
||||
const token = await jwt.sign({
|
||||
sub: "1234",
|
||||
|
||||
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",
|
||||
"version": "3.1.4",
|
||||
"version": "3.1.7",
|
||||
"description": "A lightweight JWT implementation with ZERO dependencies for Cloudflare Worker",
|
||||
"type": "module",
|
||||
"exports": "./index.js",
|
||||
@@ -30,10 +30,10 @@
|
||||
},
|
||||
"homepage": "https://github.com/tsndr/cloudflare-worker-jwt#readme",
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20250313.0",
|
||||
"@cloudflare/workers-types": "^4.20250525.0",
|
||||
"@edge-runtime/vm": "^5.0.0",
|
||||
"esbuild": "^0.25.1",
|
||||
"typescript": "^5.8.2",
|
||||
"vitest": "^3.0.8"
|
||||
"esbuild": "^0.25.4",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.1.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ const algorithms: JwtAlgorithms = {
|
||||
* @throws If there"s a validation issue.
|
||||
* @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")
|
||||
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`.
|
||||
* @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")
|
||||
options = { algorithm: 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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export async function importPrivateKey(key: string, algorithm: SubtleCryptoImpor
|
||||
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")
|
||||
return importJwk(key, algorithm, keyUsages)
|
||||
|
||||
|
||||
@@ -13,27 +13,27 @@ describe("Verify", async () => {
|
||||
const notYetValidToken = await jwt.sign({ sub: "me", nbf: now + offset }, secret)
|
||||
const expiredToken = await jwt.sign({ sub: "me", exp: now - offset }, secret)
|
||||
|
||||
test("Valid", () => {
|
||||
expect(jwt.verify(validToken, secret, { throwError: true })).resolves.toBeTruthy()
|
||||
test("Valid", async () => {
|
||||
await expect(jwt.verify(validToken, secret, { throwError: true })).resolves.toBeTruthy()
|
||||
})
|
||||
|
||||
test("Not yet expired", () => {
|
||||
expect(jwt.verify(notYetExpired, secret, { throwError: true })).resolves.toBeTruthy()
|
||||
test("Not yet expired", async () => {
|
||||
await expect(jwt.verify(notYetExpired, secret, { throwError: true })).resolves.toBeTruthy()
|
||||
})
|
||||
|
||||
test("Not yet valid", () => {
|
||||
expect(jwt.verify(notYetValidToken, secret, { throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
||||
test("Not yet valid", async () => {
|
||||
await expect(jwt.verify(notYetValidToken, secret, { throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
||||
})
|
||||
|
||||
test("Expired", () => {
|
||||
expect(jwt.verify(expiredToken, secret, { throwError: true })).rejects.toThrowError("EXPIRED")
|
||||
test("Expired", async () => {
|
||||
await expect(jwt.verify(expiredToken, secret, { throwError: true })).rejects.toThrowError("EXPIRED")
|
||||
})
|
||||
|
||||
test("Clock offset", () => {
|
||||
expect(jwt.verify(notYetValidToken, secret, { clockTolerance: offset, throwError: true })).resolves.toBeTruthy()
|
||||
expect(jwt.verify(expiredToken, secret, { clockTolerance: offset, throwError: true })).resolves.toBeTruthy()
|
||||
test("Clock offset", async () => {
|
||||
await expect(jwt.verify(notYetValidToken, 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")
|
||||
expect(jwt.verify(expiredToken, secret, { clockTolerance: offset - 1, throwError: true })).rejects.toThrowError("EXPIRED")
|
||||
await expect(jwt.verify(notYetValidToken, secret, { clockTolerance: offset - 1, throwError: true })).rejects.toThrowError("NOT_YET_VALID")
|
||||
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 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")
|
||||
|
||||
Reference in New Issue
Block a user