@venizia/ignis-docs 0.0.5 → 0.0.6-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/package.json +1 -1
- package/wiki/best-practices/architectural-patterns.md +0 -2
- package/wiki/best-practices/architecture-decisions.md +0 -8
- package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
- package/wiki/best-practices/code-style-standards/index.md +0 -1
- package/wiki/best-practices/code-style-standards/tooling.md +0 -3
- package/wiki/best-practices/contribution-workflow.md +12 -12
- package/wiki/best-practices/index.md +4 -14
- package/wiki/best-practices/performance-optimization.md +3 -3
- package/wiki/best-practices/security-guidelines.md +2 -2
- package/wiki/best-practices/troubleshooting-tips.md +1 -1
- package/wiki/guides/core-concepts/application/bootstrapping.md +6 -7
- package/wiki/guides/core-concepts/components-guide.md +1 -1
- package/wiki/guides/core-concepts/components.md +2 -2
- package/wiki/guides/core-concepts/dependency-injection.md +4 -5
- package/wiki/guides/core-concepts/persistent/datasources.md +4 -5
- package/wiki/guides/core-concepts/services.md +1 -1
- package/wiki/guides/get-started/5-minute-quickstart.md +4 -5
- package/wiki/guides/get-started/philosophy.md +12 -24
- package/wiki/guides/index.md +2 -9
- package/wiki/guides/reference/mcp-docs-server.md +13 -13
- package/wiki/guides/tutorials/building-a-crud-api.md +10 -10
- package/wiki/guides/tutorials/complete-installation.md +11 -12
- package/wiki/guides/tutorials/ecommerce-api.md +3 -3
- package/wiki/guides/tutorials/realtime-chat.md +6 -6
- package/wiki/guides/tutorials/testing.md +4 -5
- package/wiki/index.md +8 -14
- package/wiki/references/base/bootstrapping.md +0 -3
- package/wiki/references/base/components.md +2 -2
- package/wiki/references/base/controllers.md +0 -1
- package/wiki/references/base/datasources.md +1 -1
- package/wiki/references/base/dependency-injection.md +2 -2
- package/wiki/references/base/filter-system/default-filter.md +2 -3
- package/wiki/references/base/filter-system/index.md +1 -1
- package/wiki/references/base/filter-system/quick-reference.md +0 -14
- package/wiki/references/base/middlewares.md +0 -8
- package/wiki/references/base/providers.md +0 -9
- package/wiki/references/base/repositories/advanced.md +1 -1
- package/wiki/references/base/repositories/mixins.md +2 -3
- package/wiki/references/base/services.md +0 -1
- package/wiki/references/components/authentication/api.md +444 -0
- package/wiki/references/components/authentication/errors.md +177 -0
- package/wiki/references/components/authentication/index.md +571 -0
- package/wiki/references/components/authentication/usage.md +781 -0
- package/wiki/references/components/health-check.md +292 -103
- package/wiki/references/components/index.md +14 -12
- package/wiki/references/components/mail/api.md +505 -0
- package/wiki/references/components/mail/errors.md +176 -0
- package/wiki/references/components/mail/index.md +535 -0
- package/wiki/references/components/mail/usage.md +404 -0
- package/wiki/references/components/request-tracker.md +229 -25
- package/wiki/references/components/socket-io/api.md +1051 -0
- package/wiki/references/components/socket-io/errors.md +119 -0
- package/wiki/references/components/socket-io/index.md +410 -0
- package/wiki/references/components/socket-io/usage.md +322 -0
- package/wiki/references/components/static-asset/api.md +261 -0
- package/wiki/references/components/static-asset/errors.md +89 -0
- package/wiki/references/components/static-asset/index.md +617 -0
- package/wiki/references/components/static-asset/usage.md +364 -0
- package/wiki/references/components/swagger.md +390 -110
- package/wiki/references/components/template/api-page.md +125 -0
- package/wiki/references/components/template/errors-page.md +100 -0
- package/wiki/references/components/template/index.md +104 -0
- package/wiki/references/components/template/setup-page.md +134 -0
- package/wiki/references/components/template/single-page.md +132 -0
- package/wiki/references/components/template/usage-page.md +127 -0
- package/wiki/references/components/websocket/api.md +508 -0
- package/wiki/references/components/websocket/errors.md +123 -0
- package/wiki/references/components/websocket/index.md +453 -0
- package/wiki/references/components/websocket/usage.md +475 -0
- package/wiki/references/helpers/cron/index.md +224 -0
- package/wiki/references/helpers/crypto/index.md +537 -0
- package/wiki/references/helpers/env/index.md +214 -0
- package/wiki/references/helpers/error/index.md +232 -0
- package/wiki/references/helpers/index.md +16 -15
- package/wiki/references/helpers/inversion/index.md +608 -0
- package/wiki/references/helpers/logger/index.md +600 -0
- package/wiki/references/helpers/network/api.md +986 -0
- package/wiki/references/helpers/network/index.md +620 -0
- package/wiki/references/helpers/queue/index.md +589 -0
- package/wiki/references/helpers/redis/index.md +495 -0
- package/wiki/references/helpers/socket-io/api.md +497 -0
- package/wiki/references/helpers/socket-io/index.md +513 -0
- package/wiki/references/helpers/storage/api.md +705 -0
- package/wiki/references/helpers/storage/index.md +583 -0
- package/wiki/references/helpers/template/index.md +66 -0
- package/wiki/references/helpers/template/single-page.md +126 -0
- package/wiki/references/helpers/testing/index.md +510 -0
- package/wiki/references/helpers/types/index.md +512 -0
- package/wiki/references/helpers/uid/index.md +272 -0
- package/wiki/references/helpers/websocket/api.md +736 -0
- package/wiki/references/helpers/websocket/index.md +574 -0
- package/wiki/references/helpers/worker-thread/index.md +470 -0
- package/wiki/references/index.md +2 -9
- package/wiki/references/quick-reference.md +3 -18
- package/wiki/references/utilities/jsx.md +1 -8
- package/wiki/references/utilities/statuses.md +0 -7
- package/wiki/references/components/authentication.md +0 -476
- package/wiki/references/components/mail.md +0 -687
- package/wiki/references/components/socket-io.md +0 -562
- package/wiki/references/components/static-asset.md +0 -1277
- package/wiki/references/helpers/cron.md +0 -108
- package/wiki/references/helpers/crypto.md +0 -132
- package/wiki/references/helpers/env.md +0 -83
- package/wiki/references/helpers/error.md +0 -97
- package/wiki/references/helpers/inversion.md +0 -176
- package/wiki/references/helpers/logger.md +0 -296
- package/wiki/references/helpers/network.md +0 -396
- package/wiki/references/helpers/queue.md +0 -150
- package/wiki/references/helpers/redis.md +0 -142
- package/wiki/references/helpers/socket-io.md +0 -932
- package/wiki/references/helpers/storage.md +0 -665
- package/wiki/references/helpers/testing.md +0 -133
- package/wiki/references/helpers/types.md +0 -167
- package/wiki/references/helpers/uid.md +0 -167
- package/wiki/references/helpers/worker-thread.md +0 -178
- package/wiki/references/src-details/boot.md +0 -379
- package/wiki/references/src-details/core.md +0 -263
- package/wiki/references/src-details/dev-configs.md +0 -298
- package/wiki/references/src-details/docs.md +0 -71
- package/wiki/references/src-details/helpers.md +0 -211
- package/wiki/references/src-details/index.md +0 -86
- package/wiki/references/src-details/inversion.md +0 -340
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
# Authentication -- Setup & Configuration
|
|
2
|
+
|
|
3
|
+
> JWT and Basic HTTP authentication with AES-encrypted payloads, multi-strategy support, and built-in auth controller
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
| Item | Value |
|
|
8
|
+
|------|-------|
|
|
9
|
+
| **Package** | `@venizia/ignis` |
|
|
10
|
+
| **Class** | `AuthenticateComponent` |
|
|
11
|
+
| **Runtimes** | Both |
|
|
12
|
+
|
|
13
|
+
### Key Components
|
|
14
|
+
|
|
15
|
+
| Component | Purpose |
|
|
16
|
+
|-----------|---------|
|
|
17
|
+
| **AuthenticateComponent** | Main component registering auth services and controllers |
|
|
18
|
+
| **AuthenticationStrategyRegistry** | Singleton managing available auth strategies |
|
|
19
|
+
| **JWTAuthenticationStrategy** | JWT verification using `JWTTokenService` |
|
|
20
|
+
| **BasicAuthenticationStrategy** | Basic HTTP authentication using `BasicTokenService` |
|
|
21
|
+
| **JWTTokenService** | Generate, verify, encrypt/decrypt JWT tokens |
|
|
22
|
+
| **BasicTokenService** | Extract and verify Basic auth credentials |
|
|
23
|
+
| **IAuthService** | Interface for custom auth implementation (sign-in, sign-up) |
|
|
24
|
+
| **defineAuthController** | Factory function for creating custom auth controllers |
|
|
25
|
+
| **authenticate** | Standalone function wrapping `AuthenticationStrategyRegistry.getInstance().authenticate()` |
|
|
26
|
+
|
|
27
|
+
### Environment Variables
|
|
28
|
+
|
|
29
|
+
| Variable | Purpose | Required |
|
|
30
|
+
|----------|---------|----------|
|
|
31
|
+
| `APP_ENV_APPLICATION_SECRET` | Encrypt JWT payload | Required for JWT |
|
|
32
|
+
| `APP_ENV_JWT_SECRET` | Sign and verify JWT signature | Required for JWT |
|
|
33
|
+
| `APP_ENV_JWT_EXPIRES_IN` | Token expiration (seconds) | Optional |
|
|
34
|
+
|
|
35
|
+
### Auth Modes
|
|
36
|
+
|
|
37
|
+
| Mode | Behavior |
|
|
38
|
+
|------|----------|
|
|
39
|
+
| `'any'` | First successful strategy wins (fallback mode) |
|
|
40
|
+
| `'all'` | All strategies must pass (MFA mode) |
|
|
41
|
+
|
|
42
|
+
### Token Types
|
|
43
|
+
|
|
44
|
+
| Constant | Value | Description |
|
|
45
|
+
|----------|-------|-------------|
|
|
46
|
+
| `AuthenticationTokenTypes.TYPE_AUTHORIZATION_CODE` | `'000_AUTHORIZATION_CODE'` | Authorization code grant type |
|
|
47
|
+
| `AuthenticationTokenTypes.TYPE_ACCESS_TOKEN` | `'100_ACCESS_TOKEN'` | Access token type |
|
|
48
|
+
| `AuthenticationTokenTypes.TYPE_REFRESH_TOKEN` | `'200_REFRESH_TOKEN'` | Refresh token type |
|
|
49
|
+
|
|
50
|
+
### Authentication Constants
|
|
51
|
+
|
|
52
|
+
| Constant | Value | Description |
|
|
53
|
+
|----------|-------|-------------|
|
|
54
|
+
| `Authentication.ACCESS_TOKEN_SECRET` | `'token.secret'` | Default access token secret key |
|
|
55
|
+
| `Authentication.ACCESS_TOKEN_EXPIRES_IN` | `86400` | Default access token expiration (seconds, 24h) |
|
|
56
|
+
| `Authentication.REFRESH_TOKEN_SECRET` | `'refresh.secret'` | Default refresh token secret key |
|
|
57
|
+
| `Authentication.REFRESH_TOKEN_EXPIRES_IN` | `86400` | Default refresh token expiration (seconds, 24h) |
|
|
58
|
+
| `Authentication.AUTHENTICATION_STRATEGY` | `'authentication.strategy'` | Namespace prefix for strategy binding keys |
|
|
59
|
+
| `Authentication.STRATEGY_JWT` | `'jwt'` | JWT strategy name |
|
|
60
|
+
| `Authentication.STRATEGY_BASIC` | `'basic'` | Basic strategy name |
|
|
61
|
+
| `Authentication.TYPE_BEARER` | `'Bearer'` | Bearer token type prefix |
|
|
62
|
+
| `Authentication.TYPE_BASIC` | `'Basic'` | Basic token type prefix |
|
|
63
|
+
| `Authentication.SKIP_AUTHENTICATION` | `'authentication.skip'` | Context key to dynamically skip auth |
|
|
64
|
+
| `Authentication.CURRENT_USER` | `'auth.current.user'` | Context key for the authenticated user payload |
|
|
65
|
+
| `Authentication.AUDIT_USER_ID` | `'audit.user.id'` | Context key for the authenticated user ID |
|
|
66
|
+
|
|
67
|
+
#### Import Paths
|
|
68
|
+
```typescript
|
|
69
|
+
import {
|
|
70
|
+
AuthenticateComponent,
|
|
71
|
+
AuthenticateBindingKeys,
|
|
72
|
+
Authentication,
|
|
73
|
+
AuthenticationModes,
|
|
74
|
+
AuthenticationTokenTypes,
|
|
75
|
+
AuthenticationStrategyRegistry,
|
|
76
|
+
JWTAuthenticationStrategy,
|
|
77
|
+
BasicAuthenticationStrategy,
|
|
78
|
+
JWTTokenService,
|
|
79
|
+
BasicTokenService,
|
|
80
|
+
defineAuthController,
|
|
81
|
+
authenticate,
|
|
82
|
+
} from '@venizia/ignis';
|
|
83
|
+
|
|
84
|
+
import type {
|
|
85
|
+
TAuthenticationRestOptions,
|
|
86
|
+
IJWTTokenServiceOptions,
|
|
87
|
+
IBasicTokenServiceOptions,
|
|
88
|
+
IAuthenticateOptions,
|
|
89
|
+
IAuthUser,
|
|
90
|
+
IJWTTokenPayload,
|
|
91
|
+
IAuthService,
|
|
92
|
+
IAuthenticationStrategy,
|
|
93
|
+
TDefineAuthControllerOpts,
|
|
94
|
+
TAuthStrategy,
|
|
95
|
+
TAuthMode,
|
|
96
|
+
TGetTokenExpiresFn,
|
|
97
|
+
} from '@venizia/ignis';
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Entity Column Helper Imports
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import {
|
|
104
|
+
extraUserColumns,
|
|
105
|
+
extraRoleColumns,
|
|
106
|
+
extraPermissionColumns,
|
|
107
|
+
extraPermissionMappingColumns,
|
|
108
|
+
extraUserRoleColumns,
|
|
109
|
+
} from '@venizia/ignis';
|
|
110
|
+
|
|
111
|
+
import type {
|
|
112
|
+
TPermissionOptions,
|
|
113
|
+
TPermissionCommonColumns,
|
|
114
|
+
TPermissionMappingOptions,
|
|
115
|
+
TPermissionMappingCommonColumns,
|
|
116
|
+
TUserRoleOptions,
|
|
117
|
+
TUserRoleCommonColumns,
|
|
118
|
+
} from '@venizia/ignis';
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Status and Type Imports
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import {
|
|
125
|
+
UserStatuses,
|
|
126
|
+
UserTypes,
|
|
127
|
+
RoleStatuses,
|
|
128
|
+
} from '@venizia/ignis';
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Setup
|
|
132
|
+
|
|
133
|
+
### Step 1: Bind Configuration
|
|
134
|
+
|
|
135
|
+
Bind at least one of `JWT_OPTIONS` or `BASIC_OPTIONS` in your application's `preConfigure()`.
|
|
136
|
+
|
|
137
|
+
### JWT Only (Primary Setup)
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import {
|
|
141
|
+
AuthenticateBindingKeys,
|
|
142
|
+
IJWTTokenServiceOptions,
|
|
143
|
+
} from '@venizia/ignis';
|
|
144
|
+
|
|
145
|
+
// Bind JWT options
|
|
146
|
+
this.bind<IJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS }).toValue({
|
|
147
|
+
applicationSecret: process.env.APP_ENV_APPLICATION_SECRET,
|
|
148
|
+
jwtSecret: process.env.APP_ENV_JWT_SECRET,
|
|
149
|
+
getTokenExpiresFn: () => Number(process.env.APP_ENV_JWT_EXPIRES_IN || 86400),
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Example `.env` file:**
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
APP_ENV_APPLICATION_SECRET=your-strong-application-secret
|
|
157
|
+
APP_ENV_JWT_SECRET=your-strong-jwt-secret
|
|
158
|
+
APP_ENV_JWT_EXPIRES_IN=86400
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Basic Auth Only (Alternative Setup)
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import {
|
|
165
|
+
AuthenticateBindingKeys,
|
|
166
|
+
IBasicTokenServiceOptions,
|
|
167
|
+
} from '@venizia/ignis';
|
|
168
|
+
|
|
169
|
+
// Bind Basic auth options
|
|
170
|
+
this.bind<IBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS }).toValue({
|
|
171
|
+
verifyCredentials: async (opts) => {
|
|
172
|
+
const { credentials, context } = opts;
|
|
173
|
+
const user = await userRepo.findByUsername(credentials.username);
|
|
174
|
+
if (user && await bcrypt.compare(credentials.password, user.passwordHash)) {
|
|
175
|
+
return { userId: user.id, roles: user.roles };
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Combined JWT + Basic with Auth Controller (Full Setup)
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import {
|
|
186
|
+
AuthenticateBindingKeys,
|
|
187
|
+
IJWTTokenServiceOptions,
|
|
188
|
+
IBasicTokenServiceOptions,
|
|
189
|
+
TAuthenticationRestOptions,
|
|
190
|
+
} from '@venizia/ignis';
|
|
191
|
+
|
|
192
|
+
// Bind REST options (enables auth controller)
|
|
193
|
+
this.bind<TAuthenticationRestOptions>({ key: AuthenticateBindingKeys.REST_OPTIONS }).toValue({
|
|
194
|
+
useAuthController: true,
|
|
195
|
+
controllerOpts: {
|
|
196
|
+
restPath: '/auth',
|
|
197
|
+
payload: {
|
|
198
|
+
signIn: {
|
|
199
|
+
request: { schema: SignInRequestSchema },
|
|
200
|
+
response: { schema: SignInResponseSchema },
|
|
201
|
+
},
|
|
202
|
+
signUp: {
|
|
203
|
+
request: { schema: SignUpRequestSchema },
|
|
204
|
+
response: { schema: SignUpResponseSchema },
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Bind JWT options
|
|
211
|
+
this.bind<IJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS }).toValue({
|
|
212
|
+
applicationSecret: process.env.APP_ENV_APPLICATION_SECRET,
|
|
213
|
+
jwtSecret: process.env.APP_ENV_JWT_SECRET,
|
|
214
|
+
getTokenExpiresFn: () => Number(process.env.APP_ENV_JWT_EXPIRES_IN || 86400),
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Bind Basic auth options
|
|
218
|
+
this.bind<IBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS }).toValue({
|
|
219
|
+
verifyCredentials: async (opts) => {
|
|
220
|
+
const authenticateService = this.get<AuthenticationService>({
|
|
221
|
+
key: BindingKeys.build({
|
|
222
|
+
namespace: BindingNamespaces.SERVICE,
|
|
223
|
+
key: AuthenticationService.name,
|
|
224
|
+
}),
|
|
225
|
+
});
|
|
226
|
+
return authenticateService.signIn(opts.context, {
|
|
227
|
+
identifier: { scheme: 'username', value: opts.credentials.username },
|
|
228
|
+
credential: { scheme: 'basic', value: opts.credentials.password },
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Step 2: Register Component
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import {
|
|
238
|
+
AuthenticateComponent,
|
|
239
|
+
Authentication,
|
|
240
|
+
AuthenticationStrategyRegistry,
|
|
241
|
+
JWTAuthenticationStrategy,
|
|
242
|
+
BasicAuthenticationStrategy,
|
|
243
|
+
BaseApplication,
|
|
244
|
+
ValueOrPromise,
|
|
245
|
+
} from '@venizia/ignis';
|
|
246
|
+
|
|
247
|
+
export class Application extends BaseApplication {
|
|
248
|
+
preConfigure(): ValueOrPromise<void> {
|
|
249
|
+
// Register your auth service (if using auth controller)
|
|
250
|
+
this.service(AuthenticationService);
|
|
251
|
+
|
|
252
|
+
// Step 1 bindings here...
|
|
253
|
+
|
|
254
|
+
// Register component
|
|
255
|
+
this.component(AuthenticateComponent);
|
|
256
|
+
|
|
257
|
+
// Register strategies
|
|
258
|
+
AuthenticationStrategyRegistry.getInstance().register({
|
|
259
|
+
container: this,
|
|
260
|
+
strategies: [
|
|
261
|
+
{ name: Authentication.STRATEGY_JWT, strategy: JWTAuthenticationStrategy },
|
|
262
|
+
{ name: Authentication.STRATEGY_BASIC, strategy: BasicAuthenticationStrategy },
|
|
263
|
+
],
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
> [!NOTE]
|
|
270
|
+
> Only register the strategies you need. JWT-only setups can omit `BasicAuthenticationStrategy` and vice versa.
|
|
271
|
+
|
|
272
|
+
## Configuration
|
|
273
|
+
|
|
274
|
+
### JWT Options
|
|
275
|
+
|
|
276
|
+
| Option | Type | Default | Description |
|
|
277
|
+
|--------|------|---------|-------------|
|
|
278
|
+
| `jwtSecret` | `string` | -- | Secret for signing and verifying JWT signature |
|
|
279
|
+
| `applicationSecret` | `string` | -- | Secret for AES-encrypting JWT payload fields |
|
|
280
|
+
| `getTokenExpiresFn` | `() => ValueOrPromise<number>` | -- | Function returning token expiration in seconds |
|
|
281
|
+
| `aesAlgorithm` | `AESAlgorithmType` | `'aes-256-cbc'` | AES algorithm for payload encryption |
|
|
282
|
+
| `headerAlgorithm` | `string` | `'HS256'` | JWT signing algorithm |
|
|
283
|
+
|
|
284
|
+
> [!WARNING]
|
|
285
|
+
> Both `applicationSecret` and `jwtSecret` are mandatory when using JWT authentication. They must be strong, unique secret values. The component will throw an error if either is missing or set to `'unknown_secret'`. Additionally, the error message from `defineJWTAuth` **includes the actual provided secret value** in the error output (e.g., <code v-pre>[defineJWTAuth] Invalid jwtSecret | Provided: {{jwtSecret}}</code>), so ensure these errors are never exposed to end users.
|
|
286
|
+
|
|
287
|
+
> [!NOTE]
|
|
288
|
+
> The `getTokenExpiresFn` is called on every token generation, not just once. This allows dynamic expiration (e.g., shorter tokens for mobile, longer for admin).
|
|
289
|
+
|
|
290
|
+
**Example `.env` file:**
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
APP_ENV_APPLICATION_SECRET=your-strong-application-secret
|
|
294
|
+
APP_ENV_JWT_SECRET=your-strong-jwt-secret
|
|
295
|
+
APP_ENV_JWT_EXPIRES_IN=86400
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### IJWTTokenServiceOptions -- Full Interface
|
|
299
|
+
```typescript
|
|
300
|
+
interface IJWTTokenServiceOptions {
|
|
301
|
+
jwtSecret: string;
|
|
302
|
+
applicationSecret: string;
|
|
303
|
+
getTokenExpiresFn: () => ValueOrPromise<number>;
|
|
304
|
+
aesAlgorithm?: AESAlgorithmType;
|
|
305
|
+
headerAlgorithm?: string;
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Basic Auth Options
|
|
310
|
+
|
|
311
|
+
| Option | Type | Default | Description |
|
|
312
|
+
|--------|------|---------|-------------|
|
|
313
|
+
| `verifyCredentials` | `(opts: { credentials, context }) => Promise<IAuthUser \| null>` | -- | Callback to verify Basic auth credentials |
|
|
314
|
+
|
|
315
|
+
The `verifyCredentials` function receives an options object:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
type TBasicAuthVerifyFn<E extends Env = Env> = (opts: {
|
|
319
|
+
credentials: { username: string; password: string };
|
|
320
|
+
context: TContext<E, string>;
|
|
321
|
+
}) => Promise<IAuthUser | null>;
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### IBasicTokenServiceOptions -- Full Interface
|
|
325
|
+
```typescript
|
|
326
|
+
interface IBasicTokenServiceOptions<E extends Env = Env> {
|
|
327
|
+
verifyCredentials: (opts: {
|
|
328
|
+
credentials: { username: string; password: string };
|
|
329
|
+
context: TContext<E, string>;
|
|
330
|
+
}) => Promise<IAuthUser | null>;
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### REST Options
|
|
335
|
+
|
|
336
|
+
| Option | Type | Default | Description |
|
|
337
|
+
|--------|------|---------|-------------|
|
|
338
|
+
| `useAuthController` | `boolean` | `false` | Enable/disable built-in auth controller |
|
|
339
|
+
| `controllerOpts` | `TDefineAuthControllerOpts` | -- | Configuration for built-in auth controller (required when `useAuthController` is `true`) |
|
|
340
|
+
|
|
341
|
+
`TAuthenticationRestOptions` is a discriminated union type:
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
type TAuthenticationRestOptions = {} & (
|
|
345
|
+
| { useAuthController?: false | undefined }
|
|
346
|
+
| {
|
|
347
|
+
useAuthController: true;
|
|
348
|
+
controllerOpts: TDefineAuthControllerOpts;
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
> [!IMPORTANT]
|
|
354
|
+
> When `useAuthController` is `true`, the `controllerOpts` field becomes required. The discriminated union enforces this at the type level -- you cannot set `useAuthController: true` without providing `controllerOpts`.
|
|
355
|
+
|
|
356
|
+
### Controller Options
|
|
357
|
+
|
|
358
|
+
| Option | Type | Default | Description |
|
|
359
|
+
|--------|------|---------|-------------|
|
|
360
|
+
| `restPath` | `string` | `'/auth'` | Base path for auth endpoints |
|
|
361
|
+
| `serviceKey` | `string` | `'services.AuthenticationService'` | DI key for the auth service |
|
|
362
|
+
| `requireAuthenticatedSignUp` | `boolean` | `false` | Whether sign-up requires JWT authentication |
|
|
363
|
+
| `payload` | `object` | `{}` | Custom Zod schemas for request/response payloads |
|
|
364
|
+
|
|
365
|
+
#### TDefineAuthControllerOpts -- Full Interface
|
|
366
|
+
```typescript
|
|
367
|
+
type TDefineAuthControllerOpts = {
|
|
368
|
+
restPath?: string;
|
|
369
|
+
serviceKey?: string;
|
|
370
|
+
requireAuthenticatedSignUp?: boolean;
|
|
371
|
+
payload?: {
|
|
372
|
+
signIn?: {
|
|
373
|
+
request: { schema: TAnyObjectSchema };
|
|
374
|
+
response: { schema: TAnyObjectSchema };
|
|
375
|
+
};
|
|
376
|
+
signUp?: {
|
|
377
|
+
request: { schema: TAnyObjectSchema };
|
|
378
|
+
response: { schema: TAnyObjectSchema };
|
|
379
|
+
};
|
|
380
|
+
changePassword?: {
|
|
381
|
+
request: { schema?: TAnyObjectSchema };
|
|
382
|
+
response: { schema: TAnyObjectSchema };
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
};
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Route Configuration Options
|
|
389
|
+
|
|
390
|
+
These options are used in route configs to control per-route authentication:
|
|
391
|
+
|
|
392
|
+
| Option | Type | Default | Description |
|
|
393
|
+
|--------|------|---------|-------------|
|
|
394
|
+
| `authStrategies` | `TAuthStrategy[]` | -- | Array of strategy names (e.g., `['jwt']`, `['jwt', 'basic']`) |
|
|
395
|
+
| `authMode` | `'any' \| 'all'` | `'any'` | How to handle multiple strategies |
|
|
396
|
+
| `skipAuth` | `boolean` | `false` | Skip authentication for this route |
|
|
397
|
+
|
|
398
|
+
### IAuthUser Interface
|
|
399
|
+
|
|
400
|
+
The base authenticated user type returned by strategies and available on the context:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
interface IAuthUser {
|
|
404
|
+
userId: IdType;
|
|
405
|
+
[extra: string | symbol]: any;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
> [!TIP]
|
|
410
|
+
> `IAuthUser` is intentionally minimal. Your `IAuthService` implementation can extend the user payload with additional fields (roles, email, provider, etc.) -- these extra fields will be preserved through JWT token generation and available after authentication via `Authentication.CURRENT_USER`.
|
|
411
|
+
|
|
412
|
+
### SignInRequestSchema Field Constraints
|
|
413
|
+
|
|
414
|
+
The built-in `SignInRequestSchema` enforces the following validation constraints on sign-in request payloads:
|
|
415
|
+
|
|
416
|
+
| Field | Type | Constraints |
|
|
417
|
+
|-------|------|-------------|
|
|
418
|
+
| `identifier.scheme` | `string` | Non-empty, min 4 chars (required) |
|
|
419
|
+
| `identifier.value` | `string` | Non-empty, min 8 chars (required) |
|
|
420
|
+
| `credential.scheme` | `string` | Non-empty (required) |
|
|
421
|
+
| `credential.value` | `string` | Non-empty, min 8 chars (required) |
|
|
422
|
+
| `clientId` | `string` | Optional |
|
|
423
|
+
|
|
424
|
+
### SignUpRequestSchema Field Constraints
|
|
425
|
+
|
|
426
|
+
The built-in `SignUpRequestSchema` uses a **flat structure** (not nested like `SignInRequestSchema`):
|
|
427
|
+
|
|
428
|
+
| Field | Type | Constraints |
|
|
429
|
+
|-------|------|-------------|
|
|
430
|
+
| `username` | `string` | Non-empty, min 8 chars (required) |
|
|
431
|
+
| `credential` | `string` | Non-empty, min 8 chars (required) |
|
|
432
|
+
|
|
433
|
+
### ChangePasswordRequestSchema Field Constraints
|
|
434
|
+
|
|
435
|
+
The built-in `ChangePasswordRequestSchema` uses scheme-based credential naming:
|
|
436
|
+
|
|
437
|
+
| Field | Type | Constraints |
|
|
438
|
+
|-------|------|-------------|
|
|
439
|
+
| `scheme` | `string` | Required |
|
|
440
|
+
| `oldCredential` | `string` | Non-empty, min 8 chars (required) |
|
|
441
|
+
| `newCredential` | `string` | Non-empty, min 8 chars (required) |
|
|
442
|
+
| `userId` | `string \| number` | Required |
|
|
443
|
+
|
|
444
|
+
#### IAuthService -- Full Interface
|
|
445
|
+
```typescript
|
|
446
|
+
interface IAuthService<
|
|
447
|
+
E extends Env = Env,
|
|
448
|
+
SIRQ extends TSignInRequest = TSignInRequest,
|
|
449
|
+
SIRS = AnyObject,
|
|
450
|
+
SURQ extends TSignUpRequest = TSignUpRequest,
|
|
451
|
+
SURS = AnyObject,
|
|
452
|
+
CPRQ extends TChangePasswordRequest = TChangePasswordRequest,
|
|
453
|
+
CPRS = AnyObject,
|
|
454
|
+
UIRQ = AnyObject,
|
|
455
|
+
UIRS = AnyObject,
|
|
456
|
+
> {
|
|
457
|
+
signIn(context: TContext<E>, opts: SIRQ): Promise<SIRS>;
|
|
458
|
+
signUp(context: TContext<E>, opts: SURQ): Promise<SURS>;
|
|
459
|
+
changePassword(context: TContext<E>, opts: CPRQ): Promise<CPRS>;
|
|
460
|
+
getUserInformation?(context: TContext<E>, opts: UIRQ): Promise<UIRS>;
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
> [!NOTE]
|
|
465
|
+
> `IAuthService` is generic on the Hono `Env` type as well as all request/response types. The `getUserInformation` method is optional.
|
|
466
|
+
|
|
467
|
+
#### IJWTTokenPayload -- Full Interface
|
|
468
|
+
```typescript
|
|
469
|
+
interface IJWTTokenPayload extends JWTPayload, IAuthUser {
|
|
470
|
+
userId: IdType;
|
|
471
|
+
roles: { id: IdType; identifier: string; priority: number }[];
|
|
472
|
+
clientId?: string;
|
|
473
|
+
provider?: string;
|
|
474
|
+
email?: string;
|
|
475
|
+
name?: string;
|
|
476
|
+
[extra: string | symbol]: any;
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Binding Keys
|
|
481
|
+
|
|
482
|
+
| Key | Constant | Type | Required | Default |
|
|
483
|
+
|-----|----------|------|----------|---------|
|
|
484
|
+
| `@app/authenticate/rest-options` | `AuthenticateBindingKeys.REST_OPTIONS` | `TAuthenticationRestOptions` | No | <code v-pre>{ useAuthController: false }</code> |
|
|
485
|
+
| `@app/authenticate/jwt-options` | `AuthenticateBindingKeys.JWT_OPTIONS` | `IJWTTokenServiceOptions` | Conditional | -- |
|
|
486
|
+
| `@app/authenticate/basic-options` | `AuthenticateBindingKeys.BASIC_OPTIONS` | `IBasicTokenServiceOptions` | Conditional | -- |
|
|
487
|
+
|
|
488
|
+
> [!IMPORTANT]
|
|
489
|
+
> At least one of `JWT_OPTIONS` or `BASIC_OPTIONS` must be bound. If neither is configured, the component will throw an error during `binding()`.
|
|
490
|
+
|
|
491
|
+
### Context Variables
|
|
492
|
+
|
|
493
|
+
These values are set on the Hono `Context` during authentication and can be accessed via `context.get()`:
|
|
494
|
+
|
|
495
|
+
| Key | Constant | Type | Description |
|
|
496
|
+
|-----|----------|------|-------------|
|
|
497
|
+
| `auth.current.user` | `Authentication.CURRENT_USER` | `IAuthUser` | Authenticated user payload |
|
|
498
|
+
| `audit.user.id` | `Authentication.AUDIT_USER_ID` | `IdType` | Authenticated user's ID |
|
|
499
|
+
| `authentication.skip` | `Authentication.SKIP_AUTHENTICATION` | `boolean` | Dynamically skip auth |
|
|
500
|
+
|
|
501
|
+
### Strategy Constants
|
|
502
|
+
|
|
503
|
+
| Constant | Value | Description |
|
|
504
|
+
|----------|-------|-------------|
|
|
505
|
+
| `Authentication.STRATEGY_JWT` | `'jwt'` | JWT strategy name |
|
|
506
|
+
| `Authentication.STRATEGY_BASIC` | `'basic'` | Basic strategy name |
|
|
507
|
+
| `Authentication.TYPE_BEARER` | `'Bearer'` | Bearer token type |
|
|
508
|
+
| `Authentication.TYPE_BASIC` | `'Basic'` | Basic token type |
|
|
509
|
+
|
|
510
|
+
### AuthenticateStrategy Class
|
|
511
|
+
|
|
512
|
+
Utility class for validating strategy names:
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
class AuthenticateStrategy {
|
|
516
|
+
static readonly BASIC = 'basic';
|
|
517
|
+
static readonly JWT = 'jwt';
|
|
518
|
+
static readonly SCHEME_SET: Set<string>;
|
|
519
|
+
static isValid(input: string): boolean;
|
|
520
|
+
}
|
|
521
|
+
type TAuthStrategy = TConstValue<typeof AuthenticateStrategy>;
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
| Member | Type | Description |
|
|
525
|
+
|--------|------|-------------|
|
|
526
|
+
| `BASIC` | `string` | Constant for basic strategy name |
|
|
527
|
+
| `JWT` | `string` | Constant for JWT strategy name |
|
|
528
|
+
| `SCHEME_SET` | `Set<string>` | Set containing all valid strategy names |
|
|
529
|
+
| `isValid(input)` | `(input: string) => boolean` | Returns `true` if the input is a recognized strategy name |
|
|
530
|
+
|
|
531
|
+
### AuthenticationModes Class
|
|
532
|
+
|
|
533
|
+
Utility class for validating authentication modes:
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
class AuthenticationModes {
|
|
537
|
+
static readonly ANY = 'any';
|
|
538
|
+
static readonly ALL = 'all';
|
|
539
|
+
}
|
|
540
|
+
type TAuthMode = TConstValue<typeof AuthenticationModes>;
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
| Member | Type | Description |
|
|
544
|
+
|--------|------|-------------|
|
|
545
|
+
| `ANY` | `string` | First successful strategy wins (fallback) |
|
|
546
|
+
| `ALL` | `string` | All strategies must pass (MFA) |
|
|
547
|
+
|
|
548
|
+
## See Also
|
|
549
|
+
|
|
550
|
+
- [Usage & Examples](./usage) -- Securing routes, auth flows, and API endpoints
|
|
551
|
+
- [API Reference](./api) -- Architecture, service internals, and strategy registry
|
|
552
|
+
- [Error Reference](./errors) -- Error messages and troubleshooting
|
|
553
|
+
|
|
554
|
+
- **Guides:**
|
|
555
|
+
- [Components Overview](/guides/core-concepts/components) -- Component system basics
|
|
556
|
+
- [Controllers](/guides/core-concepts/controllers) -- Protecting routes with auth
|
|
557
|
+
|
|
558
|
+
- **Components:**
|
|
559
|
+
- [All Components](../index) -- Built-in components list
|
|
560
|
+
|
|
561
|
+
- **Helpers:**
|
|
562
|
+
- [Crypto Helper](/references/helpers/crypto/) -- Password hashing utilities
|
|
563
|
+
|
|
564
|
+
- **References:**
|
|
565
|
+
- [Middlewares](/references/base/middlewares) -- Custom authentication middleware
|
|
566
|
+
|
|
567
|
+
- **Best Practices:**
|
|
568
|
+
- [Security Guidelines](/best-practices/security-guidelines) -- Authentication best practices
|
|
569
|
+
|
|
570
|
+
- **Tutorials:**
|
|
571
|
+
- [Building a CRUD API](/guides/tutorials/building-a-crud-api) -- Adding authentication
|