@hazeljs/auth 0.2.0-beta.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 ADDED
@@ -0,0 +1,483 @@
1
+ # @hazeljs/auth
2
+
3
+ **Authentication and JWT Module for HazelJS**
4
+
5
+ Secure your HazelJS applications with JWT-based authentication, guards, and decorators.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@hazeljs/auth.svg)](https://www.npmjs.com/package/@hazeljs/auth)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ## Features
11
+
12
+ - 🔐 **JWT Authentication** - Secure token-based authentication
13
+ - 🛡️ **Auth Guards** - Protect routes with decorators
14
+ - 👤 **User Extraction** - Get current user from request
15
+ - 🔑 **Token Management** - Generate, verify, and refresh tokens
16
+ - ⏰ **Token Expiration** - Configurable expiration times
17
+ - 🎯 **Role-Based Access** - Role and permission guards
18
+ - 🔄 **Refresh Tokens** - Long-lived refresh token support
19
+ - 📊 **Token Blacklisting** - Revoke tokens when needed
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @hazeljs/auth
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Configure Auth Module
30
+
31
+ ```typescript
32
+ import { HazelModule } from '@hazeljs/core';
33
+ import { AuthModule } from '@hazeljs/auth';
34
+
35
+ @HazelModule({
36
+ imports: [
37
+ AuthModule.forRoot({
38
+ secret: process.env.JWT_SECRET || 'your-secret-key',
39
+ expiresIn: '1h',
40
+ refreshExpiresIn: '7d',
41
+ }),
42
+ ],
43
+ })
44
+ export class AppModule {}
45
+ ```
46
+
47
+ ### 2. Create Auth Service
48
+
49
+ ```typescript
50
+ import { Injectable } from '@hazeljs/core';
51
+ import { AuthService } from '@hazeljs/auth';
52
+
53
+ @Injectable()
54
+ export class UserAuthService {
55
+ constructor(private authService: AuthService) {}
56
+
57
+ async login(email: string, password: string) {
58
+ // Validate credentials
59
+ const user = await this.validateUser(email, password);
60
+
61
+ if (!user) {
62
+ throw new Error('Invalid credentials');
63
+ }
64
+
65
+ // Generate tokens
66
+ const accessToken = await this.authService.generateToken({
67
+ sub: user.id,
68
+ email: user.email,
69
+ roles: user.roles,
70
+ });
71
+
72
+ const refreshToken = await this.authService.generateRefreshToken({
73
+ sub: user.id,
74
+ });
75
+
76
+ return {
77
+ accessToken,
78
+ refreshToken,
79
+ user,
80
+ };
81
+ }
82
+
83
+ async validateUser(email: string, password: string) {
84
+ // Your user validation logic
85
+ const user = await this.userService.findByEmail(email);
86
+
87
+ if (user && await this.comparePasswords(password, user.password)) {
88
+ return user;
89
+ }
90
+
91
+ return null;
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### 3. Protect Routes with Guards
97
+
98
+ ```typescript
99
+ import { Controller, Get, Post, Body } from '@hazeljs/core';
100
+ import { UseGuard, AuthGuard, CurrentUser } from '@hazeljs/auth';
101
+
102
+ @Controller('/api')
103
+ export class ApiController {
104
+ @Post('/login')
105
+ async login(@Body() credentials: LoginDto) {
106
+ return this.authService.login(credentials.email, credentials.password);
107
+ }
108
+
109
+ @Get('/profile')
110
+ @UseGuard(AuthGuard)
111
+ getProfile(@CurrentUser() user: any) {
112
+ return { user };
113
+ }
114
+
115
+ @Get('/admin')
116
+ @UseGuard(AuthGuard)
117
+ @UseGuard(RoleGuard(['admin']))
118
+ getAdminData(@CurrentUser() user: any) {
119
+ return { message: 'Admin only data', user };
120
+ }
121
+ }
122
+ ```
123
+
124
+ ## Authentication Flow
125
+
126
+ ### Login
127
+
128
+ ```typescript
129
+ @Post('/auth/login')
130
+ async login(@Body() loginDto: LoginDto) {
131
+ const user = await this.authService.validateUser(
132
+ loginDto.email,
133
+ loginDto.password
134
+ );
135
+
136
+ if (!user) {
137
+ throw new UnauthorizedException('Invalid credentials');
138
+ }
139
+
140
+ const payload = {
141
+ sub: user.id,
142
+ email: user.email,
143
+ roles: user.roles,
144
+ };
145
+
146
+ return {
147
+ accessToken: await this.authService.generateToken(payload),
148
+ refreshToken: await this.authService.generateRefreshToken(payload),
149
+ };
150
+ }
151
+ ```
152
+
153
+ ### Refresh Token
154
+
155
+ ```typescript
156
+ @Post('/auth/refresh')
157
+ async refresh(@Body() refreshDto: RefreshDto) {
158
+ const payload = await this.authService.verifyRefreshToken(
159
+ refreshDto.refreshToken
160
+ );
161
+
162
+ return {
163
+ accessToken: await this.authService.generateToken({
164
+ sub: payload.sub,
165
+ email: payload.email,
166
+ roles: payload.roles,
167
+ }),
168
+ };
169
+ }
170
+ ```
171
+
172
+ ### Logout
173
+
174
+ ```typescript
175
+ @Post('/auth/logout')
176
+ @UseGuard(AuthGuard)
177
+ async logout(@CurrentUser() user: any, @Headers('authorization') token: string) {
178
+ // Extract token from "Bearer <token>"
179
+ const jwt = token.split(' ')[1];
180
+
181
+ // Blacklist the token
182
+ await this.authService.blacklistToken(jwt);
183
+
184
+ return { message: 'Logged out successfully' };
185
+ }
186
+ ```
187
+
188
+ ## Guards
189
+
190
+ ### Auth Guard
191
+
192
+ ```typescript
193
+ import { AuthGuard } from '@hazeljs/auth';
194
+
195
+ @Controller('/protected')
196
+ export class ProtectedController {
197
+ @Get()
198
+ @UseGuard(AuthGuard)
199
+ getData(@CurrentUser() user: any) {
200
+ return { data: 'protected', user };
201
+ }
202
+ }
203
+ ```
204
+
205
+ ### Role Guard
206
+
207
+ ```typescript
208
+ import { RoleGuard } from '@hazeljs/auth';
209
+
210
+ @Controller('/admin')
211
+ export class AdminController {
212
+ @Get('/users')
213
+ @UseGuard(AuthGuard)
214
+ @UseGuard(RoleGuard(['admin']))
215
+ getAllUsers() {
216
+ return { users: [] };
217
+ }
218
+
219
+ @Get('/settings')
220
+ @UseGuard(AuthGuard)
221
+ @UseGuard(RoleGuard(['admin', 'superadmin']))
222
+ getSettings() {
223
+ return { settings: {} };
224
+ }
225
+ }
226
+ ```
227
+
228
+ ### Permission Guard
229
+
230
+ ```typescript
231
+ import { PermissionGuard } from '@hazeljs/auth';
232
+
233
+ @Controller('/posts')
234
+ export class PostController {
235
+ @Post()
236
+ @UseGuard(AuthGuard)
237
+ @UseGuard(PermissionGuard(['posts:create']))
238
+ createPost(@Body() createPostDto: CreatePostDto) {
239
+ return this.postService.create(createPostDto);
240
+ }
241
+
242
+ @Delete('/:id')
243
+ @UseGuard(AuthGuard)
244
+ @UseGuard(PermissionGuard(['posts:delete']))
245
+ deletePost(@Param('id') id: string) {
246
+ return this.postService.delete(id);
247
+ }
248
+ }
249
+ ```
250
+
251
+ ## Decorators
252
+
253
+ ### @CurrentUser()
254
+
255
+ Extract the authenticated user from the request:
256
+
257
+ ```typescript
258
+ @Get('/me')
259
+ @UseGuard(AuthGuard)
260
+ getMe(@CurrentUser() user: any) {
261
+ return user;
262
+ }
263
+
264
+ // With specific property
265
+ @Get('/email')
266
+ @UseGuard(AuthGuard)
267
+ getEmail(@CurrentUser('email') email: string) {
268
+ return { email };
269
+ }
270
+ ```
271
+
272
+ ### @Public()
273
+
274
+ Mark routes as public (skip authentication):
275
+
276
+ ```typescript
277
+ import { Public } from '@hazeljs/auth';
278
+
279
+ @Controller('/api')
280
+ @UseGuard(AuthGuard) // Applied to all routes
281
+ export class ApiController {
282
+ @Get('/public')
283
+ @Public() // This route skips authentication
284
+ getPublicData() {
285
+ return { data: 'public' };
286
+ }
287
+
288
+ @Get('/private')
289
+ getPrivateData(@CurrentUser() user: any) {
290
+ return { data: 'private', user };
291
+ }
292
+ }
293
+ ```
294
+
295
+ ### @Roles()
296
+
297
+ Shorthand for role-based access:
298
+
299
+ ```typescript
300
+ import { Roles } from '@hazeljs/auth';
301
+
302
+ @Controller('/admin')
303
+ export class AdminController {
304
+ @Get('/dashboard')
305
+ @Roles('admin', 'superadmin')
306
+ getDashboard() {
307
+ return { dashboard: 'data' };
308
+ }
309
+ }
310
+ ```
311
+
312
+ ## Token Management
313
+
314
+ ### Generate Token
315
+
316
+ ```typescript
317
+ const token = await authService.generateToken({
318
+ sub: user.id,
319
+ email: user.email,
320
+ roles: ['user'],
321
+ customClaim: 'value',
322
+ });
323
+ ```
324
+
325
+ ### Verify Token
326
+
327
+ ```typescript
328
+ try {
329
+ const payload = await authService.verifyToken(token);
330
+ console.log(payload.sub); // user.id
331
+ console.log(payload.email);
332
+ } catch (error) {
333
+ console.error('Invalid token:', error.message);
334
+ }
335
+ ```
336
+
337
+ ### Decode Token (without verification)
338
+
339
+ ```typescript
340
+ const payload = authService.decodeToken(token);
341
+ console.log(payload);
342
+ ```
343
+
344
+ ### Blacklist Token
345
+
346
+ ```typescript
347
+ await authService.blacklistToken(token);
348
+
349
+ // Check if blacklisted
350
+ const isBlacklisted = await authService.isTokenBlacklisted(token);
351
+ ```
352
+
353
+ ## Configuration
354
+
355
+ ### Module Configuration
356
+
357
+ ```typescript
358
+ AuthModule.forRoot({
359
+ // JWT secret key
360
+ secret: process.env.JWT_SECRET,
361
+
362
+ // Access token expiration
363
+ expiresIn: '15m',
364
+
365
+ // Refresh token expiration
366
+ refreshExpiresIn: '7d',
367
+
368
+ // Token issuer
369
+ issuer: 'hazeljs-app',
370
+
371
+ // Token audience
372
+ audience: 'hazeljs-users',
373
+
374
+ // Algorithm
375
+ algorithm: 'HS256',
376
+
377
+ // Token blacklist (requires Redis)
378
+ blacklist: {
379
+ enabled: true,
380
+ redis: redisClient,
381
+ },
382
+ })
383
+ ```
384
+
385
+ ### Environment Variables
386
+
387
+ ```env
388
+ JWT_SECRET=your-super-secret-key-change-in-production
389
+ JWT_EXPIRES_IN=1h
390
+ JWT_REFRESH_EXPIRES_IN=7d
391
+ ```
392
+
393
+ ## Password Hashing
394
+
395
+ ```typescript
396
+ import { hash, compare } from '@hazeljs/auth';
397
+
398
+ // Hash password
399
+ const hashedPassword = await hash('user-password', 10);
400
+
401
+ // Compare password
402
+ const isValid = await compare('user-password', hashedPassword);
403
+ ```
404
+
405
+ ## Custom Guards
406
+
407
+ ```typescript
408
+ import { Guard, GuardContext } from '@hazeljs/core';
409
+ import { Injectable } from '@hazeljs/core';
410
+
411
+ @Injectable()
412
+ export class CustomAuthGuard implements Guard {
413
+ async canActivate(context: GuardContext): Promise<boolean> {
414
+ const request = context.request;
415
+ const token = request.headers.authorization?.split(' ')[1];
416
+
417
+ if (!token) {
418
+ return false;
419
+ }
420
+
421
+ try {
422
+ const payload = await this.authService.verifyToken(token);
423
+ request.user = payload;
424
+ return true;
425
+ } catch {
426
+ return false;
427
+ }
428
+ }
429
+ }
430
+ ```
431
+
432
+ ## API Reference
433
+
434
+ ### AuthService
435
+
436
+ ```typescript
437
+ class AuthService {
438
+ generateToken(payload: any, options?: SignOptions): Promise<string>;
439
+ generateRefreshToken(payload: any): Promise<string>;
440
+ verifyToken(token: string): Promise<any>;
441
+ verifyRefreshToken(token: string): Promise<any>;
442
+ decodeToken(token: string): any;
443
+ blacklistToken(token: string): Promise<void>;
444
+ isTokenBlacklisted(token: string): Promise<boolean>;
445
+ }
446
+ ```
447
+
448
+ ### Guards
449
+
450
+ - `AuthGuard` - Validates JWT token
451
+ - `RoleGuard(roles: string[])` - Checks user roles
452
+ - `PermissionGuard(permissions: string[])` - Checks user permissions
453
+
454
+ ### Decorators
455
+
456
+ - `@CurrentUser(property?: string)` - Extract user from request
457
+ - `@Public()` - Skip authentication
458
+ - `@Roles(...roles: string[])` - Require specific roles
459
+
460
+ ## Examples
461
+
462
+ See the [examples](../../example/src/auth) directory for complete working examples.
463
+
464
+ ## Testing
465
+
466
+ ```bash
467
+ npm test
468
+ ```
469
+
470
+ ## Contributing
471
+
472
+ Contributions are welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md) for details.
473
+
474
+ ## License
475
+
476
+ MIT © [HazelJS](https://hazeljs.com)
477
+
478
+ ## Links
479
+
480
+ - [Documentation](https://hazeljs.com/docs/packages/auth)
481
+ - [GitHub](https://github.com/hazel-js/hazeljs)
482
+ - [Issues](https://github.com/hazeljs/hazel-js/issues)
483
+ - [Discord](https://discord.gg/hazeljs)
@@ -0,0 +1,15 @@
1
+ import { RequestContext } from '@hazeljs/core';
2
+ import { AuthService } from './auth.service';
3
+ export interface AuthGuardOptions {
4
+ roles?: string[];
5
+ }
6
+ export interface IAuthGuard {
7
+ canActivate(context: RequestContext, options?: AuthGuardOptions): Promise<boolean>;
8
+ }
9
+ export declare class AuthGuard implements IAuthGuard {
10
+ private authService;
11
+ constructor(authService: AuthService);
12
+ canActivate(context: RequestContext, options?: AuthGuardOptions): Promise<boolean>;
13
+ }
14
+ export declare function Auth(options?: AuthGuardOptions): (target: unknown, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
15
+ //# sourceMappingURL=auth.guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../src/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAK/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF;AAMD,qBACa,SAAU,YAAW,UAAU;IAC9B,OAAO,CAAC,WAAW;gBAAX,WAAW,EAAE,WAAW;IAEtC,WAAW,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CA4CzF;AAGD,wBAAgB,IAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,IAE3C,QAAQ,OAAO,EACf,aAAa,MAAM,EACnB,YAAY,kBAAkB,KAC7B,kBAAkB,CA2BtB"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AuthGuard = void 0;
16
+ exports.Auth = Auth;
17
+ const core_1 = require("@hazeljs/core");
18
+ const core_2 = __importDefault(require("@hazeljs/core"));
19
+ const core_3 = require("@hazeljs/core");
20
+ const auth_service_1 = require("./auth.service");
21
+ let AuthGuard = class AuthGuard {
22
+ constructor(authService) {
23
+ this.authService = authService;
24
+ }
25
+ async canActivate(context, options) {
26
+ const authHeader = context.headers['authorization'];
27
+ if (!authHeader) {
28
+ const error = new Error('No authorization header');
29
+ error.status = 400;
30
+ throw error;
31
+ }
32
+ const token = authHeader.split(' ')[1];
33
+ if (!token) {
34
+ const error = new Error('Invalid authorization header format');
35
+ error.status = 400;
36
+ throw error;
37
+ }
38
+ try {
39
+ const user = await this.authService.verifyToken(token);
40
+ if (!user) {
41
+ const error = new Error('Invalid token');
42
+ error.status = 401;
43
+ throw error;
44
+ }
45
+ // Check roles if specified
46
+ if (options?.roles && !options.roles.includes(user.role)) {
47
+ const error = new Error('Insufficient permissions');
48
+ error.status = 403;
49
+ throw error;
50
+ }
51
+ // Attach user to context
52
+ context.user = user;
53
+ return true;
54
+ }
55
+ catch (error) {
56
+ const authError = error;
57
+ core_2.default.error(`[${context.method}] ${context.url} - ${authError.message} (status: ${authError.status || 500})`);
58
+ if (process.env.NODE_ENV === 'development' && authError.stack) {
59
+ core_2.default.debug(authError.stack);
60
+ }
61
+ throw authError;
62
+ }
63
+ }
64
+ };
65
+ exports.AuthGuard = AuthGuard;
66
+ exports.AuthGuard = AuthGuard = __decorate([
67
+ (0, core_1.Injectable)(),
68
+ __metadata("design:paramtypes", [auth_service_1.AuthService])
69
+ ], AuthGuard);
70
+ // Decorator factory for protecting routes
71
+ function Auth(options) {
72
+ return function (target, propertyKey, descriptor) {
73
+ const originalMethod = descriptor.value;
74
+ descriptor.value = async function (context) {
75
+ try {
76
+ // Get the auth guard instance from the container
77
+ const container = core_3.Container.getInstance();
78
+ const guard = container.resolve(AuthGuard);
79
+ if (!guard) {
80
+ throw new Error('AuthGuard not found. Make sure to provide an AuthGuard implementation.');
81
+ }
82
+ await guard.canActivate(context, options);
83
+ return originalMethod.call(this, context);
84
+ }
85
+ catch (error) {
86
+ const authError = error;
87
+ core_2.default.error(`[${context.method}] ${context.url} - ${authError.message} (status: ${authError.status || 500})`);
88
+ if (process.env.NODE_ENV === 'development' && authError.stack) {
89
+ core_2.default.debug(authError.stack);
90
+ }
91
+ throw authError;
92
+ }
93
+ };
94
+ return descriptor;
95
+ };
96
+ }
@@ -0,0 +1,13 @@
1
+ import { JwtService } from './jwt/jwt.service';
2
+ export interface AuthUser {
3
+ id: string;
4
+ username?: string;
5
+ role: string;
6
+ [key: string]: unknown;
7
+ }
8
+ export declare class AuthService {
9
+ private readonly jwtService;
10
+ constructor(jwtService: JwtService);
11
+ verifyToken(token: string): Promise<AuthUser | null>;
12
+ }
13
+ //# sourceMappingURL=auth.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../src/auth.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAc,MAAM,mBAAmB,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBACa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,UAAU;IAE7C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAa3D"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AuthService = void 0;
13
+ const core_1 = require("@hazeljs/core");
14
+ const jwt_service_1 = require("./jwt/jwt.service");
15
+ let AuthService = class AuthService {
16
+ constructor(jwtService) {
17
+ this.jwtService = jwtService;
18
+ }
19
+ async verifyToken(token) {
20
+ try {
21
+ const payload = this.jwtService.verify(token);
22
+ return {
23
+ id: payload.sub,
24
+ username: payload.username || payload.email,
25
+ role: payload.role || 'user',
26
+ ...payload,
27
+ };
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ };
34
+ exports.AuthService = AuthService;
35
+ exports.AuthService = AuthService = __decorate([
36
+ (0, core_1.Injectable)(),
37
+ __metadata("design:paramtypes", [jwt_service_1.JwtService])
38
+ ], AuthService);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @hazeljs/auth - Authentication module for HazelJS
3
+ */
4
+ export { AuthGuard } from './auth.guard';
5
+ export { AuthService } from './auth.service';
6
+ export { JwtModule } from './jwt/jwt.module';
7
+ export { JwtService } from './jwt/jwt.service';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * @hazeljs/auth - Authentication module for HazelJS
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.JwtService = exports.JwtModule = exports.AuthService = exports.AuthGuard = void 0;
7
+ var auth_guard_1 = require("./auth.guard");
8
+ Object.defineProperty(exports, "AuthGuard", { enumerable: true, get: function () { return auth_guard_1.AuthGuard; } });
9
+ var auth_service_1 = require("./auth.service");
10
+ Object.defineProperty(exports, "AuthService", { enumerable: true, get: function () { return auth_service_1.AuthService; } });
11
+ var jwt_module_1 = require("./jwt/jwt.module");
12
+ Object.defineProperty(exports, "JwtModule", { enumerable: true, get: function () { return jwt_module_1.JwtModule; } });
13
+ var jwt_service_1 = require("./jwt/jwt.service");
14
+ Object.defineProperty(exports, "JwtService", { enumerable: true, get: function () { return jwt_service_1.JwtService; } });
@@ -0,0 +1,7 @@
1
+ import { JwtServiceOptions } from './jwt.service';
2
+ export interface JwtModuleOptions extends JwtServiceOptions {
3
+ }
4
+ export declare class JwtModule {
5
+ static forRoot(options?: JwtModuleOptions): typeof JwtModule;
6
+ }
7
+ //# sourceMappingURL=jwt.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.module.d.ts","sourceRoot":"","sources":["../../src/jwt/jwt.module.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;CAAG;AAE9D,qBAIa,SAAS;IACpB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,SAAS;CAM7D"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var JwtModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.JwtModule = void 0;
11
+ const core_1 = require("@hazeljs/core");
12
+ const jwt_service_1 = require("./jwt.service");
13
+ let JwtModule = JwtModule_1 = class JwtModule {
14
+ static forRoot(options) {
15
+ if (options) {
16
+ jwt_service_1.JwtService.configure(options);
17
+ }
18
+ return JwtModule_1;
19
+ }
20
+ };
21
+ exports.JwtModule = JwtModule;
22
+ exports.JwtModule = JwtModule = JwtModule_1 = __decorate([
23
+ (0, core_1.HazelModule)({
24
+ providers: [jwt_service_1.JwtService],
25
+ exports: [jwt_service_1.JwtService],
26
+ })
27
+ ], JwtModule);
@@ -0,0 +1,25 @@
1
+ export interface JwtPayload {
2
+ sub: string;
3
+ [key: string]: unknown;
4
+ }
5
+ export interface JwtServiceOptions {
6
+ secret?: string;
7
+ expiresIn?: string | number;
8
+ issuer?: string;
9
+ audience?: string;
10
+ }
11
+ export declare class JwtService {
12
+ private readonly secret;
13
+ private readonly defaultExpiresIn;
14
+ private readonly issuer?;
15
+ private readonly audience?;
16
+ constructor();
17
+ private static moduleOptions;
18
+ static configure(options: JwtServiceOptions): void;
19
+ sign(payload: JwtPayload, options?: {
20
+ expiresIn?: string | number;
21
+ }): string;
22
+ verify(token: string): JwtPayload;
23
+ decode(token: string): JwtPayload | null;
24
+ }
25
+ //# sourceMappingURL=jwt.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.service.d.ts","sourceRoot":"","sources":["../../src/jwt/jwt.service.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBACa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;;IAgBnC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAyB;IAErD,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAIlD,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,MAAM;IAU5E,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAQjC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;CAIzC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ var JwtService_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.JwtService = void 0;
17
+ const core_1 = require("@hazeljs/core");
18
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
19
+ let JwtService = JwtService_1 = class JwtService {
20
+ constructor() {
21
+ const options = JwtService_1.moduleOptions;
22
+ this.secret = options.secret || process.env.JWT_SECRET || '';
23
+ this.defaultExpiresIn = options.expiresIn || process.env.JWT_EXPIRES_IN || '1h';
24
+ this.issuer = options.issuer || process.env.JWT_ISSUER;
25
+ this.audience = options.audience || process.env.JWT_AUDIENCE;
26
+ if (!this.secret) {
27
+ throw new Error('JWT secret is not configured. Set JWT_SECRET environment variable or pass secret via JwtModule.forRoot({ secret: "..." })');
28
+ }
29
+ }
30
+ static configure(options) {
31
+ JwtService_1.moduleOptions = options;
32
+ }
33
+ sign(payload, options) {
34
+ const signOptions = {
35
+ expiresIn: (options?.expiresIn || this.defaultExpiresIn),
36
+ };
37
+ if (this.issuer)
38
+ signOptions.issuer = this.issuer;
39
+ if (this.audience)
40
+ signOptions.audience = this.audience;
41
+ return jsonwebtoken_1.default.sign(payload, this.secret, signOptions);
42
+ }
43
+ verify(token) {
44
+ const verifyOptions = {};
45
+ if (this.issuer)
46
+ verifyOptions.issuer = this.issuer;
47
+ if (this.audience)
48
+ verifyOptions.audience = this.audience;
49
+ return jsonwebtoken_1.default.verify(token, this.secret, verifyOptions);
50
+ }
51
+ decode(token) {
52
+ const decoded = jsonwebtoken_1.default.decode(token);
53
+ return decoded;
54
+ }
55
+ };
56
+ exports.JwtService = JwtService;
57
+ JwtService.moduleOptions = {};
58
+ exports.JwtService = JwtService = JwtService_1 = __decorate([
59
+ (0, core_1.Injectable)(),
60
+ __metadata("design:paramtypes", [])
61
+ ], JwtService);
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@hazeljs/auth",
3
+ "version": "0.2.0-beta.1",
4
+ "description": "Authentication and JWT module for HazelJS framework",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "test": "jest --coverage --passWithNoTests",
13
+ "lint": "eslint \"src/**/*.ts\"",
14
+ "lint:fix": "eslint \"src/**/*.ts\" --fix",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "dependencies": {
18
+ "@hazeljs/core": "file:../core",
19
+ "jsonwebtoken": "^9.0.2"
20
+ },
21
+ "devDependencies": {
22
+ "@types/jsonwebtoken": "^9.0.9",
23
+ "@types/node": "^20.17.50",
24
+ "@typescript-eslint/eslint-plugin": "^8.18.2",
25
+ "@typescript-eslint/parser": "^8.18.2",
26
+ "eslint": "^8.56.0",
27
+ "jest": "^29.7.0",
28
+ "ts-jest": "^29.1.2",
29
+ "typescript": "^5.3.3"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/hazel-js/hazeljs.git",
37
+ "directory": "packages/auth"
38
+ },
39
+ "keywords": [
40
+ "hazeljs",
41
+ "auth",
42
+ "authentication",
43
+ "jwt",
44
+ "security"
45
+ ],
46
+ "author": "Muhammad Arslan <marslan@hazeljs.com>",
47
+ "license": "MIT"
48
+ }