@tstdl/base 0.93.178 → 0.93.180

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 (207) hide show
  1. package/api/response.js +4 -3
  2. package/api/server/gateway.js +9 -3
  3. package/audit/auditor.d.ts +1 -2
  4. package/audit/drizzle/{0000_lumpy_thunderball.sql → 0000_shallow_elektra.sql} +1 -1
  5. package/audit/drizzle/meta/0000_snapshot.json +2 -2
  6. package/audit/drizzle/meta/_journal.json +2 -2
  7. package/authentication/README.md +87 -42
  8. package/authentication/authentication.api.d.ts +392 -53
  9. package/authentication/authentication.api.js +133 -28
  10. package/authentication/client/api.client.d.ts +3 -3
  11. package/authentication/client/api.client.js +4 -4
  12. package/authentication/client/authentication.service.d.ts +93 -23
  13. package/authentication/client/authentication.service.js +113 -28
  14. package/authentication/client/http-client.middleware.d.ts +1 -1
  15. package/authentication/client/http-client.middleware.js +5 -4
  16. package/authentication/client/module.d.ts +1 -1
  17. package/authentication/client/module.js +2 -2
  18. package/authentication/errors/index.d.ts +1 -1
  19. package/authentication/errors/index.js +1 -1
  20. package/authentication/errors/password-requirements.error.d.ts +5 -0
  21. package/authentication/errors/{secret-requirements.error.js → password-requirements.error.js} +2 -2
  22. package/authentication/models/authentication-password.model.d.ts +8 -0
  23. package/authentication/models/{authentication-credentials.model.js → authentication-password.model.js} +11 -17
  24. package/authentication/models/authentication-session.model.d.ts +0 -2
  25. package/authentication/models/authentication-session.model.js +1 -7
  26. package/authentication/models/authentication-totp-recovery-code.model.d.ts +6 -0
  27. package/authentication/models/authentication-totp-recovery-code.model.js +34 -0
  28. package/authentication/models/authentication-totp.model.d.ts +19 -0
  29. package/authentication/models/authentication-totp.model.js +51 -0
  30. package/authentication/models/authentication-used-totp-token.model.d.ts +5 -0
  31. package/authentication/models/authentication-used-totp-token.model.js +32 -0
  32. package/authentication/models/index.d.ts +6 -3
  33. package/authentication/models/index.js +6 -3
  34. package/authentication/models/{init-secret-reset-data.model.d.ts → init-password-reset-data.model.d.ts} +3 -3
  35. package/authentication/models/{init-secret-reset-data.model.js → init-password-reset-data.model.js} +5 -5
  36. package/authentication/models/password-check-result.model.d.ts +3 -0
  37. package/authentication/models/{secret-check-result.model.js → password-check-result.model.js} +6 -6
  38. package/authentication/models/subject.model.d.ts +0 -6
  39. package/authentication/models/subject.model.js +0 -6
  40. package/authentication/models/token.model.d.ts +16 -2
  41. package/authentication/server/authentication-ancillary.service.d.ts +6 -6
  42. package/authentication/server/authentication-ancillary.service.js +1 -1
  43. package/authentication/server/authentication-password-requirements.validator.d.ts +55 -0
  44. package/authentication/server/{authentication-secret-requirements.validator.js → authentication-password-requirements.validator.js} +22 -22
  45. package/authentication/server/authentication.api-controller.d.ts +55 -27
  46. package/authentication/server/authentication.api-controller.js +214 -39
  47. package/authentication/server/authentication.audit.d.ts +42 -5
  48. package/authentication/server/authentication.service.d.ts +182 -93
  49. package/authentication/server/authentication.service.js +628 -206
  50. package/authentication/server/drizzle/{0000_soft_tag.sql → 0000_odd_echo.sql} +59 -13
  51. package/authentication/server/drizzle/meta/0000_snapshot.json +345 -32
  52. package/authentication/server/drizzle/meta/_journal.json +2 -2
  53. package/authentication/server/helper.d.ts +16 -16
  54. package/authentication/server/helper.js +33 -34
  55. package/authentication/server/index.d.ts +1 -1
  56. package/authentication/server/index.js +1 -1
  57. package/authentication/server/module.d.ts +2 -2
  58. package/authentication/server/module.js +4 -2
  59. package/authentication/server/schemas.d.ts +11 -7
  60. package/authentication/server/schemas.js +7 -3
  61. package/authentication/tests/authentication-password-requirements.validator.test.js +29 -0
  62. package/authentication/tests/authentication.api-controller.test.js +49 -15
  63. package/authentication/tests/authentication.client-error-handling.test.js +3 -2
  64. package/authentication/tests/authentication.client-middleware.test.js +5 -5
  65. package/authentication/tests/authentication.client-service-methods.test.js +28 -14
  66. package/authentication/tests/authentication.client-service-refresh.test.js +7 -6
  67. package/authentication/tests/authentication.client-service.test.js +10 -8
  68. package/authentication/tests/authentication.service.test.js +37 -29
  69. package/authentication/tests/authentication.test-ancillary-service.d.ts +1 -1
  70. package/authentication/tests/authentication.test-ancillary-service.js +1 -1
  71. package/authentication/tests/brute-force-protection.test.js +211 -0
  72. package/authentication/tests/helper.test.js +25 -21
  73. package/authentication/tests/password-requirements.error.test.js +14 -0
  74. package/authentication/tests/remember.api.test.js +22 -14
  75. package/authentication/tests/remember.service.test.js +23 -16
  76. package/authentication/tests/subject.service.test.js +2 -2
  77. package/authentication/tests/suspended-subject.test.d.ts +1 -0
  78. package/authentication/tests/suspended-subject.test.js +120 -0
  79. package/authentication/tests/totp.enrollment.test.d.ts +1 -0
  80. package/authentication/tests/totp.enrollment.test.js +123 -0
  81. package/authentication/tests/totp.login.test.d.ts +1 -0
  82. package/authentication/tests/totp.login.test.js +213 -0
  83. package/authentication/tests/totp.recovery-codes.test.d.ts +1 -0
  84. package/authentication/tests/totp.recovery-codes.test.js +97 -0
  85. package/authentication/tests/totp.status.test.d.ts +1 -0
  86. package/authentication/tests/totp.status.test.js +72 -0
  87. package/circuit-breaker/postgres/drizzle/{0000_cooing_korath.sql → 0000_same_captain_cross.sql} +1 -1
  88. package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +2 -2
  89. package/circuit-breaker/postgres/drizzle/meta/_journal.json +2 -2
  90. package/cryptography/cryptography.d.ts +336 -0
  91. package/cryptography/cryptography.js +328 -0
  92. package/cryptography/index.d.ts +4 -0
  93. package/cryptography/index.js +4 -0
  94. package/{utils → cryptography}/jwt.d.ts +22 -4
  95. package/{utils → cryptography}/jwt.js +36 -18
  96. package/cryptography/module.d.ts +35 -0
  97. package/cryptography/module.js +148 -0
  98. package/cryptography/tests/cryptography.test.d.ts +1 -0
  99. package/cryptography/tests/cryptography.test.js +175 -0
  100. package/cryptography/tests/jwt.test.d.ts +1 -0
  101. package/cryptography/tests/jwt.test.js +54 -0
  102. package/cryptography/tests/modern.test.d.ts +1 -0
  103. package/cryptography/tests/modern.test.js +105 -0
  104. package/cryptography/tests/module.test.d.ts +1 -0
  105. package/cryptography/tests/module.test.js +100 -0
  106. package/cryptography/tests/totp.test.d.ts +1 -0
  107. package/cryptography/tests/totp.test.js +108 -0
  108. package/cryptography/totp.d.ts +96 -0
  109. package/cryptography/totp.js +123 -0
  110. package/document-management/server/drizzle/{0000_curious_nighthawk.sql → 0000_sharp_scream.sql} +21 -21
  111. package/document-management/server/drizzle/meta/0000_snapshot.json +22 -22
  112. package/document-management/server/drizzle/meta/_journal.json +2 -2
  113. package/document-management/server/services/document-file.service.js +1 -1
  114. package/errors/errors.localization.d.ts +2 -2
  115. package/errors/errors.localization.js +2 -2
  116. package/errors/index.d.ts +1 -0
  117. package/errors/index.js +1 -0
  118. package/errors/too-many-requests.error.d.ts +5 -0
  119. package/errors/too-many-requests.error.js +7 -0
  120. package/examples/api/authentication.js +5 -5
  121. package/examples/api/custom-authentication.js +4 -3
  122. package/file/server/mime-type.js +1 -1
  123. package/http/http-body.d.ts +1 -0
  124. package/http/http-body.js +3 -0
  125. package/image-service/imgproxy/imgproxy-image-service.d.ts +0 -1
  126. package/image-service/imgproxy/imgproxy-image-service.js +9 -27
  127. package/key-value-store/postgres/drizzle/{0000_shocking_slipstream.sql → 0000_moaning_calypso.sql} +1 -1
  128. package/key-value-store/postgres/drizzle/meta/0000_snapshot.json +2 -2
  129. package/key-value-store/postgres/drizzle/meta/_journal.json +2 -2
  130. package/lock/postgres/drizzle/{0000_busy_tattoo.sql → 0000_nappy_wraith.sql} +1 -1
  131. package/lock/postgres/drizzle/meta/0000_snapshot.json +2 -2
  132. package/lock/postgres/drizzle/meta/_journal.json +2 -2
  133. package/logger/formatters/json.js +1 -1
  134. package/logger/formatters/pretty-print.js +1 -1
  135. package/mail/drizzle/{0000_numerous_the_watchers.sql → 0000_cultured_quicksilver.sql} +2 -2
  136. package/mail/drizzle/meta/0000_snapshot.json +4 -4
  137. package/mail/drizzle/meta/_journal.json +2 -9
  138. package/notification/server/drizzle/{0000_wise_pyro.sql → 0000_new_tenebrous.sql} +6 -6
  139. package/notification/server/drizzle/meta/0000_snapshot.json +7 -7
  140. package/notification/server/drizzle/meta/_journal.json +2 -2
  141. package/notification/tests/notification-flow.test.js +1 -8
  142. package/notification/tests/notification-type.service.test.js +3 -3
  143. package/openid-connect/oidc.service.js +2 -3
  144. package/orm/data-types/common.js +1 -1
  145. package/orm/server/drizzle/schema-converter.js +9 -4
  146. package/orm/server/encryption.js +1 -1
  147. package/orm/server/module.d.ts +0 -1
  148. package/orm/server/module.js +0 -4
  149. package/orm/server/repository.d.ts +2 -1
  150. package/orm/server/repository.js +7 -10
  151. package/orm/tests/encryption.test.js +4 -6
  152. package/orm/tests/repository-extra-coverage.test.js +0 -2
  153. package/orm/tests/repository-regression.test.js +0 -3
  154. package/package.json +9 -8
  155. package/password/README.md +1 -1
  156. package/password/have-i-been-pwned.js +1 -1
  157. package/rate-limit/postgres/drizzle/{0000_watery_rage.sql → 0000_serious_sauron.sql} +1 -1
  158. package/rate-limit/postgres/drizzle/meta/0000_snapshot.json +2 -2
  159. package/rate-limit/postgres/drizzle/meta/_journal.json +2 -2
  160. package/rate-limit/postgres/postgres-rate-limiter.d.ts +1 -1
  161. package/rate-limit/postgres/postgres-rate-limiter.js +1 -1
  162. package/rate-limit/rate-limiter.d.ts +1 -1
  163. package/rpc/tests/rpc.integration.test.js +25 -31
  164. package/supports.d.ts +1 -0
  165. package/supports.js +1 -0
  166. package/task-queue/postgres/drizzle/{0000_faithful_daimon_hellstrom.sql → 0000_dark_ronan.sql} +5 -5
  167. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +10 -10
  168. package/task-queue/postgres/drizzle/meta/_journal.json +2 -9
  169. package/task-queue/postgres/task-queue.js +2 -2
  170. package/task-queue/tests/coverage-enhancement.test.js +2 -2
  171. package/test/drizzle/{0000_natural_cannonball.sql → 0000_organic_gamora.sql} +2 -2
  172. package/test/drizzle/meta/0000_snapshot.json +3 -4
  173. package/test/drizzle/meta/_journal.json +2 -9
  174. package/testing/integration-setup.d.ts +7 -3
  175. package/testing/integration-setup.js +119 -96
  176. package/utils/alphabet.d.ts +1 -0
  177. package/utils/alphabet.js +1 -0
  178. package/utils/base32.d.ts +4 -0
  179. package/utils/base32.js +49 -0
  180. package/utils/base64.d.ts +0 -2
  181. package/utils/base64.js +6 -70
  182. package/utils/equals.d.ts +13 -3
  183. package/utils/equals.js +29 -9
  184. package/utils/index.d.ts +1 -2
  185. package/utils/index.js +1 -2
  186. package/utils/random.d.ts +1 -0
  187. package/utils/random.js +14 -8
  188. package/authentication/errors/secret-requirements.error.d.ts +0 -5
  189. package/authentication/models/authentication-credentials.model.d.ts +0 -10
  190. package/authentication/models/secret-check-result.model.d.ts +0 -3
  191. package/authentication/server/authentication-secret-requirements.validator.d.ts +0 -55
  192. package/authentication/tests/authentication-ancillary.service.test.js +0 -13
  193. package/authentication/tests/authentication-secret-requirements.validator.test.js +0 -29
  194. package/authentication/tests/secret-requirements.error.test.js +0 -14
  195. package/mail/drizzle/0001_married_tarantula.sql +0 -12
  196. package/mail/drizzle/meta/0001_snapshot.json +0 -69
  197. package/orm/server/tokens.d.ts +0 -1
  198. package/orm/server/tokens.js +0 -2
  199. package/task-queue/postgres/drizzle/0001_rapid_infant_terrible.sql +0 -16
  200. package/task-queue/postgres/drizzle/meta/0001_snapshot.json +0 -753
  201. package/test/drizzle/0001_closed_the_captain.sql +0 -2
  202. package/test/drizzle/meta/0001_snapshot.json +0 -117
  203. package/utils/cryptography.d.ts +0 -137
  204. package/utils/cryptography.js +0 -201
  205. /package/authentication/tests/{authentication-ancillary.service.test.d.ts → authentication-password-requirements.validator.test.d.ts} +0 -0
  206. /package/authentication/tests/{authentication-secret-requirements.validator.test.d.ts → brute-force-protection.test.d.ts} +0 -0
  207. /package/authentication/tests/{secret-requirements.error.test.d.ts → password-requirements.error.test.d.ts} +0 -0
@@ -1,6 +1,7 @@
1
1
  import { defineApi } from '../api/types.js';
2
- import { assign, boolean, defaulted, emptyObjectSchema, explicitObject, literal, never, number, object, optional, string } from '../schema/index.js';
3
- import { SecretCheckResult } from './models/secret-check-result.model.js';
2
+ import { array, assign, boolean, defaulted, emptyObjectSchema, explicitObject, literal, never, number, object, optional, pick, string, union } from '../schema/index.js';
3
+ import { AuthenticationSession } from './models/index.js';
4
+ import { PasswordCheckResult } from './models/password-check-result.model.js';
4
5
  import { TokenPayloadBase } from './models/token-payload-base.model.js';
5
6
  /**
6
7
  * Can be provided in {@link ApiEndpointDefinition} data property to signal that the request does not need a valid token.
@@ -13,20 +14,20 @@ export const authenticationApiDefinition = getAuthenticationApiDefinition(emptyO
13
14
  * Get authentication REST API definition
14
15
  * @param additionalTokenPayloadSchema Schema for additional token payload
15
16
  * @param authenticationDataSchema Schema for additional authentication data
16
- * @param initSecretResetDataSchema Schema for additional secret reset data
17
+ * @param initPasswordResetDataSchema Schema for additional password reset data
17
18
  * @param resource Resource name (default: 'auth')
18
19
  * @param additionalEndpoints Additional endpoints to add to the API definition
19
20
  * @returns Authentication REST API definition
20
21
  * @template AdditionalTokenPayload Type of additional token payload
21
22
  * @template AuthenticationData Type of additional authentication data
22
- * @template AdditionalInitSecretResetData Type of additional secret reset data
23
+ * @template AdditionalInitPasswordResetData Type of additional password reset data
23
24
  * @template AdditionalEndpoints Type of additional endpoints
24
25
  */
25
- export function getAuthenticationApiDefinition(additionalTokenPayloadSchema, authenticationDataSchema, initSecretResetDataSchema, resource, additionalEndpoints) {
26
+ export function getAuthenticationApiDefinition(additionalTokenPayloadSchema, authenticationDataSchema, initPasswordResetDataSchema, resource, additionalEndpoints) {
26
27
  return defineApi({
27
28
  resource: resource ?? 'auth',
28
29
  endpoints: {
29
- ...getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSchema, authenticationDataSchema, initSecretResetDataSchema),
30
+ ...getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSchema, authenticationDataSchema, initPasswordResetDataSchema),
30
31
  ...additionalEndpoints,
31
32
  },
32
33
  });
@@ -35,14 +36,24 @@ export function getAuthenticationApiDefinition(additionalTokenPayloadSchema, aut
35
36
  * Get authentication REST API endpoints definition
36
37
  * @param additionalTokenPayloadSchema Schema for additional token payload
37
38
  * @param authenticationDataSchema Schema for additional authentication data
38
- * @param additionalInitSecretResetDataSchema Schema for additional secret reset data
39
+ * @param additionalInitPasswordResetDataSchema Schema for additional password reset data
39
40
  * @returns Authentication REST API endpoints definition
40
41
  * @template AdditionalTokenPayload Type of additional token payload
41
42
  * @template AuthenticationData Type of additional authentication data
42
- * @template AdditionalInitSecretResetData Type of additional secret reset data
43
+ * @template AdditionalInitPasswordResetData Type of additional password reset data
43
44
  */
44
- export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitSecretResetDataSchema) {
45
+ export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitPasswordResetDataSchema) {
45
46
  const tokenResultSchema = assign(TokenPayloadBase, additionalTokenPayloadSchema);
47
+ const loginSuccessResultSchema = object({
48
+ type: literal('success'),
49
+ result: tokenResultSchema,
50
+ lowRecoveryCodesWarning: optional(boolean()),
51
+ });
52
+ const loginTotpResultSchema = object({
53
+ type: literal('totp'),
54
+ challengeToken: string(),
55
+ });
56
+ const loginResultSchema = union(loginSuccessResultSchema, loginTotpResultSchema);
46
57
  return {
47
58
  login: {
48
59
  resource: 'token',
@@ -50,16 +61,100 @@ export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSc
50
61
  parameters: explicitObject({
51
62
  tenantId: optional(string()),
52
63
  subject: string(),
53
- secret: string(),
64
+ password: string(),
54
65
  remember: defaulted(boolean(), false),
55
66
  data: authenticationDataSchema,
56
67
  }),
57
- result: tokenResultSchema,
68
+ result: loginResultSchema,
69
+ credentials: true,
70
+ data: {
71
+ [dontWaitForValidToken]: true,
72
+ },
73
+ },
74
+ loginVerifyTotp: {
75
+ resource: 'token/verify-totp',
76
+ method: 'POST',
77
+ parameters: explicitObject({
78
+ challengeToken: string(),
79
+ token: string(),
80
+ }),
81
+ result: loginSuccessResultSchema,
82
+ credentials: true,
83
+ data: {
84
+ [dontWaitForValidToken]: true,
85
+ },
86
+ },
87
+ loginRecovery: {
88
+ resource: 'token/recovery',
89
+ method: 'POST',
90
+ parameters: object({
91
+ challengeToken: string(),
92
+ recoveryCode: string(),
93
+ }),
94
+ result: loginSuccessResultSchema,
58
95
  credentials: true,
59
96
  data: {
60
97
  [dontWaitForValidToken]: true,
61
98
  },
62
99
  },
100
+ initEnrollTotp: {
101
+ resource: 'totp/enroll/init',
102
+ method: 'POST',
103
+ result: object({
104
+ secret: string(),
105
+ uri: string(),
106
+ }),
107
+ credentials: true,
108
+ },
109
+ completeEnrollTotp: {
110
+ resource: 'totp/enroll/complete',
111
+ method: 'POST',
112
+ parameters: object({
113
+ token: string(),
114
+ }),
115
+ result: object({
116
+ recoveryCodes: array(string()),
117
+ }),
118
+ credentials: true,
119
+ },
120
+ disableTotp: {
121
+ resource: 'totp/disable',
122
+ method: 'POST',
123
+ parameters: object({
124
+ token: string(),
125
+ }),
126
+ result: literal('ok'),
127
+ credentials: true,
128
+ },
129
+ disableTotpWithRecoveryCode: {
130
+ resource: 'totp/disable-with-recovery-code',
131
+ method: 'POST',
132
+ parameters: object({
133
+ recoveryCode: string(),
134
+ }),
135
+ result: literal('ok'),
136
+ credentials: true,
137
+ },
138
+ regenerateRecoveryCodes: {
139
+ resource: 'totp/recovery-codes',
140
+ method: 'POST',
141
+ parameters: object({
142
+ token: string(),
143
+ invalidateOtherSessions: optional(boolean()),
144
+ }),
145
+ result: object({
146
+ recoveryCodes: array(string()),
147
+ }),
148
+ credentials: true,
149
+ },
150
+ getTotpStatus: {
151
+ resource: 'totp/status',
152
+ method: 'GET',
153
+ result: object({
154
+ active: boolean(),
155
+ }),
156
+ credentials: true,
157
+ },
63
158
  refresh: {
64
159
  resource: 'refresh',
65
160
  method: 'POST',
@@ -106,44 +201,42 @@ export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSc
106
201
  [dontWaitForValidToken]: true,
107
202
  },
108
203
  },
109
- changeSecret: {
110
- resource: 'secret/change',
204
+ changePassword: {
205
+ resource: 'password/change',
111
206
  method: 'POST',
112
- parameters: explicitObject({
113
- tenantId: optional(string()),
114
- subject: string(),
115
- currentSecret: string(),
116
- newSecret: string(),
207
+ parameters: object({
208
+ currentPassword: string(),
209
+ newPassword: string(),
117
210
  }),
118
211
  result: literal('ok'),
119
212
  credentials: true,
120
213
  },
121
- initSecretReset: {
122
- resource: 'secret/init-reset',
214
+ initPasswordReset: {
215
+ resource: 'password/init-reset',
123
216
  method: 'POST',
124
217
  parameters: explicitObject({
125
218
  tenantId: optional(string()),
126
219
  subject: string(),
127
- data: additionalInitSecretResetDataSchema,
220
+ data: additionalInitPasswordResetDataSchema,
128
221
  }),
129
222
  result: literal('ok'),
130
223
  },
131
- resetSecret: {
132
- resource: 'secret/reset',
224
+ resetPassword: {
225
+ resource: 'password/reset',
133
226
  method: 'POST',
134
227
  parameters: object({
135
228
  token: string(),
136
- newSecret: string(),
229
+ newPassword: string(),
137
230
  }),
138
231
  result: literal('ok'),
139
232
  },
140
- checkSecret: {
141
- resource: 'secret/check',
233
+ checkPassword: {
234
+ resource: 'password/check',
142
235
  method: 'POST',
143
236
  parameters: object({
144
- secret: string(),
237
+ password: string(),
145
238
  }),
146
- result: SecretCheckResult,
239
+ result: PasswordCheckResult,
147
240
  },
148
241
  timestamp: {
149
242
  resource: 'timestamp',
@@ -152,5 +245,17 @@ export function getAuthenticationApiEndpointsDefinition(additionalTokenPayloadSc
152
245
  [dontWaitForValidToken]: true,
153
246
  },
154
247
  },
248
+ listSessions: {
249
+ resource: 'me/sessions',
250
+ method: 'GET',
251
+ result: array(pick(AuthenticationSession, ['id', 'begin', 'end'])),
252
+ credentials: true,
253
+ },
254
+ invalidateAllOtherSessions: {
255
+ resource: 'me/invalidate-other-sessions',
256
+ method: 'POST',
257
+ result: literal('ok'),
258
+ credentials: true,
259
+ },
155
260
  };
156
261
  }
@@ -6,13 +6,13 @@ import { type AuthenticationApiDefinition } from '../authentication.api.js';
6
6
  * Get an authentication API client
7
7
  * @param additionalTokenPayloadSchema Schema for additional token payload
8
8
  * @param authenticationDataSchema Schema for additional authentication data
9
- * @param additionalInitSecretResetData Schema for additional secret reset data
9
+ * @param additionalInitPasswordResetData Schema for additional password reset data
10
10
  * @returns Authentication API client
11
11
  * @template AdditionalTokenPayload Type of additional token payload
12
12
  * @template AuthenticationData Type of additional authentication data
13
- * @template AdditionalInitSecretResetData Type of additional secret reset data
13
+ * @template AdditionalInitPasswordResetData Type of additional password reset data
14
14
  */
15
- export declare function getAuthenticationApiClient<AdditionalTokenPayload extends Record, AuthenticationData, AdditionalInitSecretResetData>(additionalTokenPayloadSchema: ObjectSchemaOrType<AdditionalTokenPayload>, authenticationDataSchema: SchemaTestable<AuthenticationData>, additionalInitSecretResetData: SchemaTestable<AdditionalInitSecretResetData>): ApiClient<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>>;
15
+ export declare function getAuthenticationApiClient<AdditionalTokenPayload extends Record, AuthenticationData, AdditionalInitPasswordResetData>(additionalTokenPayloadSchema: ObjectSchemaOrType<AdditionalTokenPayload>, authenticationDataSchema: SchemaTestable<AuthenticationData>, additionalInitPasswordResetData: SchemaTestable<AdditionalInitPasswordResetData>): ApiClient<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitPasswordResetData>>;
16
16
  declare const defaultAuthenticationApiClient: ApiClient<AuthenticationApiDefinition<import("type-fest").EmptyObject, unknown, import("type-fest").EmptyObject>>;
17
17
  /**
18
18
  * Default authentication API client
@@ -12,14 +12,14 @@ import { getAuthenticationApiDefinition } from '../authentication.api.js';
12
12
  * Get an authentication API client
13
13
  * @param additionalTokenPayloadSchema Schema for additional token payload
14
14
  * @param authenticationDataSchema Schema for additional authentication data
15
- * @param additionalInitSecretResetData Schema for additional secret reset data
15
+ * @param additionalInitPasswordResetData Schema for additional password reset data
16
16
  * @returns Authentication API client
17
17
  * @template AdditionalTokenPayload Type of additional token payload
18
18
  * @template AuthenticationData Type of additional authentication data
19
- * @template AdditionalInitSecretResetData Type of additional secret reset data
19
+ * @template AdditionalInitPasswordResetData Type of additional password reset data
20
20
  */
21
- export function getAuthenticationApiClient(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitSecretResetData) {
22
- const definition = getAuthenticationApiDefinition(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitSecretResetData);
21
+ export function getAuthenticationApiClient(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitPasswordResetData) {
22
+ const definition = getAuthenticationApiDefinition(additionalTokenPayloadSchema, authenticationDataSchema, additionalInitPasswordResetData);
23
23
  let AuthenticationApiClient = class AuthenticationApiClient extends compileClient(definition) {
24
24
  };
25
25
  AuthenticationApiClient = __decorate([
@@ -1,7 +1,8 @@
1
1
  import type { AfterResolve } from '../../injector/index.js';
2
2
  import { afterResolve } from '../../injector/index.js';
3
3
  import type { Record } from '../../types/index.js';
4
- import type { SecretCheckResult, TokenPayload } from '../models/index.js';
4
+ import type { AuthenticationSession, PasswordCheckResult, TokenPayload } from '../models/index.js';
5
+ import type { LoginTotpResult } from '../server/authentication.service.js';
5
6
  import type { SubjectInput } from '../types.js';
6
7
  /**
7
8
  * Handles authentication on client side.
@@ -15,9 +16,9 @@ import type { SubjectInput } from '../types.js';
15
16
  *
16
17
  * @template AdditionalTokenPayload Type of additional token payload
17
18
  * @template AuthenticationData Type of additional authentication data
18
- * @template AdditionalInitSecretResetData Type of additional secret reset data
19
+ * @template AdditionalInitPasswordResetData Type of additional password reset data
19
20
  */
20
- export declare class AuthenticationClientService<AdditionalTokenPayload extends Record = Record, AuthenticationData = any, AdditionalInitSecretResetData = void> implements AfterResolve, AsyncDisposable {
21
+ export declare class AuthenticationClientService<AdditionalTokenPayload extends Record = Record, AuthenticationData = any, AdditionalInitPasswordResetData = void> implements AfterResolve, AsyncDisposable {
21
22
  private readonly client;
22
23
  private readonly errorSubject;
23
24
  private readonly tokenUpdateBus;
@@ -44,6 +45,8 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
44
45
  readonly rawRefreshToken: import("../../signals/api.js").WritableSignal<string | undefined>;
45
46
  /** Current raw impersonator refresh token */
46
47
  readonly rawImpersonatorRefreshToken: import("../../signals/api.js").WritableSignal<string | undefined>;
48
+ /** Whether the remaining recovery codes are low */
49
+ readonly lowRecoveryCodesWarning: import("../../signals/api.js").WritableSignal<boolean | undefined>;
47
50
  /** Whether the user is logged in */
48
51
  readonly isLoggedIn: import("../../signals/api.js").Signal<boolean>;
49
52
  /** Current session id */
@@ -123,16 +126,31 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
123
126
  */
124
127
  setAdditionalData(data: AuthenticationData): void;
125
128
  /**
126
- * Login with subject and secret
129
+ * Login with subject and password
127
130
  * @param subjectInput The subject to login with
128
- * @param secret The secret to login with
131
+ * @param password The password to login with
129
132
  * @param data Additional authentication data
130
133
  * @param remember Whether to remember the session
134
+ * @returns The login result, if it requires TOTP.
131
135
  */
132
- login(subjectInput: SubjectInput, secret: string, data?: AuthenticationData, remember?: boolean): Promise<void>;
136
+ login(subjectInput: SubjectInput, password: string, data?: AuthenticationData, remember?: boolean): Promise<{
137
+ type: 'success';
138
+ } | LoginTotpResult>;
139
+ /**
140
+ * Verify a TOTP login challenge.
141
+ * @param challengeToken The challenge token.
142
+ * @param token The TOTP token.
143
+ */
144
+ verifyTotpLogin(challengeToken: string, token: string): Promise<void>;
145
+ /**
146
+ * Verify a recovery code login challenge.
147
+ * @param challengeToken The challenge token.
148
+ * @param recoveryCode The recovery code.
149
+ */
150
+ loginRecovery(challengeToken: string, recoveryCode: string): Promise<void>;
133
151
  /**
134
152
  * Logout from the current session.
135
- * This will attempt to end the session on the server and then clear local credentials.
153
+ * This will attempt to end the session on the server and then clear local session state.
136
154
  */
137
155
  logout(): Promise<void>;
138
156
  /**
@@ -157,30 +175,82 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
157
175
  */
158
176
  unimpersonate(data?: AuthenticationData): Promise<void>;
159
177
  /**
160
- * Change the secret for a subject.
161
- * @param subjectInput The subject to change the secret for
162
- * @param currentSecret The current secret
163
- * @param newSecret The new secret
178
+ * Change the password for the current subject.
179
+ * @param currentPassword The current password
180
+ * @param newPassword The new password
181
+ */
182
+ changePassword(currentPassword: string, newPassword: string): Promise<void>;
183
+ /**
184
+ * Initialize a password reset.
185
+ * @param subjectInput The subject to reset the password for
186
+ * @param data Additional data for password reset
187
+ */
188
+ initPasswordReset(subjectInput: SubjectInput, data: AdditionalInitPasswordResetData): Promise<void>;
189
+ /**
190
+ * Reset a password using a reset token.
191
+ * @param token The password reset token
192
+ * @param newPassword The new password
193
+ */
194
+ resetPassword(token: string, newPassword: string): Promise<void>;
195
+ /**
196
+ * Initiate TOTP enrollment.
197
+ * @returns The secret and URI for enrollment.
164
198
  */
165
- changeSecret(subjectInput: SubjectInput, currentSecret: string, newSecret: string): Promise<void>;
199
+ initEnrollTotp(): Promise<{
200
+ secret: string;
201
+ uri: string;
202
+ }>;
166
203
  /**
167
- * Initialize a secret reset.
168
- * @param subjectInput The subject to reset the secret for
169
- * @param data Additional data for secret reset
204
+ * Complete TOTP enrollment.
205
+ * @param token The TOTP token to verify.
206
+ * @returns The recovery codes.
170
207
  */
171
- initResetSecret(subjectInput: SubjectInput, data: AdditionalInitSecretResetData): Promise<void>;
208
+ completeEnrollTotp(token: string): Promise<{
209
+ recoveryCodes: string[];
210
+ }>;
172
211
  /**
173
- * Reset a secret using a reset token.
174
- * @param token The secret reset token
175
- * @param newSecret The new secret
212
+ * Disable TOTP.
213
+ * @param token The TOTP token.
176
214
  */
177
- resetSecret(token: string, newSecret: string): Promise<void>;
215
+ disableTotp(token: string): Promise<void>;
178
216
  /**
179
- * Check a secret for requirements.
180
- * @param secret The secret to check
217
+ * Disable TOTP using a recovery code.
218
+ * @param recoveryCode The recovery code.
219
+ */
220
+ disableTotpWithRecoveryCode(recoveryCode: string): Promise<void>;
221
+ /**
222
+ * Regenerate recovery codes.
223
+ * @param token The TOTP token.
224
+ * @param options Options for regeneration.
225
+ * @returns The new recovery codes.
226
+ */
227
+ regenerateRecoveryCodes(token: string, options?: {
228
+ invalidateOtherSessions?: boolean;
229
+ }): Promise<{
230
+ recoveryCodes: string[];
231
+ }>;
232
+ /**
233
+ * Get TOTP activation status.
234
+ * @returns Whether TOTP is active.
235
+ */
236
+ getTotpStatus(): Promise<{
237
+ active: boolean;
238
+ }>;
239
+ /**
240
+ * Check a password for requirements.
241
+ * @param password The password to check
181
242
  * @returns The result of the check
182
243
  */
183
- checkSecret(secret: string): Promise<SecretCheckResult>;
244
+ checkPassword(password: string): Promise<PasswordCheckResult>;
245
+ /**
246
+ * List all active sessions for the current user.
247
+ * @returns List of sessions.
248
+ */
249
+ listSessions(): Promise<Pick<AuthenticationSession, 'id' | 'begin' | 'end'>[]>;
250
+ /**
251
+ * Invalidate all active sessions for the current user except the current one.
252
+ */
253
+ invalidateAllOtherSessions(): Promise<void>;
184
254
  /**
185
255
  * Update raw tokens.
186
256
  * @param token Raw token
@@ -61,7 +61,7 @@ const unrecoverableErrors = [
61
61
  *
62
62
  * @template AdditionalTokenPayload Type of additional token payload
63
63
  * @template AuthenticationData Type of additional authentication data
64
- * @template AdditionalInitSecretResetData Type of additional secret reset data
64
+ * @template AdditionalInitPasswordResetData Type of additional password reset data
65
65
  */
66
66
  let AuthenticationClientService = class AuthenticationClientService {
67
67
  client = inject(AUTHENTICATION_API_CLIENT);
@@ -90,6 +90,8 @@ let AuthenticationClientService = class AuthenticationClientService {
90
90
  rawRefreshToken = signal(undefined);
91
91
  /** Current raw impersonator refresh token */
92
92
  rawImpersonatorRefreshToken = signal(undefined);
93
+ /** Whether the remaining recovery codes are low */
94
+ lowRecoveryCodesWarning = signal(undefined);
93
95
  /** Whether the user is logged in */
94
96
  isLoggedIn = computed(() => isDefined(this.token()));
95
97
  /** Current session id */
@@ -216,25 +218,51 @@ let AuthenticationClientService = class AuthenticationClientService {
216
218
  this.authenticationData = data;
217
219
  }
218
220
  /**
219
- * Login with subject and secret
221
+ * Login with subject and password
220
222
  * @param subjectInput The subject to login with
221
- * @param secret The secret to login with
223
+ * @param password The password to login with
222
224
  * @param data Additional authentication data
223
225
  * @param remember Whether to remember the session
226
+ * @returns The login result, if it requires TOTP.
224
227
  */
225
- async login(subjectInput, secret, data, remember = false) {
228
+ async login(subjectInput, password, data, remember = false) {
226
229
  if (isDefined(data)) {
227
230
  this.setAdditionalData(data);
228
231
  }
229
- const [token] = await Promise.all([
230
- this.client.login({ tenantId: subjectInput.tenantId, subject: subjectInput.subject, secret, remember, data: this.authenticationData }),
232
+ const [result] = await Promise.all([
233
+ this.client.login({ tenantId: subjectInput.tenantId, subject: subjectInput.subject, password, remember, data: this.authenticationData }),
231
234
  this.syncClock(),
232
235
  ]);
233
- this.setNewToken(token);
236
+ if (result.type == 'totp') {
237
+ return result;
238
+ }
239
+ this.lowRecoveryCodesWarning.set(result.lowRecoveryCodesWarning);
240
+ this.setNewToken(result.result);
241
+ return { type: 'success' };
242
+ }
243
+ /**
244
+ * Verify a TOTP login challenge.
245
+ * @param challengeToken The challenge token.
246
+ * @param token The TOTP token.
247
+ */
248
+ async verifyTotpLogin(challengeToken, token) {
249
+ const result = await this.client.loginVerifyTotp({ challengeToken, token });
250
+ this.lowRecoveryCodesWarning.set(result.lowRecoveryCodesWarning);
251
+ this.setNewToken(result.result);
252
+ }
253
+ /**
254
+ * Verify a recovery code login challenge.
255
+ * @param challengeToken The challenge token.
256
+ * @param recoveryCode The recovery code.
257
+ */
258
+ async loginRecovery(challengeToken, recoveryCode) {
259
+ const result = await this.client.loginRecovery({ challengeToken, recoveryCode });
260
+ this.lowRecoveryCodesWarning.set(result.lowRecoveryCodesWarning);
261
+ this.setNewToken(result.result);
234
262
  }
235
263
  /**
236
264
  * Logout from the current session.
237
- * This will attempt to end the session on the server and then clear local credentials.
265
+ * This will attempt to end the session on the server and then clear local session state.
238
266
  */
239
267
  async logout() {
240
268
  if (isDefined(this.loggingOut)) {
@@ -334,37 +362,94 @@ let AuthenticationClientService = class AuthenticationClientService {
334
362
  });
335
363
  }
336
364
  /**
337
- * Change the secret for a subject.
338
- * @param subjectInput The subject to change the secret for
339
- * @param currentSecret The current secret
340
- * @param newSecret The new secret
365
+ * Change the password for the current subject.
366
+ * @param currentPassword The current password
367
+ * @param newPassword The new password
368
+ */
369
+ async changePassword(currentPassword, newPassword) {
370
+ await this.client.changePassword({ currentPassword, newPassword });
371
+ }
372
+ /**
373
+ * Initialize a password reset.
374
+ * @param subjectInput The subject to reset the password for
375
+ * @param data Additional data for password reset
376
+ */
377
+ async initPasswordReset(subjectInput, data) {
378
+ await this.client.initPasswordReset({ tenantId: subjectInput.tenantId, subject: subjectInput.subject, data });
379
+ }
380
+ /**
381
+ * Reset a password using a reset token.
382
+ * @param token The password reset token
383
+ * @param newPassword The new password
384
+ */
385
+ async resetPassword(token, newPassword) {
386
+ await this.client.resetPassword({ token, newPassword });
387
+ }
388
+ /**
389
+ * Initiate TOTP enrollment.
390
+ * @returns The secret and URI for enrollment.
341
391
  */
342
- async changeSecret(subjectInput, currentSecret, newSecret) {
343
- await this.client.changeSecret({ tenantId: subjectInput.tenantId, subject: subjectInput.subject, currentSecret, newSecret });
392
+ async initEnrollTotp() {
393
+ return await this.client.initEnrollTotp();
344
394
  }
345
395
  /**
346
- * Initialize a secret reset.
347
- * @param subjectInput The subject to reset the secret for
348
- * @param data Additional data for secret reset
396
+ * Complete TOTP enrollment.
397
+ * @param token The TOTP token to verify.
398
+ * @returns The recovery codes.
349
399
  */
350
- async initResetSecret(subjectInput, data) {
351
- await this.client.initSecretReset({ tenantId: subjectInput.tenantId, subject: subjectInput.subject, data });
400
+ async completeEnrollTotp(token) {
401
+ return await this.client.completeEnrollTotp({ token });
352
402
  }
353
403
  /**
354
- * Reset a secret using a reset token.
355
- * @param token The secret reset token
356
- * @param newSecret The new secret
404
+ * Disable TOTP.
405
+ * @param token The TOTP token.
357
406
  */
358
- async resetSecret(token, newSecret) {
359
- await this.client.resetSecret({ token, newSecret });
407
+ async disableTotp(token) {
408
+ await this.client.disableTotp({ token });
360
409
  }
361
410
  /**
362
- * Check a secret for requirements.
363
- * @param secret The secret to check
411
+ * Disable TOTP using a recovery code.
412
+ * @param recoveryCode The recovery code.
413
+ */
414
+ async disableTotpWithRecoveryCode(recoveryCode) {
415
+ await this.client.disableTotpWithRecoveryCode({ recoveryCode });
416
+ }
417
+ /**
418
+ * Regenerate recovery codes.
419
+ * @param token The TOTP token.
420
+ * @param options Options for regeneration.
421
+ * @returns The new recovery codes.
422
+ */
423
+ async regenerateRecoveryCodes(token, options) {
424
+ return await this.client.regenerateRecoveryCodes({ token, ...options });
425
+ }
426
+ /**
427
+ * Get TOTP activation status.
428
+ * @returns Whether TOTP is active.
429
+ */
430
+ async getTotpStatus() {
431
+ return await this.client.getTotpStatus();
432
+ }
433
+ /**
434
+ * Check a password for requirements.
435
+ * @param password The password to check
364
436
  * @returns The result of the check
365
437
  */
366
- async checkSecret(secret) {
367
- return await this.client.checkSecret({ secret });
438
+ async checkPassword(password) {
439
+ return await this.client.checkPassword({ password });
440
+ }
441
+ /**
442
+ * List all active sessions for the current user.
443
+ * @returns List of sessions.
444
+ */
445
+ async listSessions() {
446
+ return await this.client.listSessions();
447
+ }
448
+ /**
449
+ * Invalidate all active sessions for the current user except the current one.
450
+ */
451
+ async invalidateAllOtherSessions() {
452
+ await this.client.invalidateAllOtherSessions();
368
453
  }
369
454
  /**
370
455
  * Update raw tokens.
@@ -6,7 +6,7 @@ import type { AuthenticationClientService } from './authentication.service.js';
6
6
  * @param authenticationServiceOrProvider The authentication service or a provider for it.
7
7
  * @returns A http client middleware.
8
8
  */
9
- export declare function waitForAuthenticationCredentialsMiddleware(authenticationServiceOrProvider: ValueOrAsyncProvider<AuthenticationClientService>): HttpClientMiddleware;
9
+ export declare function waitForAuthenticationMiddleware(authenticationServiceOrProvider: ValueOrAsyncProvider<AuthenticationClientService>): HttpClientMiddleware;
10
10
  /**
11
11
  * A http client middleware that logs out the user if a request fails with a 401 Unauthorized error.
12
12
  * @param authenticationServiceOrProvider The authentication service or a provider for it.