@sourceregistry/node-jwt 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -75
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +52 -0
- package/dist/index.es.js +306 -77
- package/dist/index.es.js.map +1 -1
- package/dist/promises.cjs.js.map +1 -1
- package/dist/promises.d.ts +32 -0
- package/dist/promises.es.js.map +1 -1
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -1,34 +1,30 @@
|
|
|
1
1
|
# 🔐 @sourceregistry/node-jwt
|
|
2
|
-
|
|
3
2
|
[](https://www.npmjs.com/package/@sourceregistry/node-jwt)
|
|
4
|
-
[](LICENSE)
|
|
5
|
-
[](https://github.com/SourceRegistry/node-jwt/blob/main/LICENSE)
|
|
4
|
+
[](https://github.com/SourceRegistry/node-jwt/actions)
|
|
5
|
+
[](https://codecov.io/gh/SourceRegistry/node-jwt)
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
> Most JWT libraries are bloated, have security pitfalls, or lack proper TypeScript support. This library is:
|
|
12
|
-
> - **Tiny** (~150 LOC core)
|
|
13
|
-
> - **Secure by default** (correct ECDSA/RSA encoding, time validation)
|
|
14
|
-
> - **TypeScript-first** with full JSDoc
|
|
15
|
-
> - **No external dependencies**
|
|
16
|
-
> - **100% test coverage**
|
|
17
|
-
> - **Dual API**: Sync and Promise-based
|
|
7
|
+
A minimal, secure, and production-ready JWT (JSON Web Token) library for Node.js with zero dependencies. Supports all standard signing algorithms (HMAC, RSA, ECDSA, EdDSA, RSASSA-PSS) and full claim validation.
|
|
18
8
|
|
|
19
|
-
|
|
9
|
+
✨ **Why another JWT library?**
|
|
10
|
+
Most JWT libraries are bloated, have security pitfalls, or lack proper TypeScript support. This library is:
|
|
20
11
|
|
|
21
|
-
|
|
12
|
+
- **Tiny**
|
|
13
|
+
- **Secure by default** (correct ECDSA/RSA/PSS/EdDSA encoding, time validation, algorithm whitelisting)
|
|
14
|
+
- **TypeScript-first** with full JSDoc
|
|
15
|
+
- **No external dependencies**
|
|
16
|
+
- **100% test coverage**
|
|
17
|
+
- **Dual API**: Sync and Promise-based
|
|
22
18
|
|
|
19
|
+
📦 **Installation**
|
|
23
20
|
```bash
|
|
24
21
|
npm install @sourceregistry/node-jwt
|
|
25
22
|
```
|
|
26
|
-
|
|
27
|
-
> **Requires Node.js ≥ 16**
|
|
23
|
+
Requires Node.js ≥ 16
|
|
28
24
|
|
|
29
25
|
---
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
🚀 **Quick Start**
|
|
32
28
|
|
|
33
29
|
### Sync API (default)
|
|
34
30
|
```ts
|
|
@@ -42,7 +38,7 @@ const token = sign(
|
|
|
42
38
|
);
|
|
43
39
|
|
|
44
40
|
// Verify
|
|
45
|
-
const result = verify(token, 'your-secret-key');
|
|
41
|
+
const result = verify(token, 'your-secret-key', { issuer: 'https://example.com' });
|
|
46
42
|
if (result.valid) {
|
|
47
43
|
console.log('Payload:', result.payload);
|
|
48
44
|
} else {
|
|
@@ -66,7 +62,11 @@ const token = await sign(
|
|
|
66
62
|
|
|
67
63
|
// Verify
|
|
68
64
|
try {
|
|
69
|
-
const { payload, header, signature } = await verify(token, 'your-secret-key'
|
|
65
|
+
const { payload, header, signature } = await verify(token, 'your-secret-key', {
|
|
66
|
+
issuer: 'https://example.com',
|
|
67
|
+
audience: 'my-app',
|
|
68
|
+
algorithms: ['HS256']
|
|
69
|
+
});
|
|
70
70
|
console.log('Payload:', payload);
|
|
71
71
|
} catch (error) {
|
|
72
72
|
console.error('JWT Error:', error.code, error.reason);
|
|
@@ -78,35 +78,48 @@ const { header, payload, signature } = await decode(token);
|
|
|
78
78
|
|
|
79
79
|
---
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
| Algorithm
|
|
84
|
-
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
95
|
-
|
|
81
|
+
🔑 **Supported Algorithms**
|
|
82
|
+
|
|
83
|
+
| Algorithm | Type | Secret Type |
|
|
84
|
+
|-------------|--------------|------------------------------------------|
|
|
85
|
+
| HS256 | HMAC | `string \| Buffer` |
|
|
86
|
+
| HS384 | HMAC | `string \| Buffer` |
|
|
87
|
+
| HS512 | HMAC | `string \| Buffer` |
|
|
88
|
+
| RS256 | RSA | Private key (sign), Public key (verify) |
|
|
89
|
+
| RS384 | RSA | Private key (sign), Public key (verify) |
|
|
90
|
+
| RS512 | RSA | Private key (sign), Public key (verify) |
|
|
91
|
+
| PS256 | RSA-PSS | Private key (sign), Public key (verify) |
|
|
92
|
+
| PS384 | RSA-PSS | Private key (sign), Public key (verify) |
|
|
93
|
+
| PS512 | RSA-PSS | Private key (sign), Public key (verify) |
|
|
94
|
+
| ES256 | ECDSA | Private key (sign), Public key (verify) |
|
|
95
|
+
| ES384 | ECDSA | Private key (sign), Public key (verify) |
|
|
96
|
+
| ES512 | ECDSA | Private key (sign), Public key (verify) |
|
|
97
|
+
| ES256K | ECDSA (secp256k1) | Private key (sign), Public key (verify) |
|
|
98
|
+
| EdDSA | Ed25519 | Private key (sign), Public key (verify) |
|
|
99
|
+
|
|
100
|
+
> 💡 Keys must be in PEM format or as Node.js `KeyObject` (e.g., from `crypto.generateKeyPairSync`).
|
|
96
101
|
|
|
97
102
|
---
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
🛡️ **Security Features**
|
|
105
|
+
|
|
106
|
+
✅ Correct ECDSA signatures (DER-encoded, not IEEE P1363)
|
|
107
|
+
✅ Full RSASSA-PSS and Ed25519 support
|
|
108
|
+
✅ Strict algorithm validation with **whitelist** (`algorithms` option) to prevent algorithm confusion
|
|
109
|
+
✅ Time claim validation (`exp`, `nbf`, `iat`) with **clock skew** tolerance
|
|
110
|
+
✅ Optional validation for:
|
|
111
|
+
• Issuer (`iss`)
|
|
112
|
+
• Subject (`sub`)
|
|
113
|
+
• Audience (`aud`)
|
|
114
|
+
• JWT ID (`jti`)
|
|
115
|
+
✅ Maximum token age enforcement (`maxTokenAge`)
|
|
116
|
+
✅ Type header enforcement (`typ: 'JWT'`)
|
|
117
|
+
✅ Timing-safe signature comparison
|
|
118
|
+
✅ No unsafe defaults
|
|
106
119
|
|
|
107
120
|
---
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
📚 **API Reference**
|
|
110
123
|
|
|
111
124
|
### Sync vs Promise API
|
|
112
125
|
|
|
@@ -128,7 +141,7 @@ Sign a JWT.
|
|
|
128
141
|
- `kid`: Key ID
|
|
129
142
|
- `typ`: Token type (default: `'JWT'`)
|
|
130
143
|
|
|
131
|
-
|
|
144
|
+
Returns: `string` (JWT)
|
|
132
145
|
|
|
133
146
|
---
|
|
134
147
|
|
|
@@ -138,12 +151,18 @@ Verify and validate a JWT.
|
|
|
138
151
|
- `token`: JWT string
|
|
139
152
|
- `secret`: Key for verification
|
|
140
153
|
- `options`:
|
|
154
|
+
- `algorithms`: Array of allowed algorithms (e.g., `['HS256', 'RS256']`)
|
|
155
|
+
- `issuer`: Required value for the `iss` claim
|
|
156
|
+
- `subject`: Required value for the `sub` claim
|
|
157
|
+
- `audience`: Required value(s) for the `aud` claim (`string` or `string[]`)
|
|
158
|
+
- `jwtId`: Required value for the `jti` claim
|
|
141
159
|
- `ignoreExpiration`: Skip `exp` check (default: `false`)
|
|
142
160
|
- `clockSkew`: Tolerance in seconds for time validation (default: `0`)
|
|
161
|
+
- `maxTokenAge`: Maximum allowed token age in seconds (from `iat`)
|
|
143
162
|
|
|
144
163
|
#### Sync Usage:
|
|
145
164
|
```ts
|
|
146
|
-
const result = verify(token, secret);
|
|
165
|
+
const result = verify(token, secret, { issuer: 'https://example.com' });
|
|
147
166
|
if (result.valid) {
|
|
148
167
|
// success
|
|
149
168
|
} else {
|
|
@@ -154,76 +173,77 @@ if (result.valid) {
|
|
|
154
173
|
#### Promise Usage:
|
|
155
174
|
```ts
|
|
156
175
|
try {
|
|
157
|
-
const { header, payload, signature } = await verify(token, secret);
|
|
176
|
+
const { header, payload, signature } = await verify(token, secret, { issuer: 'https://example.com' });
|
|
158
177
|
// success
|
|
159
178
|
} catch (error) {
|
|
160
179
|
// handle error: error.reason, error.code
|
|
161
180
|
}
|
|
162
181
|
```
|
|
163
182
|
|
|
164
|
-
|
|
183
|
+
#### Error Codes:
|
|
165
184
|
- `INVALID_TOKEN`: Malformed token structure
|
|
166
185
|
- `INVALID_ALGORITHM`: Unsupported algorithm
|
|
186
|
+
- `ALGORITHM_NOT_ALLOWED`: Algorithm not in allowed list
|
|
167
187
|
- `INVALID_TYPE`: Invalid `typ` header
|
|
168
188
|
- `INVALID_SIGNATURE`: Signature mismatch
|
|
169
189
|
- `TOKEN_EXPIRED`: `exp` claim exceeded
|
|
170
190
|
- `TOKEN_NOT_ACTIVE`: `nbf` claim not reached
|
|
171
191
|
- `TOKEN_FUTURE_ISSUED`: `iat` claim in future
|
|
192
|
+
- `TOKEN_TOO_OLD`: Token age exceeds `maxTokenAge`
|
|
193
|
+
- `MISSING_ISSUER` / `INVALID_ISSUER`
|
|
194
|
+
- `MISSING_SUBJECT` / `INVALID_SUBJECT`
|
|
195
|
+
- `MISSING_AUDIENCE` / `INVALID_AUDIENCE`
|
|
196
|
+
- `MISSING_JTI` / `INVALID_JTI`
|
|
172
197
|
|
|
173
198
|
---
|
|
174
199
|
|
|
175
200
|
### `decode(token)`
|
|
176
|
-
Decode a JWT without verification (use with caution
|
|
201
|
+
Decode a JWT without verification (**use with caution!**).
|
|
177
202
|
|
|
178
203
|
- `token`: JWT string
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
**Throws** on malformed tokens (sync) / **Rejects** (promise)
|
|
204
|
+
- Returns: `{ header, payload, signature }`
|
|
205
|
+
- Throws on malformed tokens (sync) / Rejects (promise)
|
|
182
206
|
|
|
183
207
|
---
|
|
184
208
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
This library has **100% test coverage** with Vitest:
|
|
188
|
-
|
|
209
|
+
🧪 **Testing**
|
|
210
|
+
This library has 100% test coverage with Vitest:
|
|
189
211
|
```bash
|
|
190
212
|
npm test
|
|
191
213
|
npm run test:coverage
|
|
192
214
|
```
|
|
193
215
|
|
|
194
216
|
Tests include:
|
|
195
|
-
- All algorithms (HMAC, RSA, ECDSA)
|
|
196
|
-
- Time validation
|
|
217
|
+
- All algorithms (HMAC, RSA, ECDSA, EdDSA, PSS)
|
|
218
|
+
- Time validation (`exp`, `nbf`, `iat`, `clockSkew`, `maxTokenAge`)
|
|
219
|
+
- Claim validation (`iss`, `sub`, `aud`, `jti`)
|
|
220
|
+
- Algorithm whitelisting
|
|
197
221
|
- Malformed token handling
|
|
198
|
-
- Signature verification
|
|
222
|
+
- Signature verification (including timing-safe comparison)
|
|
199
223
|
- Custom claims
|
|
200
|
-
-
|
|
224
|
+
- Both sync and promise APIs
|
|
201
225
|
|
|
202
226
|
---
|
|
203
227
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
This package provides **two entrypoints**:
|
|
228
|
+
📦 **Exports**
|
|
229
|
+
This package provides two entrypoints:
|
|
207
230
|
|
|
208
231
|
| Import | Description |
|
|
209
|
-
|
|
210
|
-
| `@sourceregistry/node-jwt` |
|
|
211
|
-
| `@sourceregistry/node-jwt/promises` |
|
|
232
|
+
|--------|-------------|
|
|
233
|
+
| `@sourceregistry/node-jwt` | Sync API (default) |
|
|
234
|
+
| `@sourceregistry/node-jwt/promises` | Promise-based API |
|
|
212
235
|
|
|
213
236
|
Both include full TypeScript types and JSDoc.
|
|
214
237
|
|
|
215
238
|
---
|
|
216
239
|
|
|
217
|
-
|
|
218
|
-
|
|
240
|
+
🙌 **Contributing**
|
|
219
241
|
PRs welcome! Please:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
242
|
+
- Add tests for new features
|
|
243
|
+
- Maintain 100% coverage
|
|
244
|
+
- Follow existing code style
|
|
223
245
|
|
|
224
246
|
Found a security issue? [Report it responsibly](mailto:a.p.a.slaa@projectsource.nl).
|
|
225
247
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
> 🔗 **GitHub**: [github.com/SourceRegistry/node-jwt](https://github.com/SourceRegistry/node-jwt)
|
|
229
|
-
> 📦 **npm**: [@sourceregistry/node-jwt](https://www.npmjs.com/package/@sourceregistry/node-jwt)
|
|
248
|
+
🔗 **GitHub**: [github.com/SourceRegistry/node-jwt](https://github.com/SourceRegistry/node-jwt)
|
|
249
|
+
📦 **npm**: [@sourceregistry/node-jwt](https://www.npmjs.com/package/@sourceregistry/node-jwt)
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("crypto"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("crypto"),c={encode:e=>Buffer.from(e).toString("base64url"),decode:e=>Buffer.from(e,"base64url").toString()},y=(e,r)=>e.length!==r.length?!1:a.timingSafeEqual(Buffer.from(e),Buffer.from(r)),f={HS256:{sign:(e,r)=>a.createHmac("sha256",r).update(e).digest("base64url"),verify:(e,r,t)=>{const i=a.createHmac("sha256",r).update(e).digest("base64url");return y(i,t)}},HS384:{sign:(e,r)=>a.createHmac("sha384",r).update(e).digest("base64url"),verify:(e,r,t)=>{const i=a.createHmac("sha384",r).update(e).digest("base64url");return y(i,t)}},HS512:{sign:(e,r)=>a.createHmac("sha512",r).update(e).digest("base64url"),verify:(e,r,t)=>{const i=a.createHmac("sha512",r).update(e).digest("base64url");return y(i,t)}},RS256:{sign:(e,r)=>a.createSign("RSA-SHA256").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("RSA-SHA256").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},RS384:{sign:(e,r)=>a.createSign("RSA-SHA384").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("RSA-SHA384").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},RS512:{sign:(e,r)=>a.createSign("RSA-SHA512").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("RSA-SHA512").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},ES256:{sign:(e,r)=>a.createSign("SHA256").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("SHA256").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},ES384:{sign:(e,r)=>a.createSign("SHA384").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("SHA384").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},ES512:{sign:(e,r)=>a.createSign("SHA512").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("SHA512").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},ES256K:{sign:(e,r)=>a.createSign("SHA256").update(e).end().sign(r).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("SHA256").update(e).end().verify(r,Buffer.from(t,"base64url"))}catch{return!1}}},PS256:{sign:(e,r)=>a.createSign("RSA-SHA256").update(e).end().sign({key:r,padding:a.constants.RSA_PKCS1_PSS_PADDING,saltLength:32}).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("RSA-SHA256").update(e).end().verify({key:r,padding:a.constants.RSA_PKCS1_PSS_PADDING,saltLength:32},Buffer.from(t,"base64url"))}catch{return!1}}},PS384:{sign:(e,r)=>a.createSign("RSA-SHA384").update(e).end().sign({key:r,padding:a.constants.RSA_PKCS1_PSS_PADDING,saltLength:48}).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("RSA-SHA384").update(e).end().verify({key:r,padding:a.constants.RSA_PKCS1_PSS_PADDING,saltLength:48},Buffer.from(t,"base64url"))}catch{return!1}}},PS512:{sign:(e,r)=>a.createSign("RSA-SHA512").update(e).end().sign({key:r,padding:a.constants.RSA_PKCS1_PSS_PADDING,saltLength:64}).toString("base64url"),verify:(e,r,t)=>{try{return a.createVerify("RSA-SHA512").update(e).end().verify({key:r,padding:a.constants.RSA_PKCS1_PSS_PADDING,saltLength:64},Buffer.from(t,"base64url"))}catch{return!1}}},EdDSA:{sign:(e,r)=>a.sign(null,typeof e=="string"?Buffer.from(e,"utf8"):e,r).toString("base64url"),verify:(e,r,t)=>{try{return a.verify(null,typeof e=="string"?Buffer.from(e,"utf8"):e,r,Buffer.from(t,"base64url"))}catch{return!1}}}},T=Object.keys(f),A=e=>{const r=e.split(".");if(r.length!==3)throw new Error('Invalid JWT: must contain exactly 3 parts separated by "."');const[t,i,s]=r;if(!t||!i||!s)throw new Error("Invalid JWT: empty part detected");try{const n=JSON.parse(c.decode(t)),u=JSON.parse(c.decode(i));return{header:n,payload:u,signature:s}}catch(n){throw new Error(`Invalid JWT: malformed header or payload (${n.message})`)}},m=(e,r,t={})=>{const i=t.alg??"HS256",s=t.typ??"JWT";if(!(i in f))throw new Error(`Unsupported algorithm: ${i}`);const n={alg:i,typ:s};t.kid&&(n.kid=t.kid);const u=c.encode(JSON.stringify(n)),o=c.encode(JSON.stringify(e)),g=`${u}.${o}`,v=f[i].sign(g,r);return`${u}.${o}.${v}`},h=(e,r,t={})=>{let i;try{i=A(e)}catch(d){return{valid:!1,error:{reason:d.message,code:"INVALID_TOKEN"}}}const{header:s,payload:n,signature:u}=i,o=s.alg;if(!(o in f))return{valid:!1,error:{reason:`Unsupported or unknown algorithm: ${s.alg}`,code:"INVALID_ALGORITHM"}};if(t.algorithms&&t.algorithms.length>0&&!t.algorithms.includes(o))return{valid:!1,error:{reason:`Algorithm "${o}" is not in the allowed algorithms list`,code:"ALGORITHM_NOT_ALLOWED"}};if(s.typ!==void 0&&s.typ!=="JWT")return{valid:!1,error:{reason:`Invalid token type: expected 'JWT', got '${s.typ}'`,code:"INVALID_TYPE"}};const g=`${c.encode(JSON.stringify(s))}.${c.encode(JSON.stringify(n))}`;if(!f[o].verify(g,r,u))return{valid:!1,error:{reason:"Signature verification failed",code:"INVALID_SIGNATURE"}};const l=Math.floor(Date.now()/1e3),S=t.clockSkew??0;if(!t.ignoreExpiration&&n.exp!==void 0&&l>n.exp+S)return{valid:!1,error:{reason:"Token expired",code:"TOKEN_EXPIRED"}};if(n.nbf!==void 0&&l+S<n.nbf)return{valid:!1,error:{reason:"Token not yet valid",code:"TOKEN_NOT_ACTIVE"}};if(n.iat!==void 0&&l+S<n.iat)return{valid:!1,error:{reason:"Token issued in the future",code:"TOKEN_FUTURE_ISSUED"}};if(t.maxTokenAge!==void 0&&n.iat!==void 0){const d=l-n.iat;if(d>t.maxTokenAge)return{valid:!1,error:{reason:`Token age (${d}s) exceeds maximum allowed age (${t.maxTokenAge}s)`,code:"TOKEN_TOO_OLD"}}}if(t.issuer!==void 0){if(n.iss===void 0)return{valid:!1,error:{reason:'Token missing required issuer claim ("iss")',code:"MISSING_ISSUER"}};if(t.issuer!==n.iss)return{valid:!1,error:{reason:`Invalid token issuer: expected "${t.issuer}", got "${n.iss}"`,code:"INVALID_ISSUER"}}}if(t.subject!==void 0){if(n.sub===void 0)return{valid:!1,error:{reason:'Token missing required subject claim ("sub")',code:"MISSING_SUBJECT"}};if(t.subject!==n.sub)return{valid:!1,error:{reason:`Invalid token subject: expected "${t.subject}", got "${n.sub}"`,code:"INVALID_SUBJECT"}}}if(t.audience!==void 0){const d=n.aud;if(d===void 0)return{valid:!1,error:{reason:'Token missing required audience claim ("aud")',code:"MISSING_AUDIENCE"}};const I=Array.isArray(t.audience)?t.audience:[t.audience],p=Array.isArray(d)?d:[d];if(!I.some(b=>p.includes(b)))return{valid:!1,error:{reason:"Audience claim mismatch",code:"INVALID_AUDIENCE"}}}if(t.jwtId!==void 0){if(n.jti===void 0)return{valid:!1,error:{reason:'Token missing required JWT ID claim ("jti")',code:"MISSING_JTI"}};if(t.jwtId!==n.jti)return{valid:!1,error:{reason:`Invalid JWT ID: expected "${t.jwtId}", got "${n.jti}"`,code:"INVALID_JTI"}}}return{valid:!0,header:s,payload:n,signature:u}},_={sign:m,verify:h,decode:A,algorithms:f};exports.JWT=_;exports.SignatureAlgorithm=f;exports.SupportedAlgorithms=T;exports.base64Url=c;exports.decode=A;exports.sign=m;exports.verify=h;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/index.ts"],"sourcesContent":["import {\n createHmac,\n createSign,\n createVerify,\n type BinaryLike,\n type KeyLike\n} from 'crypto';\n\n// Base64URL helpers (padding-safe)\nexport const base64Url = {\n encode: (input: string | Buffer): string =>\n Buffer.from(input).toString('base64url'),\n\n decode: (input: string): string => {\n // Node.js Buffer handles unpadded base64url since v16, but we normalize for safety\n return Buffer.from(input, 'base64url').toString();\n }\n};\n\n// Standard JWT payload claims\nexport interface JWTPayload {\n /**\n * Issuer\n */\n iss?: string;\n /**\n * Subject\n */\n sub?: string;\n /**\n * Audience\n */\n aud?: string | string[];\n /**\n * Expiration Time (as UNIX timestamp)\n */\n exp?: number;\n /**\n * Not Before (as UNIX timestamp)\n */\n nbf?: number;\n /**\n * Issued At (as UNIX timestamp)\n */\n iat?: number;\n /**\n * JWT ID\n */\n jti?: string;\n /**\n * Session ID\n */\n sid?: string;\n /**\n * Custom claims\n */\n [key: string]: unknown;\n}\n\nexport interface JWTHeader {\n alg: string; // Allow unknown algs during decode\n typ?: string;\n kid?: string;\n}\n\nexport interface JWT {\n header: JWTHeader;\n payload: JWTPayload;\n signature: string;\n}\n\n// Signature algorithms\nexport const SignatureAlgorithm = {\n // HMAC\n HS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha256', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createHmac('sha256', secret).update(data).digest('base64url') === signature\n },\n HS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha384', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createHmac('sha384', secret).update(data).digest('base64url') === signature\n },\n HS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha512', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createHmac('sha512', secret).update(data).digest('base64url') === signature\n },\n\n // RSA (DER-encoded signatures, base64url)\n RS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('RSA-SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n RS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('RSA-SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n RS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('RSA-SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n\n // ECDSA (DER-encoded by default — no dsaEncoding!)\n ES256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n ES384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n ES512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n }\n} as const;\n\nexport type SupportedAlgorithm = keyof typeof SignatureAlgorithm;\n\nexport const SupportedAlgorithms = Object.keys(SignatureAlgorithm) as Array<SupportedAlgorithm>;\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): JWT => {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT: must contain exactly 3 parts separated by \".\"');\n }\n\n const [headerPart, payloadPart, signature] = parts;\n\n if (!headerPart || !payloadPart || !signature) {\n throw new Error('Invalid JWT: empty part detected');\n }\n\n try {\n const header = JSON.parse(base64Url.decode(headerPart)) as JWTHeader;\n const payload = JSON.parse(base64Url.decode(payloadPart)) as JWTPayload;\n return { header, payload, signature };\n } catch (err) {\n throw new Error(`Invalid JWT: malformed header or payload (${(err as Error).message})`);\n }\n};\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): string => {\n const alg = options.alg ?? 'HS256';\n const typ = options.typ ?? 'JWT';\n\n if (!(alg in SignatureAlgorithm)) {\n throw new Error(`Unsupported algorithm: ${alg}`);\n }\n\n const header: JWTHeader = { alg, typ };\n if (options.kid) header.kid = options.kid;\n\n const headerEncoded = base64Url.encode(JSON.stringify(header));\n const payloadEncoded = base64Url.encode(JSON.stringify(payload));\n\n const signingInput = `${headerEncoded}.${payloadEncoded}`;\n const signature = SignatureAlgorithm[alg].sign(signingInput, secret);\n\n return `${headerEncoded}.${payloadEncoded}.${signature}`;\n};\n\n/**\n * Verify and validate a JWT\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n } = {}\n):\n | { valid: true; header: JWTHeader; payload: JWTPayload; signature: string }\n | { valid: false; error: { reason: string; code: string } } => {\n let decoded: JWT;\n try {\n decoded = decode(token);\n } catch (err) {\n return {\n valid: false,\n error: {\n reason: (err as Error).message,\n code: 'INVALID_TOKEN'\n }\n };\n }\n\n const { header, payload, signature } = decoded;\n\n // Validate algorithm\n const alg = header.alg as SupportedAlgorithm;\n if (!(alg in SignatureAlgorithm)) {\n return {\n valid: false,\n error: {\n reason: `Unsupported or unknown algorithm: ${header.alg}`,\n code: 'INVALID_ALGORITHM'\n }\n };\n }\n\n // Optional: validate 'typ' header\n if (header.typ && header.typ !== 'JWT') {\n return {\n valid: false,\n error: {\n reason: `Invalid token type: expected 'JWT', got '${header.typ}'`,\n code: 'INVALID_TYPE'\n }\n };\n }\n\n // Verify signature\n const signingInput = `${base64Url.encode(JSON.stringify(header))}.${base64Url.encode(JSON.stringify(payload))}`;\n const isValidSignature = SignatureAlgorithm[alg].verify(signingInput, secret, signature);\n\n if (!isValidSignature) {\n return {\n valid: false,\n error: {\n reason: \"Signature verification failed\",\n code: 'INVALID_SIGNATURE'\n }\n };\n }\n\n // Time validation\n const now = Math.floor(Date.now() / 1000);\n const skew = options.clockSkew ?? 0;\n\n if (!options.ignoreExpiration) {\n if (payload.exp !== undefined && now > payload.exp + skew) {\n return {\n valid: false,\n error: {\n reason: 'Token expired',\n code: 'TOKEN_EXPIRED'\n }\n };\n }\n }\n\n if (payload.nbf !== undefined && now + skew < payload.nbf) {\n return {\n valid: false,\n error: {\n reason: 'Token not yet valid',\n code: 'TOKEN_NOT_ACTIVE'\n }\n };\n }\n\n if (payload.iat !== undefined && now + skew < payload.iat) {\n return {\n valid: false,\n error: {\n reason: 'Token issued in the future',\n code: 'TOKEN_FUTURE_ISSUED'\n }\n };\n }\n\n return { valid: true, header, payload, signature };\n};\n\n// Optional: namespace export (not default)\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n};\n"],"names":["base64Url","input","SignatureAlgorithm","data","secret","createHmac","signature","createSign","createVerify","SupportedAlgorithms","decode","token","parts","headerPart","payloadPart","header","payload","err","sign","options","alg","typ","headerEncoded","payloadEncoded","signingInput","verify","decoded","now","skew","JWT"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/index.ts"],"sourcesContent":["import crypto, {\n createHmac,\n createSign,\n createVerify,\n sign as cryptoSign,\n verify as cryptoVerify,\n timingSafeEqual,\n type BinaryLike,\n type KeyLike\n} from 'crypto';\n\n// Base64URL helpers (padding-safe)\nexport const base64Url = {\n encode: (input: string | Buffer): string =>\n Buffer.from(input).toString('base64url'),\n\n decode: (input: string): string => {\n // Node.js Buffer handles unpadded base64url since v16, but we normalize for safety\n return Buffer.from(input, 'base64url').toString();\n }\n};\n\n// Timing-safe string comparison to prevent timing attacks\nconst timingSafeCompare = (a: string, b: string): boolean => {\n if (a.length !== b.length) {\n return false;\n }\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n};\n\n// Standard JWT payload claims\nexport interface JWTPayload {\n /**\n * Issuer\n */\n iss?: string;\n /**\n * Subject\n */\n sub?: string;\n /**\n * Audience\n */\n aud?: string | string[];\n /**\n * Expiration Time (as UNIX timestamp)\n */\n exp?: number;\n /**\n * Not Before (as UNIX timestamp)\n */\n nbf?: number;\n /**\n * Issued At (as UNIX timestamp)\n */\n iat?: number;\n /**\n * JWT ID\n */\n jti?: string;\n /**\n * Session ID\n */\n sid?: string;\n\n /**\n * Custom claims\n */\n [key: string]: unknown;\n}\n\nexport interface JWTHeader {\n alg: string; // Allow unknown algs during decode\n typ?: string;\n kid?: string;\n}\n\nexport interface JWT {\n header: JWTHeader;\n payload: JWTPayload;\n signature: string;\n}\n\n// Signature algorithms\nexport const SignatureAlgorithm = {\n // HMAC\n HS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha256', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n const expected = createHmac('sha256', secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n },\n HS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha384', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n const expected = createHmac('sha384', secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n },\n HS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha512', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n const expected = createHmac('sha512', secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n },\n\n // RSA (DER-encoded signatures, base64url)\n RS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n RS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n RS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n\n // ECDSA (DER-encoded by default — no dsaEncoding!)\n ES256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n ES384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n ES512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n ES256K: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n PS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA256')\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 32\n })\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA256')\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 32\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n PS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA384')\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 48\n })\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA384')\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 48\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n PS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA512')\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 64\n })\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA512')\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 64\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n EdDSA: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n cryptoSign(null, typeof data === 'string' ? Buffer.from(data, 'utf8') : data, secret)\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return cryptoVerify(\n null,\n typeof data === 'string' ? Buffer.from(data, 'utf8') : data,\n secret,\n Buffer.from(signature, 'base64url')\n );\n } catch {\n return false;\n }\n }\n }\n} as const;\n\nexport type SupportedAlgorithm = keyof typeof SignatureAlgorithm;\n\nexport const SupportedAlgorithms = Object.keys(SignatureAlgorithm) as Array<SupportedAlgorithm>;\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): JWT => {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT: must contain exactly 3 parts separated by \".\"');\n }\n\n const [headerPart, payloadPart, signature] = parts;\n\n if (!headerPart || !payloadPart || !signature) {\n throw new Error('Invalid JWT: empty part detected');\n }\n\n try {\n const header = JSON.parse(base64Url.decode(headerPart)) as JWTHeader;\n const payload = JSON.parse(base64Url.decode(payloadPart)) as JWTPayload;\n return {header, payload, signature};\n } catch (err) {\n throw new Error(`Invalid JWT: malformed header or payload (${(err as Error).message})`);\n }\n};\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): string => {\n const alg = options.alg ?? 'HS256';\n const typ = options.typ ?? 'JWT';\n\n if (!(alg in SignatureAlgorithm)) {\n throw new Error(`Unsupported algorithm: ${alg}`);\n }\n\n const header: JWTHeader = {alg, typ};\n if (options.kid) header.kid = options.kid;\n\n const headerEncoded = base64Url.encode(JSON.stringify(header));\n const payloadEncoded = base64Url.encode(JSON.stringify(payload));\n\n const signingInput = `${headerEncoded}.${payloadEncoded}`;\n const signature = SignatureAlgorithm[alg].sign(signingInput, secret);\n\n return `${headerEncoded}.${payloadEncoded}.${signature}`;\n};\n\n/**\n * Verify and validate a JWT\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n algorithms?: SupportedAlgorithm[]; // Whitelist of allowed algorithms\n issuer?: string;\n subject?: string;\n audience?: string | string[];\n jwtId?: string;\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n maxTokenAge?: number; // Maximum age in seconds\n } = {}\n):\n | { valid: true; header: JWTHeader; payload: JWTPayload; signature: string }\n | { valid: false; error: { reason: string; code: string } } => {\n let decoded: JWT;\n try {\n decoded = decode(token);\n } catch (err) {\n return {\n valid: false,\n error: {\n reason: (err as Error).message,\n code: 'INVALID_TOKEN'\n }\n };\n }\n\n const {header, payload, signature} = decoded;\n\n // Validate algorithm\n const alg = header.alg as SupportedAlgorithm;\n if (!(alg in SignatureAlgorithm)) {\n return {\n valid: false,\n error: {\n reason: `Unsupported or unknown algorithm: ${header.alg}`,\n code: 'INVALID_ALGORITHM'\n }\n };\n }\n\n // Algorithm whitelist validation (prevents algorithm confusion attacks)\n if (options.algorithms && options.algorithms.length > 0) {\n if (!options.algorithms.includes(alg)) {\n return {\n valid: false,\n error: {\n reason: `Algorithm \"${alg}\" is not in the allowed algorithms list`,\n code: 'ALGORITHM_NOT_ALLOWED'\n }\n };\n }\n }\n\n // Validate 'typ' header (must be 'JWT' if present)\n if (header.typ !== undefined && header.typ !== 'JWT') {\n return {\n valid: false,\n error: {\n reason: `Invalid token type: expected 'JWT', got '${header.typ}'`,\n code: 'INVALID_TYPE'\n }\n };\n }\n\n // Verify signature\n const signingInput = `${base64Url.encode(JSON.stringify(header))}.${base64Url.encode(JSON.stringify(payload))}`;\n const isValidSignature = SignatureAlgorithm[alg].verify(signingInput, secret, signature);\n\n if (!isValidSignature) {\n return {\n valid: false,\n error: {\n reason: \"Signature verification failed\",\n code: 'INVALID_SIGNATURE'\n }\n };\n }\n\n // Time validation\n const now = Math.floor(Date.now() / 1000);\n const skew = options.clockSkew ?? 0;\n\n if (!options.ignoreExpiration) {\n if (payload.exp !== undefined && now > payload.exp + skew) {\n return {\n valid: false,\n error: {\n reason: 'Token expired',\n code: 'TOKEN_EXPIRED'\n }\n };\n }\n }\n\n if (payload.nbf !== undefined && now + skew < payload.nbf) {\n return {\n valid: false,\n error: {\n reason: 'Token not yet valid',\n code: 'TOKEN_NOT_ACTIVE'\n }\n };\n }\n\n if (payload.iat !== undefined && now + skew < payload.iat) {\n return {\n valid: false,\n error: {\n reason: 'Token issued in the future',\n code: 'TOKEN_FUTURE_ISSUED'\n }\n };\n }\n\n // Maximum token age validation\n if (options.maxTokenAge !== undefined && payload.iat !== undefined) {\n const tokenAge = now - payload.iat;\n if (tokenAge > options.maxTokenAge) {\n return {\n valid: false,\n error: {\n reason: `Token age (${tokenAge}s) exceeds maximum allowed age (${options.maxTokenAge}s)`,\n code: 'TOKEN_TOO_OLD'\n }\n };\n }\n }\n\n // --- Claim validations (only if options provided) ---\n\n // Issuer (`iss`)\n if (options.issuer !== undefined) {\n if (payload.iss === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required issuer claim (\"iss\")',\n code: 'MISSING_ISSUER'\n }\n };\n }\n if (options.issuer !== payload.iss) {\n return {\n valid: false,\n error: {\n reason: `Invalid token issuer: expected \"${options.issuer}\", got \"${payload.iss}\"`,\n code: 'INVALID_ISSUER'\n }\n };\n }\n }\n\n // Subject (`sub`)\n if (options.subject !== undefined) {\n if (payload.sub === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required subject claim (\"sub\")',\n code: 'MISSING_SUBJECT'\n }\n };\n }\n if (options.subject !== payload.sub) {\n return {\n valid: false,\n error: {\n reason: `Invalid token subject: expected \"${options.subject}\", got \"${payload.sub}\"`,\n code: 'INVALID_SUBJECT'\n }\n };\n }\n }\n\n // Audience (`aud`)\n if (options.audience !== undefined) {\n const aud = payload.aud;\n if (aud === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required audience claim (\"aud\")',\n code: 'MISSING_AUDIENCE'\n }\n };\n }\n\n const expectedAud = Array.isArray(options.audience) ? options.audience : [options.audience];\n const tokenAud = Array.isArray(aud) ? aud : [aud];\n\n const hasMatch = expectedAud.some(a => tokenAud.includes(a));\n if (!hasMatch) {\n return {\n valid: false,\n error: {\n reason: 'Audience claim mismatch',\n code: 'INVALID_AUDIENCE'\n }\n };\n }\n }\n\n // JWT ID (`jti`)\n if (options.jwtId !== undefined) {\n if (payload.jti === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required JWT ID claim (\"jti\")',\n code: 'MISSING_JTI'\n }\n };\n }\n if (options.jwtId !== payload.jti) {\n return {\n valid: false,\n error: {\n reason: `Invalid JWT ID: expected \"${options.jwtId}\", got \"${payload.jti}\"`,\n code: 'INVALID_JTI'\n }\n };\n }\n }\n\n return {valid: true, header, payload, signature};\n};\n\n// Optional: namespace export\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n};\n"],"names":["base64Url","input","timingSafeCompare","a","b","timingSafeEqual","SignatureAlgorithm","data","secret","createHmac","signature","expected","createSign","createVerify","crypto","cryptoSign","cryptoVerify","SupportedAlgorithms","decode","token","parts","headerPart","payloadPart","header","payload","err","sign","options","alg","typ","headerEncoded","payloadEncoded","signingInput","verify","decoded","now","skew","tokenAge","aud","expectedAud","tokenAud","JWT"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -88,6 +88,26 @@ export declare const SignatureAlgorithm: {
|
|
|
88
88
|
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
89
89
|
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
90
90
|
};
|
|
91
|
+
readonly ES256K: {
|
|
92
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
93
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
94
|
+
};
|
|
95
|
+
readonly PS256: {
|
|
96
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
97
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
98
|
+
};
|
|
99
|
+
readonly PS384: {
|
|
100
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
101
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
102
|
+
};
|
|
103
|
+
readonly PS512: {
|
|
104
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
105
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
106
|
+
};
|
|
107
|
+
readonly EdDSA: {
|
|
108
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
109
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
110
|
+
};
|
|
91
111
|
};
|
|
92
112
|
export type SupportedAlgorithm = keyof typeof SignatureAlgorithm;
|
|
93
113
|
export declare const SupportedAlgorithms: Array<SupportedAlgorithm>;
|
|
@@ -107,8 +127,14 @@ export declare const sign: (payload: JWTPayload, secret: KeyLike, options?: {
|
|
|
107
127
|
* Verify and validate a JWT
|
|
108
128
|
*/
|
|
109
129
|
export declare const verify: (token: string, secret: KeyLike, options?: {
|
|
130
|
+
algorithms?: SupportedAlgorithm[];
|
|
131
|
+
issuer?: string;
|
|
132
|
+
subject?: string;
|
|
133
|
+
audience?: string | string[];
|
|
134
|
+
jwtId?: string;
|
|
110
135
|
ignoreExpiration?: boolean;
|
|
111
136
|
clockSkew?: number;
|
|
137
|
+
maxTokenAge?: number;
|
|
112
138
|
}) => {
|
|
113
139
|
valid: true;
|
|
114
140
|
header: JWTHeader;
|
|
@@ -128,8 +154,14 @@ export declare const JWT: {
|
|
|
128
154
|
typ?: string;
|
|
129
155
|
}) => string;
|
|
130
156
|
verify: (token: string, secret: KeyLike, options?: {
|
|
157
|
+
algorithms?: SupportedAlgorithm[];
|
|
158
|
+
issuer?: string;
|
|
159
|
+
subject?: string;
|
|
160
|
+
audience?: string | string[];
|
|
161
|
+
jwtId?: string;
|
|
131
162
|
ignoreExpiration?: boolean;
|
|
132
163
|
clockSkew?: number;
|
|
164
|
+
maxTokenAge?: number;
|
|
133
165
|
}) => {
|
|
134
166
|
valid: true;
|
|
135
167
|
header: JWTHeader;
|
|
@@ -180,5 +212,25 @@ export declare const JWT: {
|
|
|
180
212
|
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
181
213
|
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
182
214
|
};
|
|
215
|
+
readonly ES256K: {
|
|
216
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
217
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
218
|
+
};
|
|
219
|
+
readonly PS256: {
|
|
220
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
221
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
222
|
+
};
|
|
223
|
+
readonly PS384: {
|
|
224
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
225
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
226
|
+
};
|
|
227
|
+
readonly PS512: {
|
|
228
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
229
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
230
|
+
};
|
|
231
|
+
readonly EdDSA: {
|
|
232
|
+
readonly sign: (data: BinaryLike, secret: KeyLike) => string;
|
|
233
|
+
readonly verify: (data: BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
234
|
+
};
|
|
183
235
|
};
|
|
184
236
|
};
|
package/dist/index.es.js
CHANGED
|
@@ -1,100 +1,238 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const
|
|
1
|
+
import l, { sign as T, createSign as s, createHmac as c, verify as E, createVerify as d, timingSafeEqual as N } from "crypto";
|
|
2
|
+
const S = {
|
|
3
3
|
encode: (e) => Buffer.from(e).toString("base64url"),
|
|
4
4
|
decode: (e) => Buffer.from(e, "base64url").toString()
|
|
5
|
-
},
|
|
5
|
+
}, h = (e, r) => e.length !== r.length ? !1 : N(Buffer.from(e), Buffer.from(r)), g = {
|
|
6
6
|
// HMAC
|
|
7
7
|
HS256: {
|
|
8
|
-
sign: (e, r) =>
|
|
9
|
-
verify: (e, r, t) =>
|
|
8
|
+
sign: (e, r) => c("sha256", r).update(e).digest("base64url"),
|
|
9
|
+
verify: (e, r, t) => {
|
|
10
|
+
const n = c("sha256", r).update(e).digest("base64url");
|
|
11
|
+
return h(n, t);
|
|
12
|
+
}
|
|
10
13
|
},
|
|
11
14
|
HS384: {
|
|
12
|
-
sign: (e, r) =>
|
|
13
|
-
verify: (e, r, t) =>
|
|
15
|
+
sign: (e, r) => c("sha384", r).update(e).digest("base64url"),
|
|
16
|
+
verify: (e, r, t) => {
|
|
17
|
+
const n = c("sha384", r).update(e).digest("base64url");
|
|
18
|
+
return h(n, t);
|
|
19
|
+
}
|
|
14
20
|
},
|
|
15
21
|
HS512: {
|
|
16
|
-
sign: (e, r) =>
|
|
17
|
-
verify: (e, r, t) =>
|
|
22
|
+
sign: (e, r) => c("sha512", r).update(e).digest("base64url"),
|
|
23
|
+
verify: (e, r, t) => {
|
|
24
|
+
const n = c("sha512", r).update(e).digest("base64url");
|
|
25
|
+
return h(n, t);
|
|
26
|
+
}
|
|
18
27
|
},
|
|
19
28
|
// RSA (DER-encoded signatures, base64url)
|
|
20
29
|
RS256: {
|
|
21
|
-
sign: (e, r) =>
|
|
22
|
-
verify: (e, r, t) =>
|
|
30
|
+
sign: (e, r) => s("RSA-SHA256").update(e).end().sign(r).toString("base64url"),
|
|
31
|
+
verify: (e, r, t) => {
|
|
32
|
+
try {
|
|
33
|
+
return d("RSA-SHA256").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
34
|
+
} catch {
|
|
35
|
+
return !1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
23
38
|
},
|
|
24
39
|
RS384: {
|
|
25
|
-
sign: (e, r) =>
|
|
26
|
-
verify: (e, r, t) =>
|
|
40
|
+
sign: (e, r) => s("RSA-SHA384").update(e).end().sign(r).toString("base64url"),
|
|
41
|
+
verify: (e, r, t) => {
|
|
42
|
+
try {
|
|
43
|
+
return d("RSA-SHA384").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
44
|
+
} catch {
|
|
45
|
+
return !1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
27
48
|
},
|
|
28
49
|
RS512: {
|
|
29
|
-
sign: (e, r) =>
|
|
30
|
-
verify: (e, r, t) =>
|
|
50
|
+
sign: (e, r) => s("RSA-SHA512").update(e).end().sign(r).toString("base64url"),
|
|
51
|
+
verify: (e, r, t) => {
|
|
52
|
+
try {
|
|
53
|
+
return d("RSA-SHA512").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
54
|
+
} catch {
|
|
55
|
+
return !1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
31
58
|
},
|
|
32
59
|
// ECDSA (DER-encoded by default — no dsaEncoding!)
|
|
33
60
|
ES256: {
|
|
34
|
-
sign: (e, r) =>
|
|
35
|
-
verify: (e, r, t) =>
|
|
61
|
+
sign: (e, r) => s("SHA256").update(e).end().sign(r).toString("base64url"),
|
|
62
|
+
verify: (e, r, t) => {
|
|
63
|
+
try {
|
|
64
|
+
return d("SHA256").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
65
|
+
} catch {
|
|
66
|
+
return !1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
36
69
|
},
|
|
37
70
|
ES384: {
|
|
38
|
-
sign: (e, r) =>
|
|
39
|
-
verify: (e, r, t) =>
|
|
71
|
+
sign: (e, r) => s("SHA384").update(e).end().sign(r).toString("base64url"),
|
|
72
|
+
verify: (e, r, t) => {
|
|
73
|
+
try {
|
|
74
|
+
return d("SHA384").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
75
|
+
} catch {
|
|
76
|
+
return !1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
40
79
|
},
|
|
41
80
|
ES512: {
|
|
42
|
-
sign: (e, r) =>
|
|
43
|
-
verify: (e, r, t) =>
|
|
81
|
+
sign: (e, r) => s("SHA512").update(e).end().sign(r).toString("base64url"),
|
|
82
|
+
verify: (e, r, t) => {
|
|
83
|
+
try {
|
|
84
|
+
return d("SHA512").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
85
|
+
} catch {
|
|
86
|
+
return !1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
ES256K: {
|
|
91
|
+
sign: (e, r) => s("SHA256").update(e).end().sign(r).toString("base64url"),
|
|
92
|
+
verify: (e, r, t) => {
|
|
93
|
+
try {
|
|
94
|
+
return d("SHA256").update(e).end().verify(r, Buffer.from(t, "base64url"));
|
|
95
|
+
} catch {
|
|
96
|
+
return !1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
PS256: {
|
|
101
|
+
sign: (e, r) => s("RSA-SHA256").update(e).end().sign({
|
|
102
|
+
//@ts-ignore
|
|
103
|
+
key: r,
|
|
104
|
+
padding: l.constants.RSA_PKCS1_PSS_PADDING,
|
|
105
|
+
saltLength: 32
|
|
106
|
+
}).toString("base64url"),
|
|
107
|
+
verify: (e, r, t) => {
|
|
108
|
+
try {
|
|
109
|
+
return d("RSA-SHA256").update(e).end().verify({
|
|
110
|
+
//@ts-ignore
|
|
111
|
+
key: r,
|
|
112
|
+
padding: l.constants.RSA_PKCS1_PSS_PADDING,
|
|
113
|
+
saltLength: 32
|
|
114
|
+
}, Buffer.from(t, "base64url"));
|
|
115
|
+
} catch {
|
|
116
|
+
return !1;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
PS384: {
|
|
121
|
+
sign: (e, r) => s("RSA-SHA384").update(e).end().sign({
|
|
122
|
+
//@ts-ignore
|
|
123
|
+
key: r,
|
|
124
|
+
padding: l.constants.RSA_PKCS1_PSS_PADDING,
|
|
125
|
+
saltLength: 48
|
|
126
|
+
}).toString("base64url"),
|
|
127
|
+
verify: (e, r, t) => {
|
|
128
|
+
try {
|
|
129
|
+
return d("RSA-SHA384").update(e).end().verify({
|
|
130
|
+
//@ts-ignore
|
|
131
|
+
key: r,
|
|
132
|
+
padding: l.constants.RSA_PKCS1_PSS_PADDING,
|
|
133
|
+
saltLength: 48
|
|
134
|
+
}, Buffer.from(t, "base64url"));
|
|
135
|
+
} catch {
|
|
136
|
+
return !1;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
PS512: {
|
|
141
|
+
sign: (e, r) => s("RSA-SHA512").update(e).end().sign({
|
|
142
|
+
//@ts-ignore
|
|
143
|
+
key: r,
|
|
144
|
+
padding: l.constants.RSA_PKCS1_PSS_PADDING,
|
|
145
|
+
saltLength: 64
|
|
146
|
+
}).toString("base64url"),
|
|
147
|
+
verify: (e, r, t) => {
|
|
148
|
+
try {
|
|
149
|
+
return d("RSA-SHA512").update(e).end().verify({
|
|
150
|
+
//@ts-ignore
|
|
151
|
+
key: r,
|
|
152
|
+
padding: l.constants.RSA_PKCS1_PSS_PADDING,
|
|
153
|
+
saltLength: 64
|
|
154
|
+
}, Buffer.from(t, "base64url"));
|
|
155
|
+
} catch {
|
|
156
|
+
return !1;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
EdDSA: {
|
|
161
|
+
sign: (e, r) => T(null, typeof e == "string" ? Buffer.from(e, "utf8") : e, r).toString("base64url"),
|
|
162
|
+
verify: (e, r, t) => {
|
|
163
|
+
try {
|
|
164
|
+
return E(
|
|
165
|
+
null,
|
|
166
|
+
typeof e == "string" ? Buffer.from(e, "utf8") : e,
|
|
167
|
+
r,
|
|
168
|
+
Buffer.from(t, "base64url")
|
|
169
|
+
);
|
|
170
|
+
} catch {
|
|
171
|
+
return !1;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
44
174
|
}
|
|
45
|
-
},
|
|
175
|
+
}, P = Object.keys(g), I = (e) => {
|
|
46
176
|
const r = e.split(".");
|
|
47
177
|
if (r.length !== 3)
|
|
48
178
|
throw new Error('Invalid JWT: must contain exactly 3 parts separated by "."');
|
|
49
|
-
const [t,
|
|
50
|
-
if (!t || !
|
|
179
|
+
const [t, n, i] = r;
|
|
180
|
+
if (!t || !n || !i)
|
|
51
181
|
throw new Error("Invalid JWT: empty part detected");
|
|
52
182
|
try {
|
|
53
|
-
const a = JSON.parse(
|
|
54
|
-
return { header: a, payload:
|
|
183
|
+
const a = JSON.parse(S.decode(t)), o = JSON.parse(S.decode(n));
|
|
184
|
+
return { header: a, payload: o, signature: i };
|
|
55
185
|
} catch (a) {
|
|
56
186
|
throw new Error(`Invalid JWT: malformed header or payload (${a.message})`);
|
|
57
187
|
}
|
|
58
|
-
},
|
|
59
|
-
const
|
|
60
|
-
if (!(
|
|
61
|
-
throw new Error(`Unsupported algorithm: ${
|
|
62
|
-
const a = { alg:
|
|
188
|
+
}, k = (e, r, t = {}) => {
|
|
189
|
+
const n = t.alg ?? "HS256", i = t.typ ?? "JWT";
|
|
190
|
+
if (!(n in g))
|
|
191
|
+
throw new Error(`Unsupported algorithm: ${n}`);
|
|
192
|
+
const a = { alg: n, typ: i };
|
|
63
193
|
t.kid && (a.kid = t.kid);
|
|
64
|
-
const
|
|
65
|
-
return `${
|
|
66
|
-
},
|
|
67
|
-
let
|
|
194
|
+
const o = S.encode(JSON.stringify(a)), f = S.encode(JSON.stringify(e)), A = `${o}.${f}`, m = g[n].sign(A, r);
|
|
195
|
+
return `${o}.${f}.${m}`;
|
|
196
|
+
}, D = (e, r, t = {}) => {
|
|
197
|
+
let n;
|
|
68
198
|
try {
|
|
69
|
-
|
|
70
|
-
} catch (
|
|
199
|
+
n = I(e);
|
|
200
|
+
} catch (u) {
|
|
71
201
|
return {
|
|
72
202
|
valid: !1,
|
|
73
203
|
error: {
|
|
74
|
-
reason:
|
|
204
|
+
reason: u.message,
|
|
75
205
|
code: "INVALID_TOKEN"
|
|
76
206
|
}
|
|
77
207
|
};
|
|
78
208
|
}
|
|
79
|
-
const { header:
|
|
80
|
-
if (!(
|
|
209
|
+
const { header: i, payload: a, signature: o } = n, f = i.alg;
|
|
210
|
+
if (!(f in g))
|
|
81
211
|
return {
|
|
82
212
|
valid: !1,
|
|
83
213
|
error: {
|
|
84
|
-
reason: `Unsupported or unknown algorithm: ${
|
|
214
|
+
reason: `Unsupported or unknown algorithm: ${i.alg}`,
|
|
85
215
|
code: "INVALID_ALGORITHM"
|
|
86
216
|
}
|
|
87
217
|
};
|
|
88
|
-
if (
|
|
218
|
+
if (t.algorithms && t.algorithms.length > 0 && !t.algorithms.includes(f))
|
|
219
|
+
return {
|
|
220
|
+
valid: !1,
|
|
221
|
+
error: {
|
|
222
|
+
reason: `Algorithm "${f}" is not in the allowed algorithms list`,
|
|
223
|
+
code: "ALGORITHM_NOT_ALLOWED"
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
if (i.typ !== void 0 && i.typ !== "JWT")
|
|
89
227
|
return {
|
|
90
228
|
valid: !1,
|
|
91
229
|
error: {
|
|
92
|
-
reason: `Invalid token type: expected 'JWT', got '${
|
|
230
|
+
reason: `Invalid token type: expected 'JWT', got '${i.typ}'`,
|
|
93
231
|
code: "INVALID_TYPE"
|
|
94
232
|
}
|
|
95
233
|
};
|
|
96
|
-
const
|
|
97
|
-
if (!
|
|
234
|
+
const A = `${S.encode(JSON.stringify(i))}.${S.encode(JSON.stringify(a))}`;
|
|
235
|
+
if (!g[f].verify(A, r, o))
|
|
98
236
|
return {
|
|
99
237
|
valid: !1,
|
|
100
238
|
error: {
|
|
@@ -102,39 +240,130 @@ const f = {
|
|
|
102
240
|
code: "INVALID_SIGNATURE"
|
|
103
241
|
}
|
|
104
242
|
};
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
243
|
+
const y = Math.floor(Date.now() / 1e3), v = t.clockSkew ?? 0;
|
|
244
|
+
if (!t.ignoreExpiration && a.exp !== void 0 && y > a.exp + v)
|
|
245
|
+
return {
|
|
246
|
+
valid: !1,
|
|
247
|
+
error: {
|
|
248
|
+
reason: "Token expired",
|
|
249
|
+
code: "TOKEN_EXPIRED"
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
if (a.nbf !== void 0 && y + v < a.nbf)
|
|
253
|
+
return {
|
|
254
|
+
valid: !1,
|
|
255
|
+
error: {
|
|
256
|
+
reason: "Token not yet valid",
|
|
257
|
+
code: "TOKEN_NOT_ACTIVE"
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
if (a.iat !== void 0 && y + v < a.iat)
|
|
261
|
+
return {
|
|
262
|
+
valid: !1,
|
|
263
|
+
error: {
|
|
264
|
+
reason: "Token issued in the future",
|
|
265
|
+
code: "TOKEN_FUTURE_ISSUED"
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
if (t.maxTokenAge !== void 0 && a.iat !== void 0) {
|
|
269
|
+
const u = y - a.iat;
|
|
270
|
+
if (u > t.maxTokenAge)
|
|
271
|
+
return {
|
|
272
|
+
valid: !1,
|
|
273
|
+
error: {
|
|
274
|
+
reason: `Token age (${u}s) exceeds maximum allowed age (${t.maxTokenAge}s)`,
|
|
275
|
+
code: "TOKEN_TOO_OLD"
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
if (t.issuer !== void 0) {
|
|
280
|
+
if (a.iss === void 0)
|
|
281
|
+
return {
|
|
282
|
+
valid: !1,
|
|
283
|
+
error: {
|
|
284
|
+
reason: 'Token missing required issuer claim ("iss")',
|
|
285
|
+
code: "MISSING_ISSUER"
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
if (t.issuer !== a.iss)
|
|
289
|
+
return {
|
|
290
|
+
valid: !1,
|
|
291
|
+
error: {
|
|
292
|
+
reason: `Invalid token issuer: expected "${t.issuer}", got "${a.iss}"`,
|
|
293
|
+
code: "INVALID_ISSUER"
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (t.subject !== void 0) {
|
|
298
|
+
if (a.sub === void 0)
|
|
299
|
+
return {
|
|
300
|
+
valid: !1,
|
|
301
|
+
error: {
|
|
302
|
+
reason: 'Token missing required subject claim ("sub")',
|
|
303
|
+
code: "MISSING_SUBJECT"
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
if (t.subject !== a.sub)
|
|
307
|
+
return {
|
|
308
|
+
valid: !1,
|
|
309
|
+
error: {
|
|
310
|
+
reason: `Invalid token subject: expected "${t.subject}", got "${a.sub}"`,
|
|
311
|
+
code: "INVALID_SUBJECT"
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
if (t.audience !== void 0) {
|
|
316
|
+
const u = a.aud;
|
|
317
|
+
if (u === void 0)
|
|
318
|
+
return {
|
|
319
|
+
valid: !1,
|
|
320
|
+
error: {
|
|
321
|
+
reason: 'Token missing required audience claim ("aud")',
|
|
322
|
+
code: "MISSING_AUDIENCE"
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const p = Array.isArray(t.audience) ? t.audience : [t.audience], b = Array.isArray(u) ? u : [u];
|
|
326
|
+
if (!p.some((_) => b.includes(_)))
|
|
327
|
+
return {
|
|
328
|
+
valid: !1,
|
|
329
|
+
error: {
|
|
330
|
+
reason: "Audience claim mismatch",
|
|
331
|
+
code: "INVALID_AUDIENCE"
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
if (t.jwtId !== void 0) {
|
|
336
|
+
if (a.jti === void 0)
|
|
337
|
+
return {
|
|
338
|
+
valid: !1,
|
|
339
|
+
error: {
|
|
340
|
+
reason: 'Token missing required JWT ID claim ("jti")',
|
|
341
|
+
code: "MISSING_JTI"
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
if (t.jwtId !== a.jti)
|
|
345
|
+
return {
|
|
346
|
+
valid: !1,
|
|
347
|
+
error: {
|
|
348
|
+
reason: `Invalid JWT ID: expected "${t.jwtId}", got "${a.jti}"`,
|
|
349
|
+
code: "INVALID_JTI"
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
return { valid: !0, header: i, payload: a, signature: o };
|
|
354
|
+
}, $ = {
|
|
355
|
+
sign: k,
|
|
356
|
+
verify: D,
|
|
357
|
+
decode: I,
|
|
358
|
+
algorithms: g
|
|
130
359
|
};
|
|
131
360
|
export {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
361
|
+
$ as JWT,
|
|
362
|
+
g as SignatureAlgorithm,
|
|
363
|
+
P as SupportedAlgorithms,
|
|
364
|
+
S as base64Url,
|
|
365
|
+
I as decode,
|
|
366
|
+
k as sign,
|
|
367
|
+
D as verify
|
|
139
368
|
};
|
|
140
369
|
//# sourceMappingURL=index.es.js.map
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/index.ts"],"sourcesContent":["import {\n createHmac,\n createSign,\n createVerify,\n type BinaryLike,\n type KeyLike\n} from 'crypto';\n\n// Base64URL helpers (padding-safe)\nexport const base64Url = {\n encode: (input: string | Buffer): string =>\n Buffer.from(input).toString('base64url'),\n\n decode: (input: string): string => {\n // Node.js Buffer handles unpadded base64url since v16, but we normalize for safety\n return Buffer.from(input, 'base64url').toString();\n }\n};\n\n// Standard JWT payload claims\nexport interface JWTPayload {\n /**\n * Issuer\n */\n iss?: string;\n /**\n * Subject\n */\n sub?: string;\n /**\n * Audience\n */\n aud?: string | string[];\n /**\n * Expiration Time (as UNIX timestamp)\n */\n exp?: number;\n /**\n * Not Before (as UNIX timestamp)\n */\n nbf?: number;\n /**\n * Issued At (as UNIX timestamp)\n */\n iat?: number;\n /**\n * JWT ID\n */\n jti?: string;\n /**\n * Session ID\n */\n sid?: string;\n /**\n * Custom claims\n */\n [key: string]: unknown;\n}\n\nexport interface JWTHeader {\n alg: string; // Allow unknown algs during decode\n typ?: string;\n kid?: string;\n}\n\nexport interface JWT {\n header: JWTHeader;\n payload: JWTPayload;\n signature: string;\n}\n\n// Signature algorithms\nexport const SignatureAlgorithm = {\n // HMAC\n HS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha256', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createHmac('sha256', secret).update(data).digest('base64url') === signature\n },\n HS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha384', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createHmac('sha384', secret).update(data).digest('base64url') === signature\n },\n HS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha512', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createHmac('sha512', secret).update(data).digest('base64url') === signature\n },\n\n // RSA (DER-encoded signatures, base64url)\n RS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('RSA-SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n RS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('RSA-SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n RS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('RSA-SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n\n // ECDSA (DER-encoded by default — no dsaEncoding!)\n ES256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n ES384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n },\n ES512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) =>\n createVerify('SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'))\n }\n} as const;\n\nexport type SupportedAlgorithm = keyof typeof SignatureAlgorithm;\n\nexport const SupportedAlgorithms = Object.keys(SignatureAlgorithm) as Array<SupportedAlgorithm>;\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): JWT => {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT: must contain exactly 3 parts separated by \".\"');\n }\n\n const [headerPart, payloadPart, signature] = parts;\n\n if (!headerPart || !payloadPart || !signature) {\n throw new Error('Invalid JWT: empty part detected');\n }\n\n try {\n const header = JSON.parse(base64Url.decode(headerPart)) as JWTHeader;\n const payload = JSON.parse(base64Url.decode(payloadPart)) as JWTPayload;\n return { header, payload, signature };\n } catch (err) {\n throw new Error(`Invalid JWT: malformed header or payload (${(err as Error).message})`);\n }\n};\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): string => {\n const alg = options.alg ?? 'HS256';\n const typ = options.typ ?? 'JWT';\n\n if (!(alg in SignatureAlgorithm)) {\n throw new Error(`Unsupported algorithm: ${alg}`);\n }\n\n const header: JWTHeader = { alg, typ };\n if (options.kid) header.kid = options.kid;\n\n const headerEncoded = base64Url.encode(JSON.stringify(header));\n const payloadEncoded = base64Url.encode(JSON.stringify(payload));\n\n const signingInput = `${headerEncoded}.${payloadEncoded}`;\n const signature = SignatureAlgorithm[alg].sign(signingInput, secret);\n\n return `${headerEncoded}.${payloadEncoded}.${signature}`;\n};\n\n/**\n * Verify and validate a JWT\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n } = {}\n):\n | { valid: true; header: JWTHeader; payload: JWTPayload; signature: string }\n | { valid: false; error: { reason: string; code: string } } => {\n let decoded: JWT;\n try {\n decoded = decode(token);\n } catch (err) {\n return {\n valid: false,\n error: {\n reason: (err as Error).message,\n code: 'INVALID_TOKEN'\n }\n };\n }\n\n const { header, payload, signature } = decoded;\n\n // Validate algorithm\n const alg = header.alg as SupportedAlgorithm;\n if (!(alg in SignatureAlgorithm)) {\n return {\n valid: false,\n error: {\n reason: `Unsupported or unknown algorithm: ${header.alg}`,\n code: 'INVALID_ALGORITHM'\n }\n };\n }\n\n // Optional: validate 'typ' header\n if (header.typ && header.typ !== 'JWT') {\n return {\n valid: false,\n error: {\n reason: `Invalid token type: expected 'JWT', got '${header.typ}'`,\n code: 'INVALID_TYPE'\n }\n };\n }\n\n // Verify signature\n const signingInput = `${base64Url.encode(JSON.stringify(header))}.${base64Url.encode(JSON.stringify(payload))}`;\n const isValidSignature = SignatureAlgorithm[alg].verify(signingInput, secret, signature);\n\n if (!isValidSignature) {\n return {\n valid: false,\n error: {\n reason: \"Signature verification failed\",\n code: 'INVALID_SIGNATURE'\n }\n };\n }\n\n // Time validation\n const now = Math.floor(Date.now() / 1000);\n const skew = options.clockSkew ?? 0;\n\n if (!options.ignoreExpiration) {\n if (payload.exp !== undefined && now > payload.exp + skew) {\n return {\n valid: false,\n error: {\n reason: 'Token expired',\n code: 'TOKEN_EXPIRED'\n }\n };\n }\n }\n\n if (payload.nbf !== undefined && now + skew < payload.nbf) {\n return {\n valid: false,\n error: {\n reason: 'Token not yet valid',\n code: 'TOKEN_NOT_ACTIVE'\n }\n };\n }\n\n if (payload.iat !== undefined && now + skew < payload.iat) {\n return {\n valid: false,\n error: {\n reason: 'Token issued in the future',\n code: 'TOKEN_FUTURE_ISSUED'\n }\n };\n }\n\n return { valid: true, header, payload, signature };\n};\n\n// Optional: namespace export (not default)\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n};\n"],"names":["base64Url","input","SignatureAlgorithm","data","secret","createHmac","signature","createSign","createVerify","SupportedAlgorithms","decode","token","parts","headerPart","payloadPart","header","payload","err","sign","options","alg","typ","headerEncoded","payloadEncoded","signingInput","verify","decoded","now","skew","JWT"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/index.ts"],"sourcesContent":["import crypto, {\n createHmac,\n createSign,\n createVerify,\n sign as cryptoSign,\n verify as cryptoVerify,\n timingSafeEqual,\n type BinaryLike,\n type KeyLike\n} from 'crypto';\n\n// Base64URL helpers (padding-safe)\nexport const base64Url = {\n encode: (input: string | Buffer): string =>\n Buffer.from(input).toString('base64url'),\n\n decode: (input: string): string => {\n // Node.js Buffer handles unpadded base64url since v16, but we normalize for safety\n return Buffer.from(input, 'base64url').toString();\n }\n};\n\n// Timing-safe string comparison to prevent timing attacks\nconst timingSafeCompare = (a: string, b: string): boolean => {\n if (a.length !== b.length) {\n return false;\n }\n return timingSafeEqual(Buffer.from(a), Buffer.from(b));\n};\n\n// Standard JWT payload claims\nexport interface JWTPayload {\n /**\n * Issuer\n */\n iss?: string;\n /**\n * Subject\n */\n sub?: string;\n /**\n * Audience\n */\n aud?: string | string[];\n /**\n * Expiration Time (as UNIX timestamp)\n */\n exp?: number;\n /**\n * Not Before (as UNIX timestamp)\n */\n nbf?: number;\n /**\n * Issued At (as UNIX timestamp)\n */\n iat?: number;\n /**\n * JWT ID\n */\n jti?: string;\n /**\n * Session ID\n */\n sid?: string;\n\n /**\n * Custom claims\n */\n [key: string]: unknown;\n}\n\nexport interface JWTHeader {\n alg: string; // Allow unknown algs during decode\n typ?: string;\n kid?: string;\n}\n\nexport interface JWT {\n header: JWTHeader;\n payload: JWTPayload;\n signature: string;\n}\n\n// Signature algorithms\nexport const SignatureAlgorithm = {\n // HMAC\n HS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha256', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n const expected = createHmac('sha256', secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n },\n HS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha384', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n const expected = createHmac('sha384', secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n },\n HS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createHmac('sha512', secret).update(data).digest('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n const expected = createHmac('sha512', secret).update(data).digest('base64url');\n return timingSafeCompare(expected, signature);\n }\n },\n\n // RSA (DER-encoded signatures, base64url)\n RS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n RS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n RS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n\n // ECDSA (DER-encoded by default — no dsaEncoding!)\n ES256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n ES384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA384').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA384')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n ES512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA512').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA512')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n ES256K: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('SHA256').update(data).end().sign(secret).toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('SHA256')\n .update(data)\n .end()\n .verify(secret, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n PS256: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA256')\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 32\n })\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA256')\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 32\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n PS384: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA384')\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 48\n })\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA384')\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 48\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n PS512: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n createSign('RSA-SHA512')\n .update(data)\n .end()\n .sign({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 64\n })\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return createVerify('RSA-SHA512')\n .update(data)\n .end()\n .verify({\n //@ts-ignore\n key: secret,\n padding: crypto.constants.RSA_PKCS1_PSS_PADDING,\n saltLength: 64\n }, Buffer.from(signature, 'base64url'));\n } catch {\n return false;\n }\n }\n },\n EdDSA: {\n sign: (data: BinaryLike, secret: KeyLike) =>\n cryptoSign(null, typeof data === 'string' ? Buffer.from(data, 'utf8') : data, secret)\n .toString('base64url'),\n verify: (data: BinaryLike, secret: KeyLike, signature: string) => {\n try {\n return cryptoVerify(\n null,\n typeof data === 'string' ? Buffer.from(data, 'utf8') : data,\n secret,\n Buffer.from(signature, 'base64url')\n );\n } catch {\n return false;\n }\n }\n }\n} as const;\n\nexport type SupportedAlgorithm = keyof typeof SignatureAlgorithm;\n\nexport const SupportedAlgorithms = Object.keys(SignatureAlgorithm) as Array<SupportedAlgorithm>;\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): JWT => {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT: must contain exactly 3 parts separated by \".\"');\n }\n\n const [headerPart, payloadPart, signature] = parts;\n\n if (!headerPart || !payloadPart || !signature) {\n throw new Error('Invalid JWT: empty part detected');\n }\n\n try {\n const header = JSON.parse(base64Url.decode(headerPart)) as JWTHeader;\n const payload = JSON.parse(base64Url.decode(payloadPart)) as JWTPayload;\n return {header, payload, signature};\n } catch (err) {\n throw new Error(`Invalid JWT: malformed header or payload (${(err as Error).message})`);\n }\n};\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): string => {\n const alg = options.alg ?? 'HS256';\n const typ = options.typ ?? 'JWT';\n\n if (!(alg in SignatureAlgorithm)) {\n throw new Error(`Unsupported algorithm: ${alg}`);\n }\n\n const header: JWTHeader = {alg, typ};\n if (options.kid) header.kid = options.kid;\n\n const headerEncoded = base64Url.encode(JSON.stringify(header));\n const payloadEncoded = base64Url.encode(JSON.stringify(payload));\n\n const signingInput = `${headerEncoded}.${payloadEncoded}`;\n const signature = SignatureAlgorithm[alg].sign(signingInput, secret);\n\n return `${headerEncoded}.${payloadEncoded}.${signature}`;\n};\n\n/**\n * Verify and validate a JWT\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n algorithms?: SupportedAlgorithm[]; // Whitelist of allowed algorithms\n issuer?: string;\n subject?: string;\n audience?: string | string[];\n jwtId?: string;\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n maxTokenAge?: number; // Maximum age in seconds\n } = {}\n):\n | { valid: true; header: JWTHeader; payload: JWTPayload; signature: string }\n | { valid: false; error: { reason: string; code: string } } => {\n let decoded: JWT;\n try {\n decoded = decode(token);\n } catch (err) {\n return {\n valid: false,\n error: {\n reason: (err as Error).message,\n code: 'INVALID_TOKEN'\n }\n };\n }\n\n const {header, payload, signature} = decoded;\n\n // Validate algorithm\n const alg = header.alg as SupportedAlgorithm;\n if (!(alg in SignatureAlgorithm)) {\n return {\n valid: false,\n error: {\n reason: `Unsupported or unknown algorithm: ${header.alg}`,\n code: 'INVALID_ALGORITHM'\n }\n };\n }\n\n // Algorithm whitelist validation (prevents algorithm confusion attacks)\n if (options.algorithms && options.algorithms.length > 0) {\n if (!options.algorithms.includes(alg)) {\n return {\n valid: false,\n error: {\n reason: `Algorithm \"${alg}\" is not in the allowed algorithms list`,\n code: 'ALGORITHM_NOT_ALLOWED'\n }\n };\n }\n }\n\n // Validate 'typ' header (must be 'JWT' if present)\n if (header.typ !== undefined && header.typ !== 'JWT') {\n return {\n valid: false,\n error: {\n reason: `Invalid token type: expected 'JWT', got '${header.typ}'`,\n code: 'INVALID_TYPE'\n }\n };\n }\n\n // Verify signature\n const signingInput = `${base64Url.encode(JSON.stringify(header))}.${base64Url.encode(JSON.stringify(payload))}`;\n const isValidSignature = SignatureAlgorithm[alg].verify(signingInput, secret, signature);\n\n if (!isValidSignature) {\n return {\n valid: false,\n error: {\n reason: \"Signature verification failed\",\n code: 'INVALID_SIGNATURE'\n }\n };\n }\n\n // Time validation\n const now = Math.floor(Date.now() / 1000);\n const skew = options.clockSkew ?? 0;\n\n if (!options.ignoreExpiration) {\n if (payload.exp !== undefined && now > payload.exp + skew) {\n return {\n valid: false,\n error: {\n reason: 'Token expired',\n code: 'TOKEN_EXPIRED'\n }\n };\n }\n }\n\n if (payload.nbf !== undefined && now + skew < payload.nbf) {\n return {\n valid: false,\n error: {\n reason: 'Token not yet valid',\n code: 'TOKEN_NOT_ACTIVE'\n }\n };\n }\n\n if (payload.iat !== undefined && now + skew < payload.iat) {\n return {\n valid: false,\n error: {\n reason: 'Token issued in the future',\n code: 'TOKEN_FUTURE_ISSUED'\n }\n };\n }\n\n // Maximum token age validation\n if (options.maxTokenAge !== undefined && payload.iat !== undefined) {\n const tokenAge = now - payload.iat;\n if (tokenAge > options.maxTokenAge) {\n return {\n valid: false,\n error: {\n reason: `Token age (${tokenAge}s) exceeds maximum allowed age (${options.maxTokenAge}s)`,\n code: 'TOKEN_TOO_OLD'\n }\n };\n }\n }\n\n // --- Claim validations (only if options provided) ---\n\n // Issuer (`iss`)\n if (options.issuer !== undefined) {\n if (payload.iss === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required issuer claim (\"iss\")',\n code: 'MISSING_ISSUER'\n }\n };\n }\n if (options.issuer !== payload.iss) {\n return {\n valid: false,\n error: {\n reason: `Invalid token issuer: expected \"${options.issuer}\", got \"${payload.iss}\"`,\n code: 'INVALID_ISSUER'\n }\n };\n }\n }\n\n // Subject (`sub`)\n if (options.subject !== undefined) {\n if (payload.sub === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required subject claim (\"sub\")',\n code: 'MISSING_SUBJECT'\n }\n };\n }\n if (options.subject !== payload.sub) {\n return {\n valid: false,\n error: {\n reason: `Invalid token subject: expected \"${options.subject}\", got \"${payload.sub}\"`,\n code: 'INVALID_SUBJECT'\n }\n };\n }\n }\n\n // Audience (`aud`)\n if (options.audience !== undefined) {\n const aud = payload.aud;\n if (aud === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required audience claim (\"aud\")',\n code: 'MISSING_AUDIENCE'\n }\n };\n }\n\n const expectedAud = Array.isArray(options.audience) ? options.audience : [options.audience];\n const tokenAud = Array.isArray(aud) ? aud : [aud];\n\n const hasMatch = expectedAud.some(a => tokenAud.includes(a));\n if (!hasMatch) {\n return {\n valid: false,\n error: {\n reason: 'Audience claim mismatch',\n code: 'INVALID_AUDIENCE'\n }\n };\n }\n }\n\n // JWT ID (`jti`)\n if (options.jwtId !== undefined) {\n if (payload.jti === undefined) {\n return {\n valid: false,\n error: {\n reason: 'Token missing required JWT ID claim (\"jti\")',\n code: 'MISSING_JTI'\n }\n };\n }\n if (options.jwtId !== payload.jti) {\n return {\n valid: false,\n error: {\n reason: `Invalid JWT ID: expected \"${options.jwtId}\", got \"${payload.jti}\"`,\n code: 'INVALID_JTI'\n }\n };\n }\n }\n\n return {valid: true, header, payload, signature};\n};\n\n// Optional: namespace export\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n};\n"],"names":["base64Url","input","timingSafeCompare","a","b","timingSafeEqual","SignatureAlgorithm","data","secret","createHmac","signature","expected","createSign","createVerify","crypto","cryptoSign","cryptoVerify","SupportedAlgorithms","decode","token","parts","headerPart","payloadPart","header","payload","err","sign","options","alg","typ","headerEncoded","payloadEncoded","signingInput","verify","decoded","now","skew","tokenAge","aud","expectedAud","tokenAud","JWT"],"mappings":"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"}
|
package/dist/promises.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promises.cjs.js","sources":["../src/promises.ts"],"sourcesContent":["import type { KeyLike } from 'crypto';\nimport {\n type JWT as JSONWebToken,\n decode as decodeSync,\n sign as signSync,\n verify as verifySync,\n JWTPayload,\n type SupportedAlgorithm,\n JWTHeader,\n SignatureAlgorithm\n} from './index.js';\n\nexport { type SupportedAlgorithm, SupportedAlgorithms, SignatureAlgorithm, type JWTHeader, type JWTPayload } from './index.js';\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): Promise<JSONWebToken> =>\n Promise.resolve().then(() => decodeSync(token));\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): Promise<string> =>\n Promise.resolve().then(() => signSync(payload, secret, options));\n\n/**\n * Verify and validate a JWT\n *\n * @throws { { reason: string; code: string } } if invalid\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n ignoreExpiration?: boolean;\n clockSkew?: number
|
|
1
|
+
{"version":3,"file":"promises.cjs.js","sources":["../src/promises.ts"],"sourcesContent":["import type { KeyLike } from 'crypto';\nimport {\n type JWT as JSONWebToken,\n decode as decodeSync,\n sign as signSync,\n verify as verifySync,\n JWTPayload,\n type SupportedAlgorithm,\n JWTHeader,\n SignatureAlgorithm\n} from './index.js';\n\nexport { type SupportedAlgorithm, SupportedAlgorithms, SignatureAlgorithm, type JWTHeader, type JWTPayload } from './index.js';\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): Promise<JSONWebToken> =>\n Promise.resolve().then(() => decodeSync(token));\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): Promise<string> =>\n Promise.resolve().then(() => signSync(payload, secret, options));\n\n/**\n * Verify and validate a JWT\n *\n * @throws { { reason: string; code: string } } if invalid\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n algorithms?: SupportedAlgorithm[]; // Whitelist of allowed algorithms\n issuer?: string;\n subject?: string;\n audience?: string | string[];\n jwtId?: string;\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n maxTokenAge?: number; // Maximum age in seconds\n } = {}\n): Promise<{ header: JWTHeader; payload: JWTPayload; signature: string }> =>\n Promise.resolve().then(() => {\n const result = verifySync(token, secret, options);\n if (!result.valid) {\n throw result.error;\n }\n const { header, payload, signature } = result;\n return { header, payload, signature };\n });\n\nexport type JWT = JSONWebToken;\n\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n};\n"],"names":["decode","token","decodeSync","sign","payload","secret","options","signSync","verify","result","verifySync","header","signature","JWT","SignatureAlgorithm"],"mappings":"kHAiBaA,EAAUC,GACnB,QAAQ,QAAA,EAAU,KAAK,IAAMC,EAAAA,OAAWD,CAAK,CAAC,EAKrCE,EAAO,CAChBC,EACAC,EACAC,EAII,CAAA,IAEJ,QAAQ,QAAA,EAAU,KAAK,IAAMC,EAAAA,KAASH,EAASC,EAAQC,CAAO,CAAC,EAOtDE,EAAS,CAClBP,EACAI,EACAC,EASI,CAAA,IAEJ,QAAQ,UAAU,KAAK,IAAM,CACzB,MAAMG,EAASC,EAAAA,OAAWT,EAAOI,EAAQC,CAAO,EAChD,GAAI,CAACG,EAAO,MACR,MAAMA,EAAO,MAEjB,KAAM,CAAE,OAAAE,EAAQ,QAAAP,EAAS,UAAAQ,CAAA,EAAcH,EACvC,MAAO,CAAE,OAAAE,EAAQ,QAAAP,EAAS,UAAAQ,CAAA,CAC9B,CAAC,EAIQC,EAAM,CACf,KAAAV,EACA,OAAAK,EACA,OAAAR,EACA,WAAYc,EAAAA,kBAChB"}
|
package/dist/promises.d.ts
CHANGED
|
@@ -19,8 +19,14 @@ export declare const sign: (payload: JWTPayload, secret: KeyLike, options?: {
|
|
|
19
19
|
* @throws { { reason: string; code: string } } if invalid
|
|
20
20
|
*/
|
|
21
21
|
export declare const verify: (token: string, secret: KeyLike, options?: {
|
|
22
|
+
algorithms?: SupportedAlgorithm[];
|
|
23
|
+
issuer?: string;
|
|
24
|
+
subject?: string;
|
|
25
|
+
audience?: string | string[];
|
|
26
|
+
jwtId?: string;
|
|
22
27
|
ignoreExpiration?: boolean;
|
|
23
28
|
clockSkew?: number;
|
|
29
|
+
maxTokenAge?: number;
|
|
24
30
|
}) => Promise<{
|
|
25
31
|
header: JWTHeader;
|
|
26
32
|
payload: JWTPayload;
|
|
@@ -34,8 +40,14 @@ export declare const JWT: {
|
|
|
34
40
|
typ?: string;
|
|
35
41
|
}) => Promise<string>;
|
|
36
42
|
verify: (token: string, secret: KeyLike, options?: {
|
|
43
|
+
algorithms?: SupportedAlgorithm[];
|
|
44
|
+
issuer?: string;
|
|
45
|
+
subject?: string;
|
|
46
|
+
audience?: string | string[];
|
|
47
|
+
jwtId?: string;
|
|
37
48
|
ignoreExpiration?: boolean;
|
|
38
49
|
clockSkew?: number;
|
|
50
|
+
maxTokenAge?: number;
|
|
39
51
|
}) => Promise<{
|
|
40
52
|
header: JWTHeader;
|
|
41
53
|
payload: JWTPayload;
|
|
@@ -79,5 +91,25 @@ export declare const JWT: {
|
|
|
79
91
|
readonly sign: (data: import('crypto').BinaryLike, secret: KeyLike) => string;
|
|
80
92
|
readonly verify: (data: import('crypto').BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
81
93
|
};
|
|
94
|
+
readonly ES256K: {
|
|
95
|
+
readonly sign: (data: import('crypto').BinaryLike, secret: KeyLike) => string;
|
|
96
|
+
readonly verify: (data: import('crypto').BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
97
|
+
};
|
|
98
|
+
readonly PS256: {
|
|
99
|
+
readonly sign: (data: import('crypto').BinaryLike, secret: KeyLike) => string;
|
|
100
|
+
readonly verify: (data: import('crypto').BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
101
|
+
};
|
|
102
|
+
readonly PS384: {
|
|
103
|
+
readonly sign: (data: import('crypto').BinaryLike, secret: KeyLike) => string;
|
|
104
|
+
readonly verify: (data: import('crypto').BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
105
|
+
};
|
|
106
|
+
readonly PS512: {
|
|
107
|
+
readonly sign: (data: import('crypto').BinaryLike, secret: KeyLike) => string;
|
|
108
|
+
readonly verify: (data: import('crypto').BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
109
|
+
};
|
|
110
|
+
readonly EdDSA: {
|
|
111
|
+
readonly sign: (data: import('crypto').BinaryLike, secret: KeyLike) => string;
|
|
112
|
+
readonly verify: (data: import('crypto').BinaryLike, secret: KeyLike, signature: string) => boolean;
|
|
113
|
+
};
|
|
82
114
|
};
|
|
83
115
|
};
|
package/dist/promises.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promises.es.js","sources":["../src/promises.ts"],"sourcesContent":["import type { KeyLike } from 'crypto';\nimport {\n type JWT as JSONWebToken,\n decode as decodeSync,\n sign as signSync,\n verify as verifySync,\n JWTPayload,\n type SupportedAlgorithm,\n JWTHeader,\n SignatureAlgorithm\n} from './index.js';\n\nexport { type SupportedAlgorithm, SupportedAlgorithms, SignatureAlgorithm, type JWTHeader, type JWTPayload } from './index.js';\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): Promise<JSONWebToken> =>\n Promise.resolve().then(() => decodeSync(token));\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): Promise<string> =>\n Promise.resolve().then(() => signSync(payload, secret, options));\n\n/**\n * Verify and validate a JWT\n *\n * @throws { { reason: string; code: string } } if invalid\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n ignoreExpiration?: boolean;\n clockSkew?: number
|
|
1
|
+
{"version":3,"file":"promises.es.js","sources":["../src/promises.ts"],"sourcesContent":["import type { KeyLike } from 'crypto';\nimport {\n type JWT as JSONWebToken,\n decode as decodeSync,\n sign as signSync,\n verify as verifySync,\n JWTPayload,\n type SupportedAlgorithm,\n JWTHeader,\n SignatureAlgorithm\n} from './index.js';\n\nexport { type SupportedAlgorithm, SupportedAlgorithms, SignatureAlgorithm, type JWTHeader, type JWTPayload } from './index.js';\n\n/**\n * Decode a JWT string into its parts (without verification)\n */\nexport const decode = (token: string): Promise<JSONWebToken> =>\n Promise.resolve().then(() => decodeSync(token));\n\n/**\n * Sign a JWT\n */\nexport const sign = (\n payload: JWTPayload,\n secret: KeyLike,\n options: {\n alg?: SupportedAlgorithm;\n kid?: string;\n typ?: string;\n } = {}\n): Promise<string> =>\n Promise.resolve().then(() => signSync(payload, secret, options));\n\n/**\n * Verify and validate a JWT\n *\n * @throws { { reason: string; code: string } } if invalid\n */\nexport const verify = (\n token: string,\n secret: KeyLike,\n options: {\n algorithms?: SupportedAlgorithm[]; // Whitelist of allowed algorithms\n issuer?: string;\n subject?: string;\n audience?: string | string[];\n jwtId?: string;\n ignoreExpiration?: boolean;\n clockSkew?: number; // in seconds, default 0\n maxTokenAge?: number; // Maximum age in seconds\n } = {}\n): Promise<{ header: JWTHeader; payload: JWTPayload; signature: string }> =>\n Promise.resolve().then(() => {\n const result = verifySync(token, secret, options);\n if (!result.valid) {\n throw result.error;\n }\n const { header, payload, signature } = result;\n return { header, payload, signature };\n });\n\nexport type JWT = JSONWebToken;\n\nexport const JWT = {\n sign,\n verify,\n decode,\n algorithms: SignatureAlgorithm\n};\n"],"names":["decode","token","decodeSync","sign","payload","secret","options","signSync","verify","result","verifySync","header","signature","JWT","SignatureAlgorithm"],"mappings":";;AAiBO,MAAMA,IAAS,CAACC,MACnB,QAAQ,QAAA,EAAU,KAAK,MAAMC,EAAWD,CAAK,CAAC,GAKrCE,IAAO,CAChBC,GACAC,GACAC,IAII,CAAA,MAEJ,QAAQ,QAAA,EAAU,KAAK,MAAMC,EAASH,GAASC,GAAQC,CAAO,CAAC,GAOtDE,IAAS,CAClBP,GACAI,GACAC,IASI,CAAA,MAEJ,QAAQ,UAAU,KAAK,MAAM;AACzB,QAAMG,IAASC,EAAWT,GAAOI,GAAQC,CAAO;AAChD,MAAI,CAACG,EAAO;AACR,UAAMA,EAAO;AAEjB,QAAM,EAAE,QAAAE,GAAQ,SAAAP,GAAS,WAAAQ,EAAA,IAAcH;AACvC,SAAO,EAAE,QAAAE,GAAQ,SAAAP,GAAS,WAAAQ,EAAA;AAC9B,CAAC,GAIQC,IAAM;AAAA,EACf,MAAAV;AAAA,EACA,QAAAK;AAAA,EACA,QAAAR;AAAA,EACA,YAAYc;AAChB;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sourceregistry/node-jwt",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A lightweight, zero-dependency TypeScript library for creating, verifying and decoding JSON Web Tokens (JWT).",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"test": "vitest",
|
|
26
26
|
"test:ui": "vitest --ui",
|
|
27
27
|
"test:coverage": "vitest run --coverage",
|
|
28
|
-
"lint": "tsc --noEmit"
|
|
28
|
+
"lint": "tsc --noEmit",
|
|
29
|
+
"docs:build": "typedoc src/index.ts --out docs --name \"node-jwt\" --theme default --excludePrivate --excludeProtected"
|
|
29
30
|
},
|
|
30
31
|
"repository": {
|
|
31
32
|
"type": "git",
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
"bugs": {
|
|
46
47
|
"url": "https://github.com/SourceRegistry/node-jwt/issues"
|
|
47
48
|
},
|
|
48
|
-
"homepage": "https://github.
|
|
49
|
+
"homepage": "https://sourceregistry.github.io/node-jwt",
|
|
49
50
|
"publishConfig": {
|
|
50
51
|
"access": "public"
|
|
51
52
|
},
|
|
@@ -53,18 +54,19 @@
|
|
|
53
54
|
"node": ">=16.0.0"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
57
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
58
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
59
|
+
"@semantic-release/git": "^10.0.1",
|
|
60
|
+
"@semantic-release/npm": "^12.0.2",
|
|
61
|
+
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
56
62
|
"@types/node": "^24.3.0",
|
|
57
63
|
"@vitest/coverage-v8": "^3.2.4",
|
|
58
64
|
"@vitest/ui": "^3.2.4",
|
|
65
|
+
"typedoc": "^0.28.14",
|
|
59
66
|
"typescript": "^5.9.3",
|
|
60
|
-
"vite": "^7.1.
|
|
67
|
+
"vite": "^7.1.12",
|
|
61
68
|
"vite-plugin-dts": "^4.5.4",
|
|
62
|
-
"vitest": "^3.2.4"
|
|
63
|
-
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
64
|
-
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
65
|
-
"@semantic-release/changelog": "^6.0.3",
|
|
66
|
-
"@semantic-release/npm": "^12.0.2",
|
|
67
|
-
"@semantic-release/git": "^10.0.1"
|
|
69
|
+
"vitest": "^3.2.4"
|
|
68
70
|
},
|
|
69
71
|
"release": {
|
|
70
72
|
"branches": [
|