@veloxts/auth 0.6.89 → 0.6.91
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/CHANGELOG.md +18 -11
- package/GUIDE.md +20 -4
- package/dist/hash.d.ts +25 -0
- package/dist/hash.js +25 -0
- package/dist/index.d.ts +1 -22
- package/dist/index.js +1 -35
- package/dist/middleware.d.ts +12 -5
- package/dist/middleware.js +7 -5
- package/dist/plugin.d.ts +65 -31
- package/dist/plugin.js +54 -107
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @veloxts/auth
|
|
2
2
|
|
|
3
|
+
## 0.6.91
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- removed unused DI system
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @veloxts/core@0.6.91
|
|
10
|
+
- @veloxts/router@0.6.91
|
|
11
|
+
|
|
12
|
+
## 0.6.90
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Dependencies updates – fix critical and high severity vulnerabilities
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @veloxts/core@0.6.90
|
|
19
|
+
- @veloxts/router@0.6.90
|
|
20
|
+
|
|
3
21
|
## 0.6.89
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -178,7 +196,6 @@
|
|
|
178
196
|
- ### feat(auth): Unified Adapter-Only Architecture
|
|
179
197
|
|
|
180
198
|
**New Features:**
|
|
181
|
-
|
|
182
199
|
- Add `JwtAdapter` implementing the `AuthAdapter` interface for unified JWT authentication
|
|
183
200
|
- Add `jwtAuth()` convenience function for direct adapter usage with optional built-in routes (`/api/auth/refresh`, `/api/auth/logout`)
|
|
184
201
|
- Add `AuthContext` discriminated union (`NativeAuthContext | AdapterAuthContext`) for type-safe auth mode handling
|
|
@@ -186,24 +203,20 @@
|
|
|
186
203
|
- Add shared decoration utilities (`decorateAuth`, `setRequestAuth`, `checkDoubleRegistration`)
|
|
187
204
|
|
|
188
205
|
**Architecture Changes:**
|
|
189
|
-
|
|
190
206
|
- `authPlugin` now uses `JwtAdapter` internally - all authentication flows through the adapter pattern
|
|
191
207
|
- Single code path for authentication (no more dual native/adapter modes)
|
|
192
208
|
- `authContext.authMode` is now always `'adapter'` with `providerId='jwt'` when using `authPlugin`
|
|
193
209
|
|
|
194
210
|
**Breaking Changes:**
|
|
195
|
-
|
|
196
211
|
- Remove deprecated `LegacySessionConfig` interface (use `sessionMiddleware` instead)
|
|
197
212
|
- Remove deprecated `session` field from `AuthConfig`
|
|
198
213
|
- `User` interface no longer has index signature (extend via declaration merging)
|
|
199
214
|
|
|
200
215
|
**Type Safety Improvements:**
|
|
201
|
-
|
|
202
216
|
- `AuthContext` discriminated union enables exhaustive type narrowing based on `authMode`
|
|
203
217
|
- Export `NativeAuthContext` and `AdapterAuthContext` types for explicit typing
|
|
204
218
|
|
|
205
219
|
**Migration:**
|
|
206
|
-
|
|
207
220
|
- Existing `authPlugin` usage remains backward-compatible
|
|
208
221
|
- If checking `authContext.token`, use `authContext.session` instead (token stored in session for adapter mode)
|
|
209
222
|
|
|
@@ -222,12 +235,10 @@
|
|
|
222
235
|
Addresses 9 user feedback items to improve DX, reduce boilerplate, and eliminate template duplications.
|
|
223
236
|
|
|
224
237
|
### Phase 1: Validation Helpers (`@veloxts/validation`)
|
|
225
|
-
|
|
226
238
|
- Add `prismaDecimal()`, `prismaDecimalNullable()`, `prismaDecimalOptional()` for Prisma Decimal → number conversion
|
|
227
239
|
- Add `dateToIso`, `dateToIsoNullable`, `dateToIsoOptional` aliases for consistency
|
|
228
240
|
|
|
229
241
|
### Phase 2: Template Deduplication (`@veloxts/auth`)
|
|
230
|
-
|
|
231
242
|
- Export `createEnhancedTokenStore()` with token revocation and refresh token reuse detection
|
|
232
243
|
- Export `parseUserRoles()` and `DEFAULT_ALLOWED_ROLES`
|
|
233
244
|
- Fix memory leak: track pending timeouts for proper cleanup on `destroy()`
|
|
@@ -235,20 +246,17 @@
|
|
|
235
246
|
- Fix jwtManager singleton pattern in templates
|
|
236
247
|
|
|
237
248
|
### Phase 3: Router Helpers (`@veloxts/router`)
|
|
238
|
-
|
|
239
249
|
- Add `createRouter()` returning `{ collections, router }` for DRY setup
|
|
240
250
|
- Add `toRouter()` for router-only use cases
|
|
241
251
|
- Update all router templates to use `createRouter()`
|
|
242
252
|
|
|
243
253
|
### Phase 4: Guard Type Narrowing - Experimental (`@veloxts/auth`, `@veloxts/router`)
|
|
244
|
-
|
|
245
254
|
- Add `NarrowingGuard` interface with phantom `_narrows` type
|
|
246
255
|
- Add `authenticatedNarrow` and `hasRoleNarrow()` guards
|
|
247
256
|
- Add `guardNarrow()` method to `ProcedureBuilder` for context narrowing
|
|
248
257
|
- Enables `ctx.user` to be non-null after guard passes
|
|
249
258
|
|
|
250
259
|
### Phase 5: Documentation (`@veloxts/router`)
|
|
251
|
-
|
|
252
260
|
- Document `.rest()` override patterns
|
|
253
261
|
- Document `createRouter()` helper usage
|
|
254
262
|
- Document `guardNarrow()` experimental API
|
|
@@ -1179,7 +1187,6 @@
|
|
|
1179
1187
|
### Patch Changes
|
|
1180
1188
|
|
|
1181
1189
|
- Fix Prisma client generation in scaffolder
|
|
1182
|
-
|
|
1183
1190
|
- Added automatic Prisma client generation after dependency installation in create-velox-app
|
|
1184
1191
|
- Fixed database template to validate DATABASE_URL environment variable
|
|
1185
1192
|
- Added alpha release warning to all package READMEs
|
package/GUIDE.md
CHANGED
|
@@ -22,9 +22,13 @@ const session = sessionMiddleware({
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
const getProfile = procedure()
|
|
25
|
-
.use(session.
|
|
25
|
+
.use(session.required())
|
|
26
26
|
.query(({ ctx }) => ctx.user);
|
|
27
27
|
|
|
28
|
+
const publicPage = procedure()
|
|
29
|
+
.use(session.optional())
|
|
30
|
+
.query(({ ctx }) => ({ user: ctx.user ?? null }));
|
|
31
|
+
|
|
28
32
|
// Login/Logout
|
|
29
33
|
await ctx.session.login(user);
|
|
30
34
|
await ctx.session.logout();
|
|
@@ -47,8 +51,12 @@ const auth = authMiddleware({
|
|
|
47
51
|
});
|
|
48
52
|
|
|
49
53
|
const getProfile = procedure()
|
|
50
|
-
.use(auth.
|
|
54
|
+
.use(auth.required())
|
|
51
55
|
.query(({ ctx }) => ctx.user);
|
|
56
|
+
|
|
57
|
+
const publicEndpoint = procedure()
|
|
58
|
+
.use(auth.optional())
|
|
59
|
+
.query(({ ctx }) => ({ user: ctx.user ?? null }));
|
|
52
60
|
```
|
|
53
61
|
|
|
54
62
|
## Guards
|
|
@@ -81,10 +89,18 @@ const adminWithPermission = procedure()
|
|
|
81
89
|
## Password Hashing
|
|
82
90
|
|
|
83
91
|
```typescript
|
|
84
|
-
import { hashPassword, verifyPassword } from '@veloxts/auth';
|
|
92
|
+
import { hashPassword, verifyPassword, passwordHasher, DEFAULT_HASH_CONFIG } from '@veloxts/auth';
|
|
85
93
|
|
|
86
|
-
|
|
94
|
+
// Simple usage (uses DEFAULT_HASH_CONFIG: bcrypt, 12 rounds)
|
|
95
|
+
const hash = await hashPassword('password');
|
|
87
96
|
const valid = await verifyPassword('password', hash);
|
|
97
|
+
|
|
98
|
+
// Custom configuration
|
|
99
|
+
const hasher = passwordHasher({
|
|
100
|
+
...DEFAULT_HASH_CONFIG,
|
|
101
|
+
bcryptRounds: 14, // Increase for higher security
|
|
102
|
+
});
|
|
103
|
+
const customHash = await hasher.hash('password');
|
|
88
104
|
```
|
|
89
105
|
|
|
90
106
|
## Learn More
|
package/dist/hash.d.ts
CHANGED
|
@@ -3,6 +3,31 @@
|
|
|
3
3
|
* @module auth/hash
|
|
4
4
|
*/
|
|
5
5
|
import type { HashConfig } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Default password hashing configuration
|
|
8
|
+
*
|
|
9
|
+
* Uses bcrypt with 12 rounds, which provides a good balance between
|
|
10
|
+
* security and performance. Increase rounds for higher security
|
|
11
|
+
* (each increment doubles the computation time).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { DEFAULT_HASH_CONFIG, passwordHasher } from '@veloxts/auth';
|
|
16
|
+
*
|
|
17
|
+
* // Use defaults explicitly
|
|
18
|
+
* const hasher = passwordHasher(DEFAULT_HASH_CONFIG);
|
|
19
|
+
*
|
|
20
|
+
* // Or customize from defaults
|
|
21
|
+
* const strongerHasher = passwordHasher({
|
|
22
|
+
* ...DEFAULT_HASH_CONFIG,
|
|
23
|
+
* bcryptRounds: 14,
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_HASH_CONFIG: {
|
|
28
|
+
readonly algorithm: "bcrypt";
|
|
29
|
+
readonly bcryptRounds: 12;
|
|
30
|
+
};
|
|
6
31
|
/**
|
|
7
32
|
* Password hasher with configurable algorithms
|
|
8
33
|
*
|
package/dist/hash.js
CHANGED
|
@@ -12,6 +12,31 @@ const DEFAULT_BCRYPT_ROUNDS = 12;
|
|
|
12
12
|
const DEFAULT_ARGON2_MEMORY_COST = 65536; // 64 MB
|
|
13
13
|
const DEFAULT_ARGON2_TIME_COST = 3;
|
|
14
14
|
const DEFAULT_ARGON2_PARALLELISM = 4;
|
|
15
|
+
/**
|
|
16
|
+
* Default password hashing configuration
|
|
17
|
+
*
|
|
18
|
+
* Uses bcrypt with 12 rounds, which provides a good balance between
|
|
19
|
+
* security and performance. Increase rounds for higher security
|
|
20
|
+
* (each increment doubles the computation time).
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { DEFAULT_HASH_CONFIG, passwordHasher } from '@veloxts/auth';
|
|
25
|
+
*
|
|
26
|
+
* // Use defaults explicitly
|
|
27
|
+
* const hasher = passwordHasher(DEFAULT_HASH_CONFIG);
|
|
28
|
+
*
|
|
29
|
+
* // Or customize from defaults
|
|
30
|
+
* const strongerHasher = passwordHasher({
|
|
31
|
+
* ...DEFAULT_HASH_CONFIG,
|
|
32
|
+
* bcryptRounds: 14,
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const DEFAULT_HASH_CONFIG = {
|
|
37
|
+
algorithm: 'bcrypt',
|
|
38
|
+
bcryptRounds: DEFAULT_BCRYPT_ROUNDS,
|
|
39
|
+
};
|
|
15
40
|
// ============================================================================
|
|
16
41
|
// Password Hasher Class
|
|
17
42
|
// ============================================================================
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type { EnhancedTokenStore, EnhancedTokenStoreOptions } from './token-stor
|
|
|
17
17
|
export { createEnhancedTokenStore, DEFAULT_ALLOWED_ROLES, parseUserRoles, } from './token-store.js';
|
|
18
18
|
export type { AuthenticatedContext, InferNarrowedContext, NarrowingGuard, RoleNarrowedContext, } from './guards-narrowing.js';
|
|
19
19
|
export { authenticatedNarrow, hasRoleNarrow } from './guards-narrowing.js';
|
|
20
|
-
export { hashPassword, PasswordHasher, passwordHasher, verifyPassword, } from './hash.js';
|
|
20
|
+
export { DEFAULT_HASH_CONFIG, hashPassword, PasswordHasher, passwordHasher, verifyPassword, } from './hash.js';
|
|
21
21
|
export type { GuardBuilder } from './guards.js';
|
|
22
22
|
export { allOf, anyOf, authenticated, defineGuard, emailVerified, executeGuard, executeGuards, guard, hasAnyPermission, hasPermission, hasRole, not, userCan, } from './guards.js';
|
|
23
23
|
export { authorize, can, cannot, clearPolicies, createAdminOnlyPolicy, createOwnerOrAdminPolicy, createPolicyBuilder, createReadOnlyPolicy, definePolicy, getPolicy, registerPolicy, } from './policies.js';
|
|
@@ -38,24 +38,3 @@ export type { JwtAdapterConfig } from './adapters/jwt-adapter.js';
|
|
|
38
38
|
export { createJwtAdapter, JwtAdapter } from './adapters/jwt-adapter.js';
|
|
39
39
|
export type { PasswordPolicyConfig, PasswordValidationResult, UserInfo, } from './password-policy.js';
|
|
40
40
|
export { checkPasswordBreach, checkPasswordStrength, isCommonPassword, PasswordPolicy, PasswordStrength, passwordPolicy, } from './password-policy.js';
|
|
41
|
-
/**
|
|
42
|
-
* DI tokens and providers for @veloxts/auth
|
|
43
|
-
*
|
|
44
|
-
* Use these to integrate auth services with the @veloxts/core DI container.
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```typescript
|
|
48
|
-
* import { Container } from '@veloxts/core';
|
|
49
|
-
* import { registerAuthProviders, JWT_MANAGER, PASSWORD_HASHER } from '@veloxts/auth';
|
|
50
|
-
*
|
|
51
|
-
* const container = new Container();
|
|
52
|
-
* registerAuthProviders(container, {
|
|
53
|
-
* jwt: { secret: process.env.JWT_SECRET! }
|
|
54
|
-
* });
|
|
55
|
-
*
|
|
56
|
-
* const jwt = container.resolve(JWT_MANAGER);
|
|
57
|
-
* const hasher = container.resolve(PASSWORD_HASHER);
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
export { authServiceProvider, jwtManagerProvider, passwordHasherProvider, passwordHasherProviderWithDefaults, registerAuthProviders, } from './providers.js';
|
|
61
|
-
export { AUTH_CONFIG, AUTH_RATE_LIMITER, AUTH_SERVICE, CSRF_CONFIG, HASH_CONFIG, JWT_CONFIG, JWT_MANAGER, PASSWORD_HASHER, RATE_LIMIT_CONFIG, SESSION_CONFIG, SESSION_STORE, TOKEN_STORE, } from './tokens.js';
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ export { authenticatedNarrow, hasRoleNarrow } from './guards-narrowing.js';
|
|
|
22
22
|
// ============================================================================
|
|
23
23
|
// Password Hashing
|
|
24
24
|
// ============================================================================
|
|
25
|
-
export { hashPassword, PasswordHasher, passwordHasher, verifyPassword, } from './hash.js';
|
|
25
|
+
export { DEFAULT_HASH_CONFIG, hashPassword, PasswordHasher, passwordHasher, verifyPassword, } from './hash.js';
|
|
26
26
|
export {
|
|
27
27
|
// Combinators
|
|
28
28
|
allOf, anyOf,
|
|
@@ -71,37 +71,3 @@ isAuthAdapter, } from './adapter.js';
|
|
|
71
71
|
export { BetterAuthAdapter, createBetterAuthAdapter } from './adapters/better-auth.js';
|
|
72
72
|
export { createJwtAdapter, JwtAdapter } from './adapters/jwt-adapter.js';
|
|
73
73
|
export { checkPasswordBreach, checkPasswordStrength, isCommonPassword, PasswordPolicy, PasswordStrength, passwordPolicy, } from './password-policy.js';
|
|
74
|
-
// ============================================================================
|
|
75
|
-
// Dependency Injection
|
|
76
|
-
// ============================================================================
|
|
77
|
-
/**
|
|
78
|
-
* DI tokens and providers for @veloxts/auth
|
|
79
|
-
*
|
|
80
|
-
* Use these to integrate auth services with the @veloxts/core DI container.
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```typescript
|
|
84
|
-
* import { Container } from '@veloxts/core';
|
|
85
|
-
* import { registerAuthProviders, JWT_MANAGER, PASSWORD_HASHER } from '@veloxts/auth';
|
|
86
|
-
*
|
|
87
|
-
* const container = new Container();
|
|
88
|
-
* registerAuthProviders(container, {
|
|
89
|
-
* jwt: { secret: process.env.JWT_SECRET! }
|
|
90
|
-
* });
|
|
91
|
-
*
|
|
92
|
-
* const jwt = container.resolve(JWT_MANAGER);
|
|
93
|
-
* const hasher = container.resolve(PASSWORD_HASHER);
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
// Provider exports - factory functions for registering services
|
|
97
|
-
export { authServiceProvider, jwtManagerProvider, passwordHasherProvider, passwordHasherProviderWithDefaults,
|
|
98
|
-
// Bulk registration helper
|
|
99
|
-
registerAuthProviders, } from './providers.js';
|
|
100
|
-
// Token exports - unique identifiers for DI resolution
|
|
101
|
-
export {
|
|
102
|
-
// Config tokens
|
|
103
|
-
AUTH_CONFIG, AUTH_RATE_LIMITER,
|
|
104
|
-
// Service tokens
|
|
105
|
-
AUTH_SERVICE, CSRF_CONFIG, HASH_CONFIG, JWT_CONFIG, JWT_MANAGER, PASSWORD_HASHER, RATE_LIMIT_CONFIG, SESSION_CONFIG,
|
|
106
|
-
// Store tokens
|
|
107
|
-
SESSION_STORE, TOKEN_STORE, } from './tokens.js';
|
package/dist/middleware.d.ts
CHANGED
|
@@ -20,18 +20,17 @@ import type { AuthConfig, AuthMiddlewareOptions, GuardDefinition, NativeAuthCont
|
|
|
20
20
|
* ```typescript
|
|
21
21
|
* const auth = authMiddleware(authConfig);
|
|
22
22
|
*
|
|
23
|
-
* //
|
|
23
|
+
* // Required auth (user guaranteed to exist)
|
|
24
24
|
* const getProfile = procedure()
|
|
25
|
-
* .use(auth.
|
|
25
|
+
* .use(auth.required())
|
|
26
26
|
* .query(async ({ ctx }) => {
|
|
27
|
-
* return ctx.user;
|
|
27
|
+
* return ctx.user;
|
|
28
28
|
* });
|
|
29
29
|
*
|
|
30
30
|
* // Optional auth (user may be undefined)
|
|
31
31
|
* const getPosts = procedure()
|
|
32
|
-
* .use(auth.
|
|
32
|
+
* .use(auth.optional())
|
|
33
33
|
* .query(async ({ ctx }) => {
|
|
34
|
-
* // ctx.user may be undefined
|
|
35
34
|
* return fetchPosts(ctx.user?.id);
|
|
36
35
|
* });
|
|
37
36
|
*
|
|
@@ -56,6 +55,14 @@ export declare function authMiddleware(config: AuthConfig): {
|
|
|
56
55
|
user?: User;
|
|
57
56
|
auth: NativeAuthContext;
|
|
58
57
|
}, TOutput>;
|
|
58
|
+
required: <TInput, TContext extends BaseContext, TOutput>(guards?: Array<GuardDefinition | string>) => MiddlewareFunction<TInput, TContext, TContext & {
|
|
59
|
+
user: User;
|
|
60
|
+
auth: NativeAuthContext;
|
|
61
|
+
}, TOutput>;
|
|
62
|
+
optional: <TInput, TContext extends BaseContext, TOutput>() => MiddlewareFunction<TInput, TContext, TContext & {
|
|
63
|
+
user?: User;
|
|
64
|
+
auth: NativeAuthContext;
|
|
65
|
+
}, TOutput>;
|
|
59
66
|
jwt: JwtManager;
|
|
60
67
|
};
|
|
61
68
|
/**
|
package/dist/middleware.js
CHANGED
|
@@ -22,18 +22,17 @@ import { AuthError } from './types.js';
|
|
|
22
22
|
* ```typescript
|
|
23
23
|
* const auth = authMiddleware(authConfig);
|
|
24
24
|
*
|
|
25
|
-
* //
|
|
25
|
+
* // Required auth (user guaranteed to exist)
|
|
26
26
|
* const getProfile = procedure()
|
|
27
|
-
* .use(auth.
|
|
27
|
+
* .use(auth.required())
|
|
28
28
|
* .query(async ({ ctx }) => {
|
|
29
|
-
* return ctx.user;
|
|
29
|
+
* return ctx.user;
|
|
30
30
|
* });
|
|
31
31
|
*
|
|
32
32
|
* // Optional auth (user may be undefined)
|
|
33
33
|
* const getPosts = procedure()
|
|
34
|
-
* .use(auth.
|
|
34
|
+
* .use(auth.optional())
|
|
35
35
|
* .query(async ({ ctx }) => {
|
|
36
|
-
* // ctx.user may be undefined
|
|
37
36
|
* return fetchPosts(ctx.user?.id);
|
|
38
37
|
* });
|
|
39
38
|
*
|
|
@@ -173,6 +172,9 @@ export function authMiddleware(config) {
|
|
|
173
172
|
middleware,
|
|
174
173
|
requireAuth,
|
|
175
174
|
optionalAuth,
|
|
175
|
+
// Terse aliases (Laravel-inspired)
|
|
176
|
+
required: requireAuth,
|
|
177
|
+
optional: optionalAuth,
|
|
176
178
|
jwt,
|
|
177
179
|
};
|
|
178
180
|
}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module auth/plugin
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
10
|
-
import type {
|
|
9
|
+
import type { VeloxPlugin } from '@veloxts/core';
|
|
10
|
+
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
11
|
+
import type { AdapterUser, AuthAdapterError, AuthAdapterPluginOptions } from './adapter.js';
|
|
11
12
|
import type { JwtAdapterConfig } from './adapters/jwt-adapter.js';
|
|
12
13
|
import { PasswordHasher } from './hash.js';
|
|
13
14
|
import type { JwtManager, TokenStore } from './jwt.js';
|
|
14
15
|
import { authMiddleware } from './middleware.js';
|
|
15
|
-
import type { AdapterAuthContext, AuthConfig, TokenPair, User } from './types.js';
|
|
16
|
+
import type { AdapterAuthContext, AuthConfig, JwtConfig, TokenPair, User } from './types.js';
|
|
16
17
|
/** Auth package version */
|
|
17
18
|
export declare const AUTH_VERSION: string;
|
|
18
19
|
/**
|
|
@@ -24,32 +25,6 @@ export interface AuthPluginOptions extends AuthConfig {
|
|
|
24
25
|
* @default false
|
|
25
26
|
*/
|
|
26
27
|
debug?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* DI container for service registration and resolution (optional)
|
|
29
|
-
*
|
|
30
|
-
* When provided, auth services are registered with the container and can be:
|
|
31
|
-
* - Resolved from the container directly
|
|
32
|
-
* - Mocked in tests by overriding registrations
|
|
33
|
-
* - Managed alongside other application services
|
|
34
|
-
*
|
|
35
|
-
* When not provided, services are created directly (legacy behavior).
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* import { Container } from '@veloxts/core';
|
|
40
|
-
* import { authPlugin, JWT_MANAGER } from '@veloxts/auth';
|
|
41
|
-
*
|
|
42
|
-
* const container = new Container();
|
|
43
|
-
* app.register(authPlugin({
|
|
44
|
-
* jwt: { secret: '...' },
|
|
45
|
-
* container,
|
|
46
|
-
* }));
|
|
47
|
-
*
|
|
48
|
-
* // Services now available from container
|
|
49
|
-
* const jwt = container.resolve(JWT_MANAGER);
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
container?: Container;
|
|
53
28
|
}
|
|
54
29
|
/**
|
|
55
30
|
* Auth service instance attached to Fastify
|
|
@@ -158,9 +133,68 @@ export declare function defaultAuthPlugin(): VeloxPlugin<AuthPluginOptions>;
|
|
|
158
133
|
/**
|
|
159
134
|
* Options for jwtAuth convenience function
|
|
160
135
|
*
|
|
161
|
-
*
|
|
136
|
+
* Explicit interface for better discoverability (name is auto-set to 'jwt').
|
|
162
137
|
*/
|
|
163
|
-
export
|
|
138
|
+
export interface JwtAuthOptions {
|
|
139
|
+
/**
|
|
140
|
+
* JWT configuration (secret, expiry, etc.)
|
|
141
|
+
*
|
|
142
|
+
* This is passed directly to JwtManager.
|
|
143
|
+
*/
|
|
144
|
+
jwt: JwtConfig;
|
|
145
|
+
/**
|
|
146
|
+
* Token store for revocation tracking
|
|
147
|
+
*
|
|
148
|
+
* Used to check if tokens have been revoked (e.g., on logout).
|
|
149
|
+
* Defaults to in-memory store (not suitable for production).
|
|
150
|
+
*/
|
|
151
|
+
tokenStore?: TokenStore;
|
|
152
|
+
/**
|
|
153
|
+
* Load user by ID
|
|
154
|
+
*
|
|
155
|
+
* Called when verifying tokens to load the full user object.
|
|
156
|
+
* If not provided, a minimal user object is created from token claims.
|
|
157
|
+
*/
|
|
158
|
+
userLoader?: (userId: string) => Promise<User | null>;
|
|
159
|
+
/**
|
|
160
|
+
* Enable built-in auth routes
|
|
161
|
+
*
|
|
162
|
+
* When true, mounts routes for token refresh and logout:
|
|
163
|
+
* - POST `${routePrefix}/refresh` - Refresh access token
|
|
164
|
+
* - POST `${routePrefix}/logout` - Revoke current token
|
|
165
|
+
*
|
|
166
|
+
* @default true
|
|
167
|
+
*/
|
|
168
|
+
enableRoutes?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Base path for auth routes
|
|
171
|
+
*
|
|
172
|
+
* Only used when `enableRoutes` is true.
|
|
173
|
+
*
|
|
174
|
+
* @default '/api/auth'
|
|
175
|
+
*/
|
|
176
|
+
routePrefix?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Enable debug logging
|
|
179
|
+
*
|
|
180
|
+
* @default false
|
|
181
|
+
*/
|
|
182
|
+
debug?: boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Transform adapter user to VeloxTS User
|
|
185
|
+
*
|
|
186
|
+
* Override to customize how token claims are transformed to User.
|
|
187
|
+
*/
|
|
188
|
+
transformUser?: (adapterUser: AdapterUser) => User;
|
|
189
|
+
/**
|
|
190
|
+
* Routes to exclude from automatic session loading
|
|
191
|
+
*/
|
|
192
|
+
excludeRoutes?: string[];
|
|
193
|
+
/**
|
|
194
|
+
* Custom error handler for adapter errors
|
|
195
|
+
*/
|
|
196
|
+
onError?: (error: AuthAdapterError, request: FastifyRequest, reply: FastifyReply) => void | Promise<void>;
|
|
197
|
+
}
|
|
164
198
|
/**
|
|
165
199
|
* Creates JWT auth using the adapter pattern directly
|
|
166
200
|
*
|
package/dist/plugin.js
CHANGED
|
@@ -12,8 +12,6 @@ import { createJwtAdapter } from './adapters/jwt-adapter.js';
|
|
|
12
12
|
import { checkDoubleRegistration, decorateAuth } from './decoration.js';
|
|
13
13
|
import { PasswordHasher } from './hash.js';
|
|
14
14
|
import { authMiddleware } from './middleware.js';
|
|
15
|
-
import { registerAuthProviders } from './providers.js';
|
|
16
|
-
import { AUTH_SERVICE } from './tokens.js';
|
|
17
15
|
// Read version from package.json dynamically
|
|
18
16
|
const require = createRequire(import.meta.url);
|
|
19
17
|
const packageJson = require('../package.json');
|
|
@@ -86,38 +84,66 @@ export function authPlugin(options) {
|
|
|
86
84
|
version: AUTH_VERSION,
|
|
87
85
|
async register(server, _opts) {
|
|
88
86
|
const config = { ...options, ..._opts };
|
|
89
|
-
const { debug = false
|
|
87
|
+
const { debug = false } = config;
|
|
90
88
|
// Prevent double-registration of auth systems
|
|
91
89
|
checkDoubleRegistration(server, 'authPlugin');
|
|
92
90
|
if (debug) {
|
|
93
91
|
server.log.info('Registering @veloxts/auth plugin (adapter-based)');
|
|
94
92
|
}
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
93
|
+
// Convert isTokenRevoked callback to TokenStore if provided
|
|
94
|
+
const tokenStore = config.isTokenRevoked
|
|
95
|
+
? createCallbackTokenStore(config.isTokenRevoked)
|
|
96
|
+
: undefined;
|
|
97
|
+
// Create the JWT adapter
|
|
98
|
+
const { adapter, config: adapterConfig } = createJwtAdapter({
|
|
99
|
+
jwt: config.jwt,
|
|
100
|
+
userLoader: config.userLoader,
|
|
101
|
+
tokenStore,
|
|
102
|
+
enableRoutes: false, // authPlugin manages its own API
|
|
103
|
+
debug,
|
|
104
|
+
});
|
|
105
|
+
// Initialize adapter
|
|
106
|
+
await adapter.initialize(server, adapterConfig);
|
|
107
|
+
// Decorate requests with auth context
|
|
108
|
+
decorateAuth(server);
|
|
109
|
+
// Get JWT manager from adapter
|
|
110
|
+
const jwt = adapter.getJwtManager();
|
|
111
|
+
const hasher = new PasswordHasher(config.hash);
|
|
112
|
+
const authMw = authMiddleware(config);
|
|
113
|
+
// Build AuthService from adapter
|
|
114
|
+
const authService = {
|
|
115
|
+
jwt,
|
|
116
|
+
hasher,
|
|
117
|
+
tokenStore: adapter.getTokenStore(),
|
|
118
|
+
createTokens(user, additionalClaims) {
|
|
119
|
+
return jwt.createTokenPair(user, additionalClaims);
|
|
120
|
+
},
|
|
121
|
+
verifyToken(token) {
|
|
122
|
+
const payload = jwt.verifyToken(token);
|
|
123
|
+
return {
|
|
124
|
+
authMode: 'adapter',
|
|
125
|
+
user: {
|
|
126
|
+
id: payload.sub,
|
|
127
|
+
email: payload.email,
|
|
128
|
+
},
|
|
129
|
+
isAuthenticated: true,
|
|
130
|
+
providerId: 'jwt',
|
|
131
|
+
session: { token, payload },
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
refreshTokens(refreshToken) {
|
|
135
|
+
if (config.userLoader) {
|
|
136
|
+
return jwt.refreshTokens(refreshToken, config.userLoader);
|
|
137
|
+
}
|
|
138
|
+
return jwt.refreshTokens(refreshToken);
|
|
139
|
+
},
|
|
140
|
+
middleware: authMw,
|
|
141
|
+
};
|
|
142
|
+
// Decorate server with auth service
|
|
143
|
+
server.decorate('auth', authService);
|
|
144
|
+
// Add preHandler hook for session loading (using adapter)
|
|
145
|
+
if (config.autoExtract !== false) {
|
|
118
146
|
server.addHook('preHandler', async (request) => {
|
|
119
|
-
if (config.autoExtract === false)
|
|
120
|
-
return;
|
|
121
147
|
const session = await adapter.getSession(request);
|
|
122
148
|
if (session) {
|
|
123
149
|
const user = {
|
|
@@ -140,85 +166,6 @@ export function authPlugin(options) {
|
|
|
140
166
|
}
|
|
141
167
|
});
|
|
142
168
|
}
|
|
143
|
-
else {
|
|
144
|
-
// Adapter-based path: Use JwtAdapter directly
|
|
145
|
-
// Convert isTokenRevoked callback to TokenStore if provided
|
|
146
|
-
const tokenStore = config.isTokenRevoked
|
|
147
|
-
? createCallbackTokenStore(config.isTokenRevoked)
|
|
148
|
-
: undefined;
|
|
149
|
-
// Create the JWT adapter
|
|
150
|
-
const { adapter, config: adapterConfig } = createJwtAdapter({
|
|
151
|
-
jwt: config.jwt,
|
|
152
|
-
userLoader: config.userLoader,
|
|
153
|
-
tokenStore,
|
|
154
|
-
enableRoutes: false, // authPlugin manages its own API
|
|
155
|
-
debug,
|
|
156
|
-
});
|
|
157
|
-
// Initialize adapter
|
|
158
|
-
await adapter.initialize(server, adapterConfig);
|
|
159
|
-
// Decorate requests with auth context
|
|
160
|
-
decorateAuth(server);
|
|
161
|
-
// Get JWT manager from adapter
|
|
162
|
-
const jwt = adapter.getJwtManager();
|
|
163
|
-
const hasher = new PasswordHasher(config.hash);
|
|
164
|
-
const authMw = authMiddleware(config);
|
|
165
|
-
// Build AuthService from adapter
|
|
166
|
-
const authService = {
|
|
167
|
-
jwt,
|
|
168
|
-
hasher,
|
|
169
|
-
tokenStore: adapter.getTokenStore(),
|
|
170
|
-
createTokens(user, additionalClaims) {
|
|
171
|
-
return jwt.createTokenPair(user, additionalClaims);
|
|
172
|
-
},
|
|
173
|
-
verifyToken(token) {
|
|
174
|
-
const payload = jwt.verifyToken(token);
|
|
175
|
-
return {
|
|
176
|
-
authMode: 'adapter',
|
|
177
|
-
user: {
|
|
178
|
-
id: payload.sub,
|
|
179
|
-
email: payload.email,
|
|
180
|
-
},
|
|
181
|
-
isAuthenticated: true,
|
|
182
|
-
providerId: 'jwt',
|
|
183
|
-
session: { token, payload },
|
|
184
|
-
};
|
|
185
|
-
},
|
|
186
|
-
refreshTokens(refreshToken) {
|
|
187
|
-
if (config.userLoader) {
|
|
188
|
-
return jwt.refreshTokens(refreshToken, config.userLoader);
|
|
189
|
-
}
|
|
190
|
-
return jwt.refreshTokens(refreshToken);
|
|
191
|
-
},
|
|
192
|
-
middleware: authMw,
|
|
193
|
-
};
|
|
194
|
-
// Decorate server with auth service
|
|
195
|
-
server.decorate('auth', authService);
|
|
196
|
-
// Add preHandler hook for session loading (using adapter)
|
|
197
|
-
if (config.autoExtract !== false) {
|
|
198
|
-
server.addHook('preHandler', async (request) => {
|
|
199
|
-
const session = await adapter.getSession(request);
|
|
200
|
-
if (session) {
|
|
201
|
-
const user = {
|
|
202
|
-
id: session.user.id,
|
|
203
|
-
email: session.user.email,
|
|
204
|
-
...(session.user.emailVerified !== undefined && {
|
|
205
|
-
emailVerified: session.user.emailVerified,
|
|
206
|
-
}),
|
|
207
|
-
...session.user.providerData,
|
|
208
|
-
};
|
|
209
|
-
const authContext = {
|
|
210
|
-
authMode: 'adapter',
|
|
211
|
-
isAuthenticated: true,
|
|
212
|
-
user,
|
|
213
|
-
providerId: 'jwt',
|
|
214
|
-
session: session.session.providerData,
|
|
215
|
-
};
|
|
216
|
-
request.auth = authContext;
|
|
217
|
-
request.user = user;
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
169
|
// Add shutdown hook for cleanup
|
|
223
170
|
server.addHook('onClose', async () => {
|
|
224
171
|
if (debug) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veloxts/auth",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.91",
|
|
4
4
|
"description": "Authentication and authorization system for VeloxTS framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@fastify/cookie": "11.0.2",
|
|
63
|
-
"fastify": "5.
|
|
64
|
-
"@veloxts/core": "0.6.
|
|
65
|
-
"@veloxts/router": "0.6.
|
|
63
|
+
"fastify": "5.7.2",
|
|
64
|
+
"@veloxts/core": "0.6.91",
|
|
65
|
+
"@veloxts/router": "0.6.91"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"argon2": ">=0.30.0",
|
|
@@ -82,12 +82,12 @@
|
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@types/bcrypt": "6.0.0",
|
|
85
|
-
"@vitest/coverage-v8": "4.0.
|
|
85
|
+
"@vitest/coverage-v8": "4.0.18",
|
|
86
86
|
"fastify-plugin": "5.1.0",
|
|
87
87
|
"typescript": "5.9.3",
|
|
88
|
-
"vitest": "4.0.
|
|
89
|
-
"@veloxts/
|
|
90
|
-
"@veloxts/
|
|
88
|
+
"vitest": "4.0.18",
|
|
89
|
+
"@veloxts/validation": "0.6.91",
|
|
90
|
+
"@veloxts/testing": "0.6.91"
|
|
91
91
|
},
|
|
92
92
|
"keywords": [
|
|
93
93
|
"velox",
|