@venizia/ignis-docs 0.2.0 → 0.2.1-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.
Files changed (174) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +24 -13
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +27 -3
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +8 -4
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +247 -153
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +109 -323
  26. package/content/extensions/components/authentication/api.md +489 -602
  27. package/content/extensions/components/authentication/errors.md +135 -498
  28. package/content/extensions/components/authentication/index.md +89 -801
  29. package/content/extensions/components/authentication/usage.md +231 -955
  30. package/content/extensions/components/authorization/api.md +991 -644
  31. package/content/extensions/components/authorization/errors.md +204 -208
  32. package/content/extensions/components/authorization/getting-started.md +227 -0
  33. package/content/extensions/components/authorization/index.md +88 -795
  34. package/content/extensions/components/authorization/usage.md +219 -528
  35. package/content/extensions/components/health-check.md +77 -243
  36. package/content/extensions/components/index.md +24 -90
  37. package/content/extensions/components/mail/api.md +553 -285
  38. package/content/extensions/components/mail/errors.md +76 -62
  39. package/content/extensions/components/mail/index.md +111 -463
  40. package/content/extensions/components/mail/usage.md +139 -173
  41. package/content/extensions/components/request-tracker.md +70 -173
  42. package/content/extensions/components/socket-io/api.md +462 -785
  43. package/content/extensions/components/socket-io/errors.md +49 -51
  44. package/content/extensions/components/socket-io/index.md +69 -372
  45. package/content/extensions/components/socket-io/usage.md +212 -105
  46. package/content/extensions/components/static-asset/api.md +461 -141
  47. package/content/extensions/components/static-asset/errors.md +121 -53
  48. package/content/extensions/components/static-asset/index.md +84 -606
  49. package/content/extensions/components/static-asset/usage.md +184 -299
  50. package/content/extensions/components/template/index.md +3 -3
  51. package/content/extensions/components/websocket/api.md +311 -404
  52. package/content/extensions/components/websocket/errors.md +47 -56
  53. package/content/extensions/components/websocket/index.md +75 -407
  54. package/content/extensions/components/websocket/usage.md +120 -338
  55. package/content/extensions/helpers/cron/index.md +52 -160
  56. package/content/extensions/helpers/crypto/index.md +67 -480
  57. package/content/extensions/helpers/crypto/reference.md +528 -0
  58. package/content/extensions/helpers/env/index.md +64 -178
  59. package/content/extensions/helpers/error/index.md +286 -196
  60. package/content/extensions/helpers/index.md +61 -47
  61. package/content/extensions/helpers/inversion/index.md +76 -550
  62. package/content/extensions/helpers/inversion/reference.md +530 -0
  63. package/content/extensions/helpers/kafka/admin.md +23 -3
  64. package/content/extensions/helpers/kafka/compile-binary.md +83 -52
  65. package/content/extensions/helpers/kafka/consumer.md +65 -28
  66. package/content/extensions/helpers/kafka/examples.md +46 -253
  67. package/content/extensions/helpers/kafka/index.md +55 -617
  68. package/content/extensions/helpers/kafka/producer.md +156 -22
  69. package/content/extensions/helpers/kafka/schema-registry.md +59 -79
  70. package/content/extensions/helpers/logger/hf-logger.md +220 -0
  71. package/content/extensions/helpers/logger/index.md +78 -552
  72. package/content/extensions/helpers/logger/pino.md +105 -0
  73. package/content/extensions/helpers/logger/reference.md +937 -0
  74. package/content/extensions/helpers/network/api.md +276 -195
  75. package/content/extensions/helpers/network/index.md +87 -524
  76. package/content/extensions/helpers/queue/index.md +80 -897
  77. package/content/extensions/helpers/queue/reference.md +494 -0
  78. package/content/extensions/helpers/redis/index.md +86 -640
  79. package/content/extensions/helpers/redis/reference.md +784 -0
  80. package/content/extensions/helpers/secrets/index.md +136 -0
  81. package/content/extensions/helpers/socket-io/api.md +325 -204
  82. package/content/extensions/helpers/socket-io/index.md +79 -429
  83. package/content/extensions/helpers/storage/api.md +584 -464
  84. package/content/extensions/helpers/storage/index.md +80 -573
  85. package/content/extensions/helpers/types/index.md +75 -495
  86. package/content/extensions/helpers/types/reference.md +689 -0
  87. package/content/extensions/helpers/uid/index.md +176 -189
  88. package/content/extensions/helpers/websocket/api.md +366 -214
  89. package/content/extensions/helpers/websocket/index.md +68 -503
  90. package/content/extensions/helpers/worker-thread/index.md +62 -396
  91. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  92. package/content/extensions/index.md +38 -39
  93. package/content/extensions/src-details/mcp-server.md +96 -548
  94. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  95. package/content/guides/core-concepts/persistent/index.md +5 -1
  96. package/content/guides/core-concepts/persistent/models.md +1 -1
  97. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  98. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  99. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  100. package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
  101. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  102. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  103. package/content/guides/core-concepts/secrets-vault.md +177 -0
  104. package/content/guides/core-concepts/services.md +1 -1
  105. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  106. package/content/guides/get-started/philosophy.md +135 -670
  107. package/content/guides/get-started/setup.md +53 -74
  108. package/content/guides/migrations/redis-helpers-migration.md +5 -4
  109. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  110. package/content/guides/migrations/unified-connectors-migration.md +8 -7
  111. package/content/guides/tutorials/ecommerce-api.md +3 -8
  112. package/content/guides/tutorials/realtime-chat.md +1 -1
  113. package/content/references/base/application.md +64 -22
  114. package/content/references/base/components.md +3 -3
  115. package/content/references/base/connectors.md +79 -136
  116. package/content/references/base/controllers.md +12 -12
  117. package/content/references/base/datasources-reference.md +600 -0
  118. package/content/references/base/datasources.md +84 -444
  119. package/content/references/base/dependency-injection.md +25 -46
  120. package/content/references/base/filter-system/application-usage.md +95 -123
  121. package/content/references/base/filter-system/array-operators.md +33 -43
  122. package/content/references/base/filter-system/comparison-operators.md +55 -63
  123. package/content/references/base/filter-system/default-filter.md +144 -350
  124. package/content/references/base/filter-system/fields-order-pagination.md +116 -148
  125. package/content/references/base/filter-system/index.md +114 -253
  126. package/content/references/base/filter-system/json-filtering.md +52 -181
  127. package/content/references/base/filter-system/list-operators.md +28 -44
  128. package/content/references/base/filter-system/logical-operators.md +69 -114
  129. package/content/references/base/filter-system/null-operators.md +41 -98
  130. package/content/references/base/filter-system/pattern-matching.md +48 -51
  131. package/content/references/base/filter-system/quick-reference.md +93 -196
  132. package/content/references/base/filter-system/range-operators.md +22 -38
  133. package/content/references/base/filter-system/tips.md +70 -133
  134. package/content/references/base/filter-system/use-cases.md +173 -232
  135. package/content/references/base/grpc-controllers.md +53 -17
  136. package/content/references/base/index.md +5 -3
  137. package/content/references/base/middlewares.md +43 -28
  138. package/content/references/base/models-reference.md +886 -0
  139. package/content/references/base/models.md +81 -1452
  140. package/content/references/base/providers.md +8 -8
  141. package/content/references/base/repositories/advanced.md +281 -419
  142. package/content/references/base/repositories/index.md +84 -644
  143. package/content/references/base/repositories/mixins.md +25 -21
  144. package/content/references/base/repositories/relations.md +194 -375
  145. package/content/references/base/repositories/soft-deletable.md +67 -55
  146. package/content/references/base/secrets.md +267 -0
  147. package/content/references/base/services.md +8 -6
  148. package/content/references/configuration/environment-variables.md +73 -21
  149. package/content/references/configuration/index.md +51 -31
  150. package/content/references/index.md +1 -1
  151. package/content/references/quick-reference.md +3 -16
  152. package/content/references/utilities/crypto.md +35 -76
  153. package/content/references/utilities/date.md +33 -73
  154. package/content/references/utilities/duration.md +85 -0
  155. package/content/references/utilities/index.md +6 -2
  156. package/content/references/utilities/jsx-reference.md +298 -0
  157. package/content/references/utilities/jsx.md +82 -525
  158. package/content/references/utilities/module.md +81 -61
  159. package/content/references/utilities/parse.md +34 -64
  160. package/content/references/utilities/performance.md +33 -58
  161. package/content/references/utilities/promise.md +28 -62
  162. package/content/references/utilities/request.md +58 -218
  163. package/content/references/utilities/retry.md +139 -0
  164. package/content/references/utilities/schema.md +43 -137
  165. package/content/references/utilities/statuses-reference.md +361 -0
  166. package/content/references/utilities/statuses.md +63 -667
  167. package/dist/mcp-server/index.js +0 -0
  168. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  169. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  171. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  172. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  173. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  174. package/package.json +24 -23
@@ -1,8 +1,31 @@
1
- # Authentication -- Error Reference
1
+ ---
2
+ title: Authentication Errors
3
+ description: Every error the Authentication component throws, organized by source, with cause and fix
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Authentication Errors
2
8
 
3
- > Complete error messages and troubleshooting for the authentication module. See [Setup & Configuration](./) for initial setup.
9
+ Every error message the Authentication component and its services throw, with cause and fix. See the [Overview](./) for initial setup.
4
10
 
5
- ## Error Flow Overview
11
+ ## Find what you need
12
+
13
+ | Error is thrown by | Go to |
14
+ |---|---|
15
+ | Startup, while wiring the component | [AuthenticateComponent (startup)](#authenticatecomponent-startup) |
16
+ | `verify`/`generate`/`extractCredentials`, shared by JWS, JWKS, and Basic | [Bearer token services (runtime)](#bearer-token-services-runtime) |
17
+ | The `JWSTokenService` constructor | [JWSTokenService (constructor)](#jwstokenservice-constructor) |
18
+ | `JWKSIssuerTokenService` init or key parsing | [JWKSIssuerTokenService (init + runtime)](#jwksissuertokenservice-init-runtime) |
19
+ | `JWKSVerifierTokenService` signing calls | [JWKSVerifierTokenService (runtime)](#jwksverifiertokenservice-runtime) |
20
+ | Basic auth credential decoding | [BasicTokenService (runtime)](#basictokenservice-runtime) |
21
+ | "Descriptor not found" or a strategy registration issue | [AuthenticationStrategyRegistry (startup + runtime)](#authenticationstrategyregistry-startup-runtime) |
22
+ | "Authentication failed" at request time | [AuthenticationProvider (runtime)](#authenticationprovider-runtime) |
23
+ | The built-in `/auth` controller | [Auth controller factory](#auth-controller-factory) |
24
+
25
+ - **Startup errors (400 unless noted)** come from `AuthenticateComponent.binding()` and stop the application before it serves traffic.
26
+ - **Runtime errors (401)** come from request-time credential extraction, verification, or strategy exhaustion.
27
+ - **Structural errors (500)** come from calling an unsupported operation - signing on a verify-only service, for example - or accessing uninitialized state.
28
+ - All of them go through `getError()`. It defaults `statusCode` to `400` when you don't set one - so every "startup" error below is a 400 unless the table says otherwise.
6
29
 
7
30
  ```mermaid
8
31
  flowchart LR
@@ -10,512 +33,170 @@ flowchart LR
10
33
  MW --> SKIP{"Skip auth?"}
11
34
  SKIP -->|"Yes"| PASS["Pass through"]
12
35
  SKIP -->|"No"| EXTRACT["Extract credentials"]
13
- EXTRACT -->|"Missing header"| E401A["401 Missing header"]
14
- EXTRACT -->|"Wrong scheme"| E401B["401 Invalid scheme"]
15
- EXTRACT -->|"Bad format"| E401C["401 Invalid format"]
16
- EXTRACT -->|"OK"| VERIFY["Verify token"]
17
- VERIFY -->|"Expired/invalid"| E401D["401 Invalid token"]
36
+ EXTRACT -->|"Missing/wrong/malformed"| E401["401"]
37
+ EXTRACT -->|"OK"| VERIFY["Verify token / credentials"]
38
+ VERIFY -->|"Invalid/expired"| E401
18
39
  VERIFY -->|"Valid"| USER["Set CURRENT_USER"]
19
40
  USER --> NEXT["Next middleware"]
20
41
 
21
- style E401A fill:#f8d7da,stroke:#dc3545
22
- style E401B fill:#f8d7da,stroke:#dc3545
23
- style E401C fill:#f8d7da,stroke:#dc3545
24
- style E401D fill:#f8d7da,stroke:#dc3545
42
+ style E401 fill:#f8d7da,stroke:#dc3545
25
43
  style PASS fill:#d4edda,stroke:#28a745
26
44
  style NEXT fill:#d4edda,stroke:#28a745
27
45
  ```
28
46
 
29
- ## Complete Error Reference
47
+ ## AuthenticateComponent (startup)
30
48
 
31
- All error messages from the authentication module, organized by source.
49
+ Thrown during `binding()` while validating options and wiring services.
32
50
 
33
- ---
51
+ | Message | Status | Cause | Fix |
52
+ |---------|--------|-------|-----|
53
+ | `[AuthenticateComponent] At least one of jwtOptions or basicOptions must be provided` | 400 | Neither `JWT_OPTIONS` nor `BASIC_OPTIONS` bound before `this.component(AuthenticateComponent)` | Bind at least one before registering the component - see [Setup](./#common-tasks) |
54
+ | `[AuthenticateComponent] Unknown JOSE standard: {standard}` | 400 | `jwtOptions.standard` is not `'JWS'` or `'JWKS'` | Use `JOSEStandards.JWS` or `JOSEStandards.JWKS` |
55
+ | `[defineJWSAuth] Invalid jwtSecret \| Provided: {jwtSecret}` | 400 | `jwtSecret` falsy or equals placeholder `'unknown_secret'` | Set a real secret - `APP_ENV_JWT_SECRET`, for example |
56
+ | `[defineJWSAuth] getTokenExpiresFn is required` | 400 | `getTokenExpiresFn` missing from JWS options | Provide `() => Number(process.env.APP_ENV_JWT_EXPIRES_IN \|\| 86400)` |
57
+ | `[defineJWKSAuth] keys.private and keys.public are required for issuer mode` | 400 | Issuer mode missing one or both keys | Provide `keys.private` and `keys.public` |
58
+ | `[defineJWKSAuth] keys.format is required and must be one of: pem, jwk` | 400 | `keys.format` missing or invalid | Use `JWKSKeyFormats.PEM` or `JWKSKeyFormats.JWK` |
59
+ | `[defineJWKSAuth] kid is required for issuer mode` | 400 | `kid` (Key ID) not provided | Provide a unique `kid` string |
60
+ | `[defineJWKSAuth] getTokenExpiresFn is required for issuer mode` | 400 | `getTokenExpiresFn` missing | Provide a token-expiry function |
61
+ | `[defineJWKSAuth] jwksUrl is required for verifier mode` | 400 | Verifier mode missing `jwksUrl` | Provide the issuer's `/certs` URL |
62
+ | `[defineJWKSAuth] Invalid JWKS mode: {mode}` | 400 | `mode` is not `'issuer'` or `'verifier'` | Use `JWKSModes.ISSUER` or `JWKSModes.VERIFIER` |
63
+ | `[defineBasicAuth] verifyCredentials function is required` | 400 | `BASIC_OPTIONS` bound without a `verifyCredentials` callback | Provide the callback - see [Setup](./#common-tasks) |
64
+ | `[defineControllers] Auth controller requires jwtOptions to be configured` | 400 | `useAuthController: true` but no `jwtOptions` bound | Bind `JWT_OPTIONS` before enabling the auth controller |
34
65
 
35
- ### Component Errors (`AuthenticateComponent`)
66
+ > [!NOTE]
67
+ > `applicationSecret` is optional and not validated. Every token service treats it as optional - omitting it disables AES payload encryption, nothing more. Its presence is never checked.
36
68
 
37
- Thrown during `binding()` when validating options and configuring services.
69
+ ## Bearer token services (runtime)
38
70
 
39
- | Error Message | Status | Method | When |
40
- |---------------|--------|--------|------|
41
- | `[AuthenticateComponent] At least one of jwtOptions or basicOptions must be provided` | 400 | `binding` | Neither `JWT_OPTIONS` nor `BASIC_OPTIONS` bound in DI container |
42
- | <code v-pre>[AuthenticateComponent] Unknown JOSE standard: {{standard}}</code> | 400 | `binding` | `jwtOptions.standard` is not `'JWS'` or `'JWKS'` |
71
+ Shared by `JWSTokenService`, `JWKSIssuerTokenService`, and `JWKSVerifierTokenService` via `AbstractBearerTokenService`.
43
72
 
44
- #### `defineJWSAuth` Errors
73
+ | Message | Status | Method | Cause | Fix |
74
+ |---------|--------|--------|-------|-----|
75
+ | `Unauthorized user! Missing authorization header` | 401 | `extractCredentials` | No `Authorization` header | Send `Authorization: Bearer <token>` |
76
+ | `Unauthorized user! Invalid schema of request token!` | 401 | `extractCredentials` | Header doesn't start with `Bearer` | Use the `Bearer` scheme |
77
+ | `Authorization header value is invalid format. It must follow the pattern: 'Bearer xx.yy.zz' ...` | 401 | `extractCredentials` | Header doesn't split into exactly 2 parts | Check for extra whitespace or a malformed token |
78
+ | `[verify] Invalid request token!` | 401 | `verify` | Token value is empty | Ensure the token half of the header isn't blank |
79
+ | `[verify] Invalid or expired token` | 401 | `verify` | `doVerify()` threw - expired, malformed, or bad signature | Check application logs for the real cause (see below) |
80
+ | `[generate] Invalid token payload!` | 401 | `generate` | Payload is null/undefined | Pass a non-null `IJWTTokenPayload` |
81
+ | `[generate] Failed to generate token` | 500 | `generate` | Signing failed (key/algorithm issue) | Check application logs for the real cause |
45
82
 
46
- | Error Message | Status | Method | When |
47
- |---------------|--------|--------|------|
48
- | <code v-pre>[defineJWSAuth] Invalid jwtSecret &#124; Provided: {{jwtSecret}}</code> | 400 | `defineJWSAuth` | `jwtSecret` is falsy or equals `'unknown_secret'` |
49
- | `[defineJWSAuth] getTokenExpiresFn is required` | 400 | `defineJWSAuth` | `getTokenExpiresFn` not provided in JWS options |
83
+ > [!TIP]
84
+ > Errors are sanitized on the wire. `verify()` and `generate()` never leak the original `error.message` to the client. The full error is logged at `error` level - run `grep "Failed to verify token" logs/application.log` to find it.
50
85
 
51
- ::: info applicationSecret is no longer validated
52
- `applicationSecret` was previously required and validated by the component. It is now **optional** - omitting it simply disables AES payload encryption.
53
- :::
86
+ ## JWSTokenService (constructor)
54
87
 
55
- #### `defineJWKSAuth` Errors (Issuer Mode)
88
+ | Message | Status | Cause | Fix |
89
+ |---------|--------|-------|-----|
90
+ | `[JWSTokenService] Invalid jwtSecret` | 500 | `jwtSecret` falsy in injected options | Fix the `JWT_OPTIONS` binding |
91
+ | `[JWSTokenService] Invalid getTokenExpiresFn` | 500 | `getTokenExpiresFn` falsy in injected options | Fix the `JWT_OPTIONS` binding |
92
+ | `[getSigningKey] Invalid jwtSecret!` | 400 | `jwtSecret` Uint8Array is null | Should not happen after constructor validation - report if seen |
56
93
 
57
- | Error Message | Status | Method | When |
58
- |---------------|--------|--------|------|
59
- | `[defineJWKSAuth] keys.private and keys.public are required for issuer mode` | 400 | `defineJWKSAuth` | `keys.private` or `keys.public` missing |
60
- | <code v-pre>[defineJWKSAuth] keys.format is required and must be one of: pem, jwk</code> | 400 | `defineJWKSAuth` | `keys.format` missing or not in `JWKSKeyFormats.SCHEME_SET` |
61
- | `[defineJWKSAuth] kid is required for issuer mode` | 400 | `defineJWKSAuth` | `kid` (Key ID) not provided |
62
- | `[defineJWKSAuth] getTokenExpiresFn is required for issuer mode` | 400 | `defineJWKSAuth` | `getTokenExpiresFn` not provided |
94
+ ## JWKSIssuerTokenService (init + runtime)
63
95
 
64
- #### `defineJWKSAuth` Errors (Verifier Mode)
96
+ | Message | Status | Method | Cause | Fix |
97
+ |---------|--------|--------|-------|-----|
98
+ | `[JWKSIssuerTokenService] Unknown key driver: {driver}` | 500 | `resolveKeyContent` | `keys.driver` not `'text'` or `'file'` | Use `JWKSKeyDrivers.TEXT` or `.FILE` |
99
+ | `[JWKSIssuerTokenService] Invalid raw.priv key!` | 500 | `parseKeyMaterial` | Resolved private key content is empty | Check the file path or inline string |
100
+ | `[JWKSIssuerTokenService] Invalid raw.pub key!` | 500 | `parseKeyMaterial` | Resolved public key content is empty | Check the file path or inline string |
101
+ | `[JWKSIssuerTokenService] Invalid JWK key material` | 500 | `parseKeyMaterial` | JWK JSON parse or `importJWK()` failed | Validate the JWK is well-formed JSON (see below) |
102
+ | `[JWKSIssuerTokenService] Unknown key format: {format}` | 500 | `parseKeyMaterial` | `keys.format` not `'pem'` or `'jwk'` | Use `JWKSKeyFormats.PEM` or `.JWK` |
103
+ | `[getSigningKey] Invalid privateKey!` | 400 | `getSigningKey` | Private key null - init incomplete or failed | Ensure `initialize()` succeeded; check logs |
104
+ | `[JWKSIssuerTokenService] JWKS not initialized yet. Call getJWKSAsync() instead.` | 500 | `getJWKS` | Sync `getJWKS()` called before lazy init completed | Use `await getJWKSAsync()` instead |
65
105
 
66
- | Error Message | Status | Method | When |
67
- |---------------|--------|--------|------|
68
- | `[defineJWKSAuth] jwksUrl is required for verifier mode` | 400 | `defineJWKSAuth` | `jwksUrl` not provided for verifier mode |
106
+ > [!WARNING]
107
+ > File read errors are not wrapped. With `JWKSKeyDrivers.FILE`, `readFile()` errors (`ENOENT`, `EACCES`, ...) surface as raw Node.js filesystem errors during initialization - they are not caught and re-thrown as `getError()`.
69
108
 
70
- #### `defineJWKSAuth` Errors (General)
109
+ ## JWKSVerifierTokenService (runtime)
71
110
 
72
- | Error Message | Status | Method | When |
73
- |---------------|--------|--------|------|
74
- | <code v-pre>[defineJWKSAuth] Invalid JWKS mode: {{mode}}</code> | 400 | `defineJWKSAuth` | `mode` is not `'issuer'` or `'verifier'` |
111
+ | Message | Status | Method | Cause |
112
+ |---------|--------|--------|-------|
113
+ | `[JWKSVerifierTokenService] Verifier mode cannot sign tokens` | 500 | `getSigner` | `generate()` called on a verify-only service |
114
+ | `[JWKSVerifierTokenService] Verifier mode cannot sign tokens` | 500 | `getSigningKey` | Signing key accessed on a verify-only service |
115
+ | `[JWKSVerifierTokenService] Verifier mode has no token expiry` | 500 | `getDefaultTokenExpiresFn` | Token expiry accessed on a verify-only service |
75
116
 
76
- #### `defineBasicAuth` Errors
77
-
78
- | Error Message | Status | Method | When |
79
- |---------------|--------|--------|------|
80
- | `[defineBasicAuth] verifyCredentials function is required` | 400 | `defineBasicAuth` | `BASIC_OPTIONS` bound without a `verifyCredentials` callback |
81
-
82
- #### `defineControllers` Errors
83
-
84
- | Error Message | Status | Method | When |
85
- |---------------|--------|--------|------|
86
- | `[defineControllers] Auth controller requires jwtOptions to be configured` | 400 | `defineControllers` | `useAuthController: true` but no `jwtOptions` provided |
87
-
88
- ---
117
+ **Fix:** token generation must happen on the **issuer** service. If one application needs both signing and verification, use `JWKSModes.ISSUER` everywhere - an issuer can both sign and verify.
89
118
 
90
- ### Bearer Token Service Errors (`AbstractBearerTokenService`)
91
-
92
- Base class errors shared by `JWSTokenService`, `JWKSIssuerTokenService`, and `JWKSVerifierTokenService`.
93
-
94
- #### `extractCredentials` Errors
95
-
96
- | Error Message | Status | Method | When |
97
- |---------------|--------|--------|------|
98
- | `Unauthorized user! Missing authorization header` | 401 | `extractCredentials` | Request has no `Authorization` header |
99
- | `Unauthorized user! Invalid schema of request token!` | 401 | `extractCredentials` | `Authorization` header doesn't start with `Bearer` |
100
- | <code v-pre>Authorization header value is invalid format. It must follow the pattern: 'Bearer xx.yy.zz' where xx.yy.zz is a valid JWT token.</code> | 401 | `extractCredentials` | `Authorization` header doesn't have exactly 2 parts (type + token) |
101
-
102
- #### `verify` Errors
103
-
104
- | Error Message | Status | Method | When |
105
- |---------------|--------|--------|------|
106
- | `[verify] Invalid request token!` | 401 | `verify` | Token value is empty/falsy |
107
- | `[verify] Invalid or expired token` | 401 | `verify` | `doVerify()` threw - token is expired, malformed, or signature invalid |
108
-
109
- ::: tip Sanitized error messages
110
- The `verify()` and `generate()` methods use **sanitized error messages** - they do NOT include the original `error.message` in the thrown error. The full error is logged at `error` level for debugging but not exposed to clients.
111
- :::
112
-
113
- #### `generate` Errors
114
-
115
- | Error Message | Status | Method | When |
116
- |---------------|--------|--------|------|
117
- | `[generate] Invalid token payload!` | 401 | `generate` | Payload is null/undefined |
118
- | `[generate] Failed to generate token` | 500 | `generate` | Signing failed (key issue, algorithm mismatch, etc.) |
119
-
120
- ---
121
-
122
- ### JWS Token Service Errors (`JWSTokenService`)
123
-
124
- Constructor validation errors thrown during DI resolution.
125
-
126
- | Error Message | Status | Method | When |
127
- |---------------|--------|--------|------|
128
- | `[JWSTokenService] Invalid jwtSecret` | 500 | `constructor` | `jwtSecret` is falsy in injected `IJWSTokenServiceOptions` |
129
- | `[JWSTokenService] Invalid getTokenExpiresFn` | 500 | `constructor` | `getTokenExpiresFn` is falsy in injected options |
130
- | `[getSigningKey] Invalid jwtSecret!` | 400 | `getSigningKey` | `jwtSecret` Uint8Array is null (should not happen after constructor validation) |
131
-
132
- ::: info applicationSecret no longer validated
133
- `JWSTokenService` no longer validates `applicationSecret` in its constructor. If not provided, AES payload encryption is simply disabled.
134
- :::
135
-
136
- ---
137
-
138
- ### JWKS Issuer Token Service Errors (`JWKSIssuerTokenService`)
139
-
140
- Errors thrown during lazy initialization (`ensureInitialized()`) and key operations.
141
-
142
- #### Initialization Errors
143
-
144
- | Error Message | Status | Method | When |
145
- |---------------|--------|--------|------|
146
- | <code v-pre>[JWKSIssuerTokenService] Unknown key driver: {{driver}}</code> | 500 | `resolveKeyContent` | `keys.driver` is not `'text'` or `'file'` |
147
- | `[JWKSIssuerTokenService] Invalid raw.priv key!` | 500 | `parseKeyMaterial` | Resolved private key content is empty |
148
- | `[JWKSIssuerTokenService] Invalid raw.pub key!` | 500 | `parseKeyMaterial` | Resolved public key content is empty |
149
- | `[JWKSIssuerTokenService] Invalid JWK key material` | 500 | `parseKeyMaterial` | JWK JSON parsing or `importJWK()` failed (PEM format works, JWK content is invalid) |
150
- | <code v-pre>[JWKSIssuerTokenService] Unknown key format: {{format}}</code> | 500 | `parseKeyMaterial` | `keys.format` is not `'pem'` or `'jwk'` |
151
-
152
- ::: warning File read errors
153
- When using `JWKSKeyDrivers.FILE`, file read errors from `readFile()` propagate as Node.js filesystem errors (e.g., `ENOENT`, `EACCES`). These are **not** wrapped - the raw error surfaces during initialization.
154
- :::
155
-
156
- #### Runtime Errors
157
-
158
- | Error Message | Status | Method | When |
159
- |---------------|--------|--------|------|
160
- | `[getSigningKey] Invalid privateKey!` | 400 | `getSigningKey` | Private key is null (initialization incomplete or failed) |
161
- | `[JWKSIssuerTokenService] JWKS not initialized yet. Call getJWKSAsync() instead.` | 500 | `getJWKS` | Sync `getJWKS()` called before lazy init completed |
162
-
163
- ---
164
-
165
- ### JWKS Verifier Token Service Errors (`JWKSVerifierTokenService`)
166
-
167
- | Error Message | Status | Method | When |
168
- |---------------|--------|--------|------|
169
- | `[JWKSVerifierTokenService] Verifier mode cannot sign tokens` | 500 | `getSigner` | Attempt to call `generate()` on a verify-only service |
170
- | `[JWKSVerifierTokenService] Verifier mode cannot sign tokens` | 500 | `getSigningKey` | Attempt to access signing key on a verify-only service |
171
- | `[JWKSVerifierTokenService] Verifier mode has no token expiry` | 500 | `getDefaultTokenExpiresFn` | Attempt to access token expiry on a verify-only service |
172
-
173
- ::: tip Verifier mode is read-only
174
- `JWKSVerifierTokenService` **cannot** generate tokens. Calling `generate()` throws because both `getSigner()` and `getSigningKey()` throw. Only `verify()` and `extractCredentials()` are functional.
175
- :::
176
-
177
- ---
119
+ ## BasicTokenService (runtime)
178
120
 
179
- ### Basic Token Service Errors (`BasicTokenService`)
121
+ | Message | Status | Method | Cause | Fix |
122
+ |---------|--------|--------|-------|-----|
123
+ | `[BasicTokenService] Invalid verifyCredentials function` | 500 | `constructor` | `verifyCredentials` missing from injected options | Provide the callback in `BASIC_OPTIONS` |
124
+ | `Unauthorized! Missing authorization header` | 401 | `extractCredentials` | No `Authorization` header | Send `Authorization: Basic <base64>` |
125
+ | `Unauthorized! Invalid authorization schema, expected Basic` | 401 | `extractCredentials` | Header doesn't start with `Basic` | Use the `Basic` scheme |
126
+ | `Unauthorized! Invalid authorization header format` | 401 | `extractCredentials` | Header doesn't split into exactly 2 parts | Check the header value |
127
+ | `Unauthorized! Invalid base64 credentials format` | 401 | `extractCredentials` | Base64 decode failed, or no `:` separator, or empty username | Verify the client encodes `username:password` correctly |
128
+ | `Unauthorized! Invalid username or password` | 401 | `verify` | `verifyCredentials` callback returned `null` | Expected on wrong credentials - check your callback's lookup logic if unexpected |
180
129
 
181
- | Error Message | Status | Method | When |
182
- |---------------|--------|--------|------|
183
- | `[BasicTokenService] Invalid verifyCredentials function` | 500 | `constructor` | `verifyCredentials` not provided in injected `TBasicTokenServiceOptions` |
184
- | `Unauthorized! Missing authorization header` | 401 | `extractCredentials` | Request has no `Authorization` header |
185
- | `Unauthorized! Invalid authorization schema, expected Basic` | 401 | `extractCredentials` | `Authorization` header doesn't start with `Basic` |
186
- | `Unauthorized! Invalid authorization header format` | 401 | `extractCredentials` | Header doesn't have exactly 2 parts (`Basic` + base64 value) |
187
- | `Unauthorized! Invalid base64 credentials format` | 401 | `extractCredentials` | Base64 decoding failed, no colon separator, or empty username |
188
- | `Unauthorized! Invalid username or password` | 401 | `verify` | `verifyCredentials` callback returned null/falsy |
189
-
190
- ---
191
-
192
- ### Strategy Registry Errors (`AuthenticationStrategyRegistry`)
130
+ ## AuthenticationStrategyRegistry (startup + runtime)
193
131
 
194
132
  Inherited from `AbstractAuthRegistry`.
195
133
 
196
- | Error Message | Status | Method | When |
197
- |---------------|--------|--------|------|
198
- | <code v-pre>[getKey] Invalid name &#124; name: {{name}}</code> | 400 | `getKey` | Strategy name is empty or falsy |
199
- | <code v-pre>[AuthenticationStrategyRegistry] No items registered</code> | 400 | `getDefaultName` | No strategies have been registered |
200
- | <code v-pre>[AuthenticationStrategyRegistry] Descriptor not found: {{name}}</code> | 400 | `resolveDescriptor` | Strategy with given name is not registered |
201
- | <code v-pre>[AuthenticationStrategyRegistry] Failed to resolve: {{name}}</code> | 400 | `resolveDescriptor` | Strategy registered but DI container returned null |
202
-
203
- ---
204
-
205
- ### Authentication Provider Errors (`AuthenticationProvider`)
206
-
207
- The middleware that executes strategies in the configured mode.
208
-
209
- | Error Message | Status | Method | When |
210
- |---------------|--------|--------|------|
211
- | <code v-pre>Authentication failed. Tried strategies: {{strategies}}</code> | 401 | `executeAnyMode` | All strategies failed in `'any'` mode - each strategy threw during `authenticate()` |
212
- | `Failed to identify authenticated user!` | 401 | `executeAllMode` | All strategies succeeded in `'all'` mode but the first strategy's `authUser.userId` is falsy |
213
- | <code v-pre>Invalid authentication mode &#124; mode: {{mode}}</code> | 500 | `createAuthenticateMiddleware` | `mode` is not `'any'` or `'all'` |
214
-
215
- ---
216
-
217
- ### Auth Controller Factory Errors
218
-
219
- | Error Message | Status | Method | When |
220
- |---------------|--------|--------|------|
221
- | `[AuthController] Failed to init auth controller \| Invalid injectable authentication service!` | 400 | `constructor` | DI could not resolve the authentication service (service key not bound) |
222
-
223
- ---
134
+ | Message | Status | Method | Cause | Fix |
135
+ |---------|--------|--------|-------|-----|
136
+ | `[getKey] Invalid name \| name: {name}` | 400 | `getKey` | Strategy name empty or falsy | Pass a non-empty strategy name |
137
+ | `[AuthenticationStrategyRegistry] No items registered` | 400 | `getDefaultName` | No strategies registered yet | Register at least one strategy |
138
+ | `[AuthenticationStrategyRegistry] Descriptor not found: {name}` | 400 | `resolveDescriptor` | Route references a strategy name that was never registered | Register it after the component - see below |
139
+ | `[AuthenticationStrategyRegistry] Failed to resolve: {name}` | 400 | `resolveDescriptor` | Strategy registered but the container returned null | Check the strategy's own constructor dependencies |
224
140
 
225
- ## Troubleshooting
226
-
227
- ### "[AuthenticateComponent] At least one of jwtOptions or basicOptions must be provided"
228
-
229
- **Cause:** The component requires at least one authentication method. Neither `JWT_OPTIONS` nor `BASIC_OPTIONS` was bound before calling `this.component(AuthenticateComponent)`.
230
-
231
- **Fix:** Bind at least one set of options before registering the component:
141
+ **Fix for "Descriptor not found":** strategies are **not** auto-registered by `AuthenticateComponent`.
232
142
 
233
143
  ```typescript
234
- // Option A: JWS (symmetric JWT)
235
- this.bind<TJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS }).toValue({
236
- standard: JOSEStandards.JWS,
237
- options: {
238
- jwtSecret: env.get('JWT_SECRET'),
239
- getTokenExpiresFn: () => 86_400,
240
- },
241
- });
242
-
243
- // Option B: JWKS Issuer (asymmetric JWT)
244
- this.bind<TJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS }).toValue({
245
- standard: JOSEStandards.JWKS,
246
- options: {
247
- mode: JWKSModes.ISSUER,
248
- algorithm: 'RS256',
249
- kid: 'my-key-1',
250
- keys: { driver: JWKSKeyDrivers.FILE, format: JWKSKeyFormats.PEM, private: './keys/private.pem', public: './keys/public.pem' },
251
- getTokenExpiresFn: () => 86_400,
252
- },
253
- });
254
-
255
- // Then register the component
256
144
  this.component(AuthenticateComponent);
257
- ```
258
-
259
- ### "[defineJWSAuth] Invalid jwtSecret"
260
-
261
- **Cause:** `jwtSecret` is missing, empty, or set to the default placeholder `'unknown_secret'`. The component validates this during `defineJWSAuth()`.
262
-
263
- **Fix:** Set a strong, unique JWT secret:
264
-
265
- ```bash
266
- # .env
267
- JWT_SECRET=your-strong-jwt-secret-at-least-32-chars
268
- ```
269
-
270
- ```typescript
271
- this.bind<TJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS }).toValue({
272
- standard: JOSEStandards.JWS,
273
- options: {
274
- jwtSecret: env.get('JWT_SECRET'),
275
- getTokenExpiresFn: () => 86_400,
276
- },
277
- });
278
- ```
279
-
280
- ### "[defineJWSAuth] getTokenExpiresFn is required"
281
-
282
- **Cause:** `getTokenExpiresFn` was not provided in the JWS options.
283
-
284
- **Fix:** Include a function that returns the token expiry time in seconds:
285
-
286
- ```typescript
287
- options: {
288
- jwtSecret: env.get('JWT_SECRET'),
289
- getTokenExpiresFn: () => Number(env.get('JWT_EXPIRES_IN') || 86_400),
290
- }
291
- ```
292
-
293
- ### "[defineJWKSAuth] keys.private and keys.public are required for issuer mode"
294
-
295
- **Cause:** JWKS issuer mode requires both a private key (for signing) and a public key (for the `/certs` JWKS endpoint). One or both were not provided.
296
145
 
297
- **Fix:** Provide both keys in the options:
298
-
299
- ```typescript
300
- options: {
301
- mode: JWKSModes.ISSUER,
302
- algorithm: 'RS256',
303
- kid: 'my-key-1',
304
- keys: {
305
- driver: JWKSKeyDrivers.FILE,
306
- format: JWKSKeyFormats.PEM,
307
- private: './keys/private.pem',
308
- public: './keys/public.pem',
309
- },
310
- getTokenExpiresFn: () => 86_400,
311
- }
312
- ```
313
-
314
- ### "[defineJWKSAuth] keys.format is required and must be one of: pem, jwk"
315
-
316
- **Cause:** `keys.format` is missing or invalid. The component validates against `JWKSKeyFormats.SCHEME_SET` (values are lowercase: `'pem'`, `'jwk'`).
317
-
318
- **Fix:** Use one of the supported formats:
319
-
320
- ```typescript
321
- keys: {
322
- driver: JWKSKeyDrivers.FILE,
323
- format: JWKSKeyFormats.PEM, // or JWKSKeyFormats.JWK
324
- private: './keys/private.pem',
325
- public: './keys/public.pem',
326
- }
327
- ```
328
-
329
- ### "[defineJWKSAuth] kid is required for issuer mode"
330
-
331
- **Cause:** The Key ID (`kid`) is required for the issuer to include in the JWKS and JWT headers. It allows verifiers to identify which key was used to sign a token.
332
-
333
- **Fix:** Provide a unique key identifier:
334
-
335
- ```typescript
336
- options: {
337
- mode: JWKSModes.ISSUER,
338
- kid: 'my-service-key-2024',
339
- // ...
340
- }
341
- ```
342
-
343
- ### "[defineJWKSAuth] jwksUrl is required for verifier mode"
344
-
345
- **Cause:** JWKS verifier mode needs the URL of the issuer's `/certs` endpoint to fetch the public key set.
346
-
347
- **Fix:** Provide the JWKS endpoint URL:
348
-
349
- ```typescript
350
- this.bind<TJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS }).toValue({
351
- standard: JOSEStandards.JWKS,
352
- options: {
353
- mode: JWKSModes.VERIFIER,
354
- jwksUrl: 'https://auth-service.example.com/certs',
355
- },
356
- });
357
- ```
358
-
359
- ### "[JWKSIssuerTokenService] Invalid JWK key material"
360
-
361
- **Cause:** When using `JWKSKeyFormats.JWK`, the private or public key content failed to parse as valid JSON, or `importJWK()` rejected it. The full error is logged at `error` level.
362
-
363
- **Fix:** Ensure your JWK keys are valid JSON objects:
364
-
365
- ```json
366
- {
367
- "kty": "RSA",
368
- "n": "...",
369
- "e": "AQAB",
370
- "d": "...",
371
- "alg": "RS256",
372
- "use": "sig"
373
- }
374
- ```
375
-
376
- If stored as files, ensure the file contains valid JSON (not PEM). If stored as text (`JWKSKeyDrivers.TEXT`), ensure the string is parseable JSON.
377
-
378
- ### "[JWKSIssuerTokenService] JWKS not initialized yet. Call getJWKSAsync() instead."
379
-
380
- **Cause:** `getJWKS()` (synchronous) was called before the lazy initialization completed. The issuer loads keys asynchronously on first use.
381
-
382
- **Fix:** Use the async variant:
383
-
384
- ```typescript
385
- const jwks = await issuerService.getJWKSAsync();
386
- ```
387
-
388
- The built-in `JWKSController` already uses `getJWKSAsync()`, so this error only occurs if you call `getJWKS()` directly in custom code.
389
-
390
- ### "[JWKSVerifierTokenService] Verifier mode cannot sign tokens"
391
-
392
- **Cause:** `generate()` was called on a `JWKSVerifierTokenService`. The verifier mode only has access to public keys (via the remote JWKS URL) and cannot sign tokens.
393
-
394
- **Fix:** Token generation should only happen on the **issuer** service. If you need both signing and verification in the same application, use `JWKSModes.ISSUER` - the issuer can both sign and verify.
395
-
396
- ### "Authentication failed. Tried strategies: jwt, jwks"
397
-
398
- **Cause:** All configured strategies failed in `'any'` mode. Each strategy attempted to authenticate the request and threw.
399
-
400
- **Fix:** Verify the client is sending the correct `Authorization` header:
401
- - For Bearer (JWS/JWKS): `Authorization: Bearer <token>`
402
- - For Basic: `Authorization: Basic <base64(username:password)>`
403
-
404
- Common causes:
405
- - Token expired
406
- - Token signed with a different key
407
- - Wrong strategy name in route config (e.g., `'jwt'` when using JWKS)
408
- - Strategy not registered (see below)
409
-
410
- ### "[AuthenticationStrategyRegistry] Descriptor not found: jwt"
411
-
412
- **Cause:** A route references strategy name `'jwt'` but no strategy with that name has been registered in the `AuthenticationStrategyRegistry`.
413
-
414
- **Fix:** Strategies are **not auto-registered** by `AuthenticateComponent`. You must manually register them after the component:
415
-
416
- ```typescript
417
- // In preConfigure() or after component registration
418
- this.component(AuthenticateComponent);
419
-
420
- // Manual strategy registration
421
146
  AuthenticationStrategyRegistry.getInstance().register({
422
147
  container: this,
423
- strategies: [
424
- { strategy: JWSAuthenticationStrategy, name: 'jwt' },
425
- ],
148
+ strategies: [{ name: Authentication.STRATEGY_JWT, strategy: JWSAuthenticationStrategy }],
426
149
  });
427
150
  ```
428
151
 
429
- See [Usage & Examples](./usage#strategy-registration) for the full registration flow.
152
+ ## AuthenticationProvider (runtime)
153
+
154
+ The middleware that executes strategies in the configured mode.
155
+
156
+ | Message | Status | Method | Cause |
157
+ |---------|--------|--------|-------|
158
+ | `Authentication failed. Tried strategies: {strategies}` | 401 | `executeAnyMode` | Every strategy failed in `'any'` mode |
159
+ | `Failed to identify authenticated user!` | 401 | `executeAllMode` | All strategies passed in `'all'` mode, but the first strategy's `userId` is falsy |
160
+ | `Invalid authentication mode \| mode: {mode}` | 500 | `createAuthenticateMiddleware` | `mode` is not `'any'` or `'all'` |
430
161
 
431
- ### "[AuthController] Failed to init auth controller | Invalid injectable authentication service!"
162
+ **Fix for "Authentication failed":** verify the client sends the right header - `Bearer <token>` or `Basic <base64>`. Common causes: an expired token, a token signed with a different key, or the wrong strategy name in the route config.
432
163
 
433
- **Cause:** The auth controller factory could not resolve the authentication service from DI. The service key (configured via `controllerOpts.serviceKey`) is not bound.
164
+ ## Auth controller factory
434
165
 
435
- **Fix:** Register your `AuthenticationService` before registering the component:
166
+ | Message | Status | Method | Cause | Fix |
167
+ |---------|--------|--------|-------|-----|
168
+ | `[AuthController] Failed to init auth controller \| Invalid injectable authentication service!` | 400 | `constructor` | DI could not resolve the service at `controllerOpts.serviceKey` | Register your service before the component |
436
169
 
437
170
  ```typescript
438
- // 1. Register your auth service
439
171
  this.service(AuthenticationService);
440
172
 
441
- // 2. Configure REST options with matching service key
442
173
  this.bind<TAuthenticationRestOptions>({ key: AuthenticateBindingKeys.REST_OPTIONS }).toValue({
443
174
  useAuthController: true,
444
- controllerOpts: {
445
- restPath: '/auth',
446
- serviceKey: 'services.AuthenticationService',
447
- },
175
+ controllerOpts: { restPath: '/auth', serviceKey: 'services.AuthenticationService' },
448
176
  });
449
177
 
450
- // 3. Register component
451
178
  this.component(AuthenticateComponent);
452
179
  ```
453
180
 
454
- ### "[defineBasicAuth] verifyCredentials function is required"
455
-
456
- **Cause:** `BASIC_OPTIONS` was bound but without a `verifyCredentials` callback.
457
-
458
- **Fix:** Provide a `verifyCredentials` function:
459
-
460
- ```typescript
461
- this.bind<TBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS }).toValue({
462
- verifyCredentials: async ({ credentials, context }) => {
463
- const user = await userRepo.findByUsername(credentials.username);
464
- if (user && await bcrypt.compare(credentials.password, user.passwordHash)) {
465
- return { userId: user.id };
466
- }
467
- return null;
468
- },
469
- });
470
- ```
471
-
472
- ### "[verify] Invalid or expired token"
473
-
474
- **Cause:** Token verification failed. This is a sanitized error - the original error (expired, wrong signature, malformed) is logged internally but not exposed to clients.
475
-
476
- **Fix:** Check the application logs for the full error. Common causes:
477
- - Token has expired (check `exp` claim)
478
- - Token signed with a different secret/key
479
- - Token was tampered with
480
- - Algorithm mismatch between signing and verification
481
-
482
- ```bash
483
- # Look for the full error in logs
484
- grep "Failed to verify token" logs/application.log
485
- ```
486
-
487
- ---
488
-
489
- ## Error Categories
181
+ ## Error categories
490
182
 
491
183
  ```mermaid
492
184
  flowchart TB
493
- subgraph S400["Startup Errors (400)"]
494
- direction TB
495
- A1["Missing options"]
496
- A2["Invalid secrets"]
497
- A3["Missing functions"]
498
- A4["JWKS key validation"]
499
- A5["Mode validation"]
500
- A6["DI resolution"]
185
+ subgraph S400["Startup (400)"]
186
+ A1["Missing options / secrets / functions"]
187
+ A2["JWKS key + format validation"]
188
+ A3["Mode validation"]
189
+ A4["DI resolution"]
501
190
  end
502
-
503
- subgraph S401["Runtime Errors (401)"]
504
- direction TB
505
- B1["Missing header"]
506
- B2["Wrong scheme"]
507
- B3["Invalid format"]
508
- B4["Token verification"]
509
- B5["Credential verification"]
510
- B6["Strategy exhaustion"]
191
+ subgraph S401["Runtime (401)"]
192
+ B1["Missing/wrong/malformed header"]
193
+ B2["Token or credential verification"]
194
+ B3["Strategy exhaustion"]
511
195
  end
512
-
513
- subgraph S500["Structural Errors (500)"]
514
- direction TB
196
+ subgraph S500["Structural (500)"]
515
197
  C1["Unsupported operation"]
516
198
  C2["Uninitialized state"]
517
- C3["Key/file I/O errors"]
518
- C4["Invalid auth mode"]
199
+ C3["Key/file I/O"]
519
200
  end
520
201
 
521
202
  style S400 fill:#fff3cd,stroke:#ffc107
@@ -523,52 +204,8 @@ flowchart TB
523
204
  style S500 fill:#d1ecf1,stroke:#0dcaf0
524
205
  ```
525
206
 
526
- ### Startup Errors (400)
527
-
528
- These errors prevent the application from starting. They occur during component binding or DI resolution. The component uses `getError()` without an explicit status code, which defaults to **400**.
529
-
530
- | Category | Errors | When |
531
- |----------|--------|------|
532
- | Missing options | `At least one of jwtOptions or basicOptions` | No auth options bound |
533
- | Invalid secrets | `Invalid jwtSecret` | JWS secret missing or placeholder |
534
- | Missing functions | `getTokenExpiresFn is required` | No expiry function |
535
- | JWKS key validation | `keys.private and keys.public are required` | Missing key material |
536
- | JWKS format validation | `keys.format is required` | Invalid key format |
537
- | Mode validation | `Unknown JOSE standard`, `Invalid JWKS mode` | Invalid discriminated union value |
538
- | DI resolution | `Invalid injectable authentication service` | Service not registered |
539
-
540
- ::: info Why 400 and not 500?
541
- The `AuthenticateComponent` and `AbstractAuthRegistry` use `getError({ message })` without specifying `statusCode`. The `getError()` helper defaults to `statusCode: 400`. Service-level initialization errors (file I/O, key parsing) explicitly set `statusCode: 500`.
542
- :::
543
-
544
- ### Runtime Errors (401)
545
-
546
- These errors occur during request processing and return `401 Unauthorized` to clients.
547
-
548
- | Category | Errors | When |
549
- |----------|--------|------|
550
- | Missing header | `Missing authorization header` | No `Authorization` header |
551
- | Wrong scheme | `Invalid schema of request token` | Header uses wrong auth type |
552
- | Invalid format | `Invalid authorization header format` | Malformed header value |
553
- | Token verification | `Invalid or expired token` | JWT verification failed |
554
- | Credential verification | `Invalid username or password` | Basic auth credentials rejected |
555
- | Strategy exhaustion | `Authentication failed. Tried strategies:` | All strategies failed |
556
-
557
- ### Structural Errors (500)
558
-
559
- These errors indicate programming mistakes, I/O failures, or misconfiguration that should be fixed in code.
560
-
561
- | Category | Errors | When |
562
- |----------|--------|------|
563
- | Unsupported operation | `Verifier mode cannot sign tokens` | Wrong service used for signing |
564
- | Uninitialized state | `JWKS not initialized yet` | Sync access before async init |
565
- | Key/file I/O errors | `Unknown key driver`, `Invalid raw.priv key`, `Invalid JWK key material` | JWKS key loading/parsing failed |
566
- | Invalid mode | `Invalid authentication mode` | Unknown mode passed to provider |
567
-
568
- ---
569
-
570
- ## See Also
207
+ ## See also
571
208
 
572
- - [Setup & Configuration](./) -- Binding keys, options interfaces, and initial setup
573
- - [Usage & Examples](./usage) -- Securing routes, auth flows, and API endpoints
574
- - [API Reference](./api) -- Architecture, service internals, and strategy registry
209
+ - [Overview](./) - initial setup and binding keys
210
+ - [Usage & Examples](./usage) - securing routes, auth flows, and API endpoints
211
+ - [API Reference](./api) - architecture, service internals, and strategy registry