@ooneex/jwt 0.0.1 → 0.0.5

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 CHANGED
@@ -1 +1,506 @@
1
1
  # @ooneex/jwt
2
+
3
+ A JWT (JSON Web Token) generation and validation library for TypeScript applications using the JOSE library. This package provides secure token creation, verification, and payload extraction with full TypeScript support and expiration time helpers.
4
+
5
+ ![Bun](https://img.shields.io/badge/Bun-Compatible-orange?style=flat-square&logo=bun)
6
+ ![Deno](https://img.shields.io/badge/Deno-Compatible-blue?style=flat-square&logo=deno)
7
+ ![Node.js](https://img.shields.io/badge/Node.js-Compatible-green?style=flat-square&logo=node.js)
8
+ ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue?style=flat-square&logo=typescript)
9
+ ![MIT License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)
10
+
11
+ ## Features
12
+
13
+ ✅ **JOSE Powered** - Built on the robust JOSE library for secure JWT operations
14
+
15
+ ✅ **Token Generation** - Create signed JWT tokens with custom payloads and headers
16
+
17
+ ✅ **Token Validation** - Verify token signatures and expiration
18
+
19
+ ✅ **Payload Extraction** - Decode and retrieve payload data from tokens
20
+
21
+ ✅ **Flexible Expiration** - Support for various expiration formats (seconds, minutes, hours, days)
22
+
23
+ ✅ **Type-Safe** - Full TypeScript support with generic payload types
24
+
25
+ ✅ **Environment Config** - Automatic secret loading from environment variables
26
+
27
+ ## Installation
28
+
29
+ ### Bun
30
+ ```bash
31
+ bun add @ooneex/jwt
32
+ ```
33
+
34
+ ### pnpm
35
+ ```bash
36
+ pnpm add @ooneex/jwt
37
+ ```
38
+
39
+ ### Yarn
40
+ ```bash
41
+ yarn add @ooneex/jwt
42
+ ```
43
+
44
+ ### npm
45
+ ```bash
46
+ npm install @ooneex/jwt
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Basic Token Generation
52
+
53
+ ```typescript
54
+ import { Jwt } from '@ooneex/jwt';
55
+
56
+ const jwt = new Jwt('your-secret-key');
57
+
58
+ // Create a simple token
59
+ const token = await jwt.create({
60
+ payload: {
61
+ sub: 'user-123',
62
+ exp: '1h' // Expires in 1 hour
63
+ }
64
+ });
65
+
66
+ console.log(token);
67
+ ```
68
+
69
+ ### Token with Custom Payload
70
+
71
+ ```typescript
72
+ import { Jwt } from '@ooneex/jwt';
73
+
74
+ const jwt = new Jwt();
75
+
76
+ interface UserPayload {
77
+ userId: string;
78
+ role: string;
79
+ permissions: string[];
80
+ }
81
+
82
+ const token = await jwt.create<UserPayload>({
83
+ payload: {
84
+ sub: 'user-123',
85
+ iss: 'my-app',
86
+ aud: 'my-api',
87
+ exp: '24h',
88
+ iat: new Date(),
89
+ userId: 'usr_abc123',
90
+ role: 'admin',
91
+ permissions: ['read', 'write', 'delete']
92
+ }
93
+ });
94
+ ```
95
+
96
+ ### Token Validation
97
+
98
+ ```typescript
99
+ import { Jwt } from '@ooneex/jwt';
100
+
101
+ const jwt = new Jwt();
102
+
103
+ const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
104
+
105
+ // Check if token is valid
106
+ const isValid = await jwt.isValid(token);
107
+
108
+ if (isValid) {
109
+ console.log('Token is valid');
110
+ } else {
111
+ console.log('Token is invalid or expired');
112
+ }
113
+ ```
114
+
115
+ ### Extracting Payload
116
+
117
+ ```typescript
118
+ import { Jwt } from '@ooneex/jwt';
119
+
120
+ const jwt = new Jwt();
121
+
122
+ interface UserPayload {
123
+ userId: string;
124
+ role: string;
125
+ }
126
+
127
+ const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
128
+
129
+ // Get payload without verification (decodes only)
130
+ const payload = jwt.getPayload<UserPayload>(token);
131
+
132
+ console.log(payload.userId); // "usr_abc123"
133
+ console.log(payload.role); // "admin"
134
+ console.log(payload.exp); // Expiration timestamp
135
+ ```
136
+
137
+ ### Extracting Header
138
+
139
+ ```typescript
140
+ import { Jwt } from '@ooneex/jwt';
141
+
142
+ const jwt = new Jwt();
143
+
144
+ const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
145
+
146
+ const header = jwt.getHeader(token);
147
+
148
+ console.log(header.alg); // "HS256"
149
+ console.log(header.typ); // "JWT"
150
+ ```
151
+
152
+ ### Using Environment Variables
153
+
154
+ ```typescript
155
+ import { Jwt } from '@ooneex/jwt';
156
+
157
+ // Automatically uses JWT_SECRET environment variable
158
+ const jwt = new Jwt();
159
+
160
+ const token = await jwt.create({
161
+ payload: {
162
+ sub: 'user-123',
163
+ exp: '1h'
164
+ }
165
+ });
166
+ ```
167
+
168
+ **Environment Variables:**
169
+ - `JWT_SECRET` - The secret key used for signing and verifying tokens
170
+
171
+ ## API Reference
172
+
173
+ ### Classes
174
+
175
+ #### `Jwt`
176
+
177
+ Main class for JWT operations.
178
+
179
+ **Constructor:**
180
+ ```typescript
181
+ new Jwt(secret?: string)
182
+ ```
183
+
184
+ **Parameters:**
185
+ - `secret` - Optional secret key. If not provided, uses `JWT_SECRET` environment variable
186
+
187
+ **Throws:** `JwtException` if no secret is provided or found in environment
188
+
189
+ **Methods:**
190
+
191
+ ##### `create<T>(config?: CreateConfig): Promise<string>`
192
+
193
+ Creates a new signed JWT token.
194
+
195
+ **Parameters:**
196
+ - `config.payload` - The JWT payload including standard and custom claims
197
+ - `config.header` - Optional custom header parameters
198
+
199
+ **Returns:** Promise resolving to the signed token string
200
+
201
+ **Example:**
202
+ ```typescript
203
+ const token = await jwt.create({
204
+ payload: {
205
+ sub: 'user-123',
206
+ iss: 'my-app',
207
+ exp: '2h',
208
+ customClaim: 'value'
209
+ },
210
+ header: {
211
+ kid: 'key-id-123'
212
+ }
213
+ });
214
+ ```
215
+
216
+ ##### `isValid(token: string): Promise<boolean>`
217
+
218
+ Verifies if a token is valid (signature and expiration).
219
+
220
+ **Parameters:**
221
+ - `token` - The JWT token to verify
222
+
223
+ **Returns:** Promise resolving to `true` if valid, `false` otherwise
224
+
225
+ **Example:**
226
+ ```typescript
227
+ const isValid = await jwt.isValid(token);
228
+ ```
229
+
230
+ ##### `getPayload<T>(token: string): JwtPayloadType<T>`
231
+
232
+ Decodes and returns the token payload (without verification).
233
+
234
+ **Parameters:**
235
+ - `token` - The JWT token to decode
236
+
237
+ **Returns:** The decoded payload
238
+
239
+ **Example:**
240
+ ```typescript
241
+ interface MyPayload {
242
+ userId: string;
243
+ }
244
+
245
+ const payload = jwt.getPayload<MyPayload>(token);
246
+ console.log(payload.userId);
247
+ ```
248
+
249
+ ##### `getHeader(token: string): JWTHeaderParameters`
250
+
251
+ Decodes and returns the token header.
252
+
253
+ **Parameters:**
254
+ - `token` - The JWT token to decode
255
+
256
+ **Returns:** The decoded header
257
+
258
+ ##### `getSecret(): Uint8Array<ArrayBuffer>`
259
+
260
+ Returns the encoded secret used for signing.
261
+
262
+ **Returns:** The secret as a Uint8Array
263
+
264
+ ### Types
265
+
266
+ #### `JwtExpiresInType`
267
+
268
+ Expiration time format strings.
269
+
270
+ ```typescript
271
+ type JwtExpiresInType =
272
+ | `${number}s` // seconds
273
+ | `${number}m` // minutes
274
+ | `${number}h` // hours
275
+ | `${number}d` // days
276
+ | `${number}w` // weeks
277
+ | `${number}y`; // years
278
+ ```
279
+
280
+ **Examples:**
281
+ - `'30s'` - 30 seconds
282
+ - `'15m'` - 15 minutes
283
+ - `'2h'` - 2 hours
284
+ - `'7d'` - 7 days
285
+ - `'1w'` - 1 week
286
+ - `'1y'` - 1 year
287
+
288
+ #### `JwtDefaultPayloadType`
289
+
290
+ Standard JWT claims.
291
+
292
+ ```typescript
293
+ type JwtDefaultPayloadType = {
294
+ iss?: string; // Issuer
295
+ sub?: string; // Subject
296
+ aud?: string | string[]; // Audience
297
+ jti?: string; // JWT ID
298
+ nbf?: number | string | Date; // Not Before
299
+ exp?: number | JwtExpiresInType | Date; // Expiration
300
+ iat?: number | string | Date; // Issued At
301
+ };
302
+ ```
303
+
304
+ #### `JwtPayloadType<T>`
305
+
306
+ Combined payload type with custom claims.
307
+
308
+ ```typescript
309
+ type JwtPayloadType<T> = JwtDefaultPayloadType & T;
310
+ ```
311
+
312
+ #### `IJwt`
313
+
314
+ Interface for JWT implementations.
315
+
316
+ ```typescript
317
+ interface IJwt {
318
+ create: <T extends Record<string, unknown>>(config?: {
319
+ payload?: JwtDefaultPayloadType & JwtPayloadType<T>;
320
+ header?: JWTHeaderParameters;
321
+ }) => Promise<string>;
322
+ getPayload: <T extends Record<string, unknown>>(token: string) => JwtPayloadType<T>;
323
+ getHeader: (token: string) => JWTHeaderParameters;
324
+ isValid: (token: string) => Promise<boolean> | boolean;
325
+ getSecret: () => Uint8Array<ArrayBuffer>;
326
+ }
327
+ ```
328
+
329
+ ## Advanced Usage
330
+
331
+ ### Authentication Flow
332
+
333
+ ```typescript
334
+ import { Jwt, JwtException } from '@ooneex/jwt';
335
+
336
+ const jwt = new Jwt();
337
+
338
+ // Login - Generate tokens
339
+ async function login(userId: string, role: string) {
340
+ const accessToken = await jwt.create({
341
+ payload: {
342
+ sub: userId,
343
+ role,
344
+ exp: '15m' // Short-lived access token
345
+ }
346
+ });
347
+
348
+ const refreshToken = await jwt.create({
349
+ payload: {
350
+ sub: userId,
351
+ type: 'refresh',
352
+ exp: '7d' // Long-lived refresh token
353
+ }
354
+ });
355
+
356
+ return { accessToken, refreshToken };
357
+ }
358
+
359
+ // Verify and extract user from token
360
+ async function authenticateRequest(token: string) {
361
+ const isValid = await jwt.isValid(token);
362
+
363
+ if (!isValid) {
364
+ throw new Error('Invalid or expired token');
365
+ }
366
+
367
+ const payload = jwt.getPayload<{ role: string }>(token);
368
+
369
+ return {
370
+ userId: payload.sub,
371
+ role: payload.role
372
+ };
373
+ }
374
+ ```
375
+
376
+ ### Refresh Token Implementation
377
+
378
+ ```typescript
379
+ import { Jwt } from '@ooneex/jwt';
380
+
381
+ const jwt = new Jwt();
382
+
383
+ async function refreshAccessToken(refreshToken: string) {
384
+ const isValid = await jwt.isValid(refreshToken);
385
+
386
+ if (!isValid) {
387
+ throw new Error('Invalid refresh token');
388
+ }
389
+
390
+ const payload = jwt.getPayload<{ type: string }>(refreshToken);
391
+
392
+ if (payload.type !== 'refresh') {
393
+ throw new Error('Not a refresh token');
394
+ }
395
+
396
+ // Generate new access token
397
+ const newAccessToken = await jwt.create({
398
+ payload: {
399
+ sub: payload.sub,
400
+ exp: '15m'
401
+ }
402
+ });
403
+
404
+ return newAccessToken;
405
+ }
406
+ ```
407
+
408
+ ### Error Handling
409
+
410
+ ```typescript
411
+ import { Jwt, JwtException } from '@ooneex/jwt';
412
+
413
+ try {
414
+ const jwt = new Jwt(); // Will throw if JWT_SECRET is not set
415
+
416
+ const token = await jwt.create({
417
+ payload: { sub: 'user-123' }
418
+ });
419
+ } catch (error) {
420
+ if (error instanceof JwtException) {
421
+ console.error('JWT Error:', error.message);
422
+ console.error('Status:', error.status);
423
+ }
424
+ }
425
+ ```
426
+
427
+ ### Middleware Integration
428
+
429
+ ```typescript
430
+ import { Jwt } from '@ooneex/jwt';
431
+ import type { IMiddleware, ContextType } from '@ooneex/middleware';
432
+
433
+ class AuthMiddleware implements IMiddleware {
434
+ private readonly jwt = new Jwt();
435
+
436
+ public async handle(context: ContextType): Promise<ContextType> {
437
+ const authHeader = context.header.get('Authorization');
438
+
439
+ if (!authHeader?.startsWith('Bearer ')) {
440
+ return context.response.exception('Missing authorization header', {
441
+ status: 401
442
+ });
443
+ }
444
+
445
+ const token = authHeader.substring(7);
446
+ const isValid = await this.jwt.isValid(token);
447
+
448
+ if (!isValid) {
449
+ return context.response.exception('Invalid or expired token', {
450
+ status: 401
451
+ });
452
+ }
453
+
454
+ const payload = this.jwt.getPayload<{ role: string }>(token);
455
+ context.user = { id: payload.sub, role: payload.role };
456
+
457
+ return context;
458
+ }
459
+ }
460
+ ```
461
+
462
+ ### Custom Header Parameters
463
+
464
+ ```typescript
465
+ import { Jwt } from '@ooneex/jwt';
466
+
467
+ const jwt = new Jwt();
468
+
469
+ const token = await jwt.create({
470
+ payload: {
471
+ sub: 'user-123',
472
+ exp: '1h'
473
+ },
474
+ header: {
475
+ kid: 'my-key-id', // Key ID
476
+ typ: 'JWT', // Type
477
+ cty: 'application/json' // Content Type
478
+ }
479
+ });
480
+ ```
481
+
482
+ ## License
483
+
484
+ This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
485
+
486
+ ## Contributing
487
+
488
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
489
+
490
+ ### Development Setup
491
+
492
+ 1. Clone the repository
493
+ 2. Install dependencies: `bun install`
494
+ 3. Run tests: `bun run test`
495
+ 4. Build the project: `bun run build`
496
+
497
+ ### Guidelines
498
+
499
+ - Write tests for new features
500
+ - Follow the existing code style
501
+ - Update documentation for API changes
502
+ - Ensure all tests pass before submitting PR
503
+
504
+ ---
505
+
506
+ Made with ❤️ by the Ooneex team
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ooneex/jwt",
3
- "description": "",
4
- "version": "0.0.1",
3
+ "description": "JWT token generation and validation using the JOSE library for secure authentication",
4
+ "version": "0.0.5",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -24,9 +24,8 @@
24
24
  "scripts": {
25
25
  "build": "bunup",
26
26
  "lint": "tsgo --noEmit && bunx biome lint",
27
- "publish:prod": "bun publish --tolerate-republish --access public",
28
- "publish:pack": "bun pm pack --destination ./dist",
29
- "publish:dry": "bun publish --dry-run"
27
+ "npm:publish": "bun publish --tolerate-republish --access public",
28
+ "test": "bun test tests"
30
29
  },
31
30
  "dependencies": {
32
31
  "@ooneex/exception": "0.0.1",
@@ -34,5 +33,14 @@
34
33
  "jose": "^6.1.2"
35
34
  },
36
35
  "devDependencies": {},
37
- "peerDependencies": {}
36
+ "keywords": [
37
+ "authentication",
38
+ "bun",
39
+ "jose",
40
+ "json-web-token",
41
+ "jwt",
42
+ "ooneex",
43
+ "token",
44
+ "typescript"
45
+ ]
38
46
  }
Binary file