@boopkit/cap-users 0.1.0

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 (58) hide show
  1. package/capability.json +50 -0
  2. package/dist/account-management-service.d.ts +52 -0
  3. package/dist/account-management-service.d.ts.map +1 -0
  4. package/dist/account-management-service.js +140 -0
  5. package/dist/account-management-service.js.map +1 -0
  6. package/dist/account-property-service.d.ts +18 -0
  7. package/dist/account-property-service.d.ts.map +1 -0
  8. package/dist/account-property-service.js +19 -0
  9. package/dist/account-property-service.js.map +1 -0
  10. package/dist/account-service.d.ts +84 -0
  11. package/dist/account-service.d.ts.map +1 -0
  12. package/dist/account-service.js +136 -0
  13. package/dist/account-service.js.map +1 -0
  14. package/dist/auth-middleware.d.ts +50 -0
  15. package/dist/auth-middleware.d.ts.map +1 -0
  16. package/dist/auth-middleware.js +149 -0
  17. package/dist/auth-middleware.js.map +1 -0
  18. package/dist/auth-service.d.ts +112 -0
  19. package/dist/auth-service.d.ts.map +1 -0
  20. package/dist/auth-service.js +575 -0
  21. package/dist/auth-service.js.map +1 -0
  22. package/dist/identity-service.d.ts +48 -0
  23. package/dist/identity-service.d.ts.map +1 -0
  24. package/dist/identity-service.js +98 -0
  25. package/dist/identity-service.js.map +1 -0
  26. package/dist/index.d.ts +27 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +40 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/team-invitation-service.d.ts +61 -0
  31. package/dist/team-invitation-service.d.ts.map +1 -0
  32. package/dist/team-invitation-service.js +237 -0
  33. package/dist/team-invitation-service.js.map +1 -0
  34. package/dist/types.d.ts +92 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +24 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/user-property-service.d.ts +18 -0
  39. package/dist/user-property-service.d.ts.map +1 -0
  40. package/dist/user-property-service.js +19 -0
  41. package/dist/user-property-service.js.map +1 -0
  42. package/dist/user-service.d.ts +47 -0
  43. package/dist/user-service.d.ts.map +1 -0
  44. package/dist/user-service.js +39 -0
  45. package/dist/user-service.js.map +1 -0
  46. package/package.json +31 -0
  47. package/scaffold/prisma/schema/accounts.prisma +47 -0
  48. package/scaffold/prisma/schema/users.prisma +47 -0
  49. package/scaffold/reference/user-auth.ref.md +237 -0
  50. package/scaffold/src/controllers/auth.ts +158 -0
  51. package/scaffold/src/middleware/auth.ts +28 -0
  52. package/scaffold/src/routes/auth.ts +20 -0
  53. package/scaffold/src/services/accounts.service.ts +53 -0
  54. package/scaffold/src/services/users.service.ts +46 -0
  55. package/scaffold/styles/auth.css +120 -0
  56. package/scaffold/views/login.hbs +28 -0
  57. package/scaffold/views/partials/auth-nav.hbs +32 -0
  58. package/scaffold/views/signup.hbs +29 -0
@@ -0,0 +1,575 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AuthError = exports.AuthValidationError = void 0;
7
+ exports.generateToken = generateToken;
8
+ exports.hashToken = hashToken;
9
+ exports.createAuthService = createAuthService;
10
+ const node_crypto_1 = require("node:crypto");
11
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
12
+ const cap_services_1 = require("@boopkit/cap-services");
13
+ // ---------- Errors ----------
14
+ /** Thrown when signup/login input validation fails. */
15
+ class AuthValidationError extends Error {
16
+ constructor(field, message) {
17
+ super(message);
18
+ this.name = 'AuthValidationError';
19
+ this.field = field;
20
+ }
21
+ }
22
+ exports.AuthValidationError = AuthValidationError;
23
+ /** Thrown on login failure — generic message to prevent user enumeration. */
24
+ class AuthError extends Error {
25
+ constructor(message = 'Invalid email or password') {
26
+ super(message);
27
+ this.name = 'AuthError';
28
+ }
29
+ }
30
+ exports.AuthError = AuthError;
31
+ // ---------- Token generation ----------
32
+ /**
33
+ * Generate a partitioned token with 128 bits of cryptographic randomness.
34
+ * Format: `XXXXXXXX-PP-YYYYYYYYYYYYYYYYY` (base36 uppercase).
35
+ * The partition segment is a data-routing hint (default '01').
36
+ */
37
+ function generateToken(partition = '01') {
38
+ const n = BigInt('0x' + (0, node_crypto_1.randomBytes)(16).toString('hex'));
39
+ const b36 = n.toString(36).toUpperCase().padStart(25, '0');
40
+ return `${b36.slice(0, 8)}-${partition}-${b36.slice(8)}`;
41
+ }
42
+ /**
43
+ * SHA-256 hash a token for storage. Input already has high entropy
44
+ * so a fast hash is sufficient (no need for bcrypt).
45
+ */
46
+ function hashToken(token) {
47
+ return (0, node_crypto_1.createHash)('sha256').update(token).digest('hex');
48
+ }
49
+ // ---------- Trust tier helpers ----------
50
+ const TRUST_ORDER = ['recognized', 'authenticated', 'verified'];
51
+ function trustLevel(tier) {
52
+ return TRUST_ORDER.indexOf(tier);
53
+ }
54
+ // ---------- Validation helpers ----------
55
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
56
+ const MIN_PASSWORD_LENGTH = 8;
57
+ function validateEmail(email) {
58
+ if (!email || !EMAIL_RE.test(email)) {
59
+ throw new AuthValidationError('email', 'Invalid email address');
60
+ }
61
+ }
62
+ function validatePassword(password) {
63
+ if (!password || password.length < MIN_PASSWORD_LENGTH) {
64
+ throw new AuthValidationError('password', `Password must be at least ${MIN_PASSWORD_LENGTH} characters`);
65
+ }
66
+ }
67
+ function validatePasswordConfirmation(password, confirmation) {
68
+ if (password !== confirmation) {
69
+ throw new AuthValidationError('passwordConfirmation', 'Passwords do not match');
70
+ }
71
+ }
72
+ // ---------- Retry helper ----------
73
+ const MAX_RETRIES = 3;
74
+ /**
75
+ * Retry a read-modify-write operation on StaleEntityError (optimistic locking).
76
+ * The operation function is called repeatedly until it succeeds or retries are
77
+ * exhausted. Each retry re-reads the current state, so the modification is
78
+ * applied to the latest revision.
79
+ */
80
+ async function withRetry(op) {
81
+ for (let attempt = 0;; attempt++) {
82
+ try {
83
+ return await op();
84
+ }
85
+ catch (err) {
86
+ if (err instanceof cap_services_1.StaleEntityError && attempt < MAX_RETRIES)
87
+ continue;
88
+ throw err;
89
+ }
90
+ }
91
+ }
92
+ // ---------- Factory ----------
93
+ /**
94
+ * Create an auth business service orchestrating signup, login, and
95
+ * session management on top of user data services.
96
+ */
97
+ function createAuthService(deps, options) {
98
+ const { userService, identityService, userPropertyService } = deps;
99
+ const hashRounds = options?.hashRounds ?? 10;
100
+ const defaultSessionDuration = options?.defaultSessionDuration ?? 604800; // 7 days
101
+ // ---- Validation ----
102
+ function validateSignupInput(input) {
103
+ validateEmail(input.email);
104
+ validatePassword(input.password);
105
+ validatePasswordConfirmation(input.password, input.passwordConfirmation);
106
+ }
107
+ // ---- Decomposed steps ----
108
+ async function createUser(input) {
109
+ const info = {
110
+ type: 'user',
111
+ name: input.name,
112
+ email: input.email,
113
+ };
114
+ return userService.create(info);
115
+ }
116
+ async function createIdentity(userId, domain, key) {
117
+ return identityService.create(userId, domain, key);
118
+ }
119
+ async function setProfile(userId, profileData) {
120
+ return userPropertyService.put(userId, 'profile', profileData);
121
+ }
122
+ async function setCredentials(userId, strategy, secret) {
123
+ const hash = await bcryptjs_1.default.hash(secret, hashRounds);
124
+ return withRetry(async () => {
125
+ const existing = await userPropertyService.get(userId, 'credentials', { allowSensitive: true });
126
+ const entries = existing ? [...existing.info] : [];
127
+ const idx = entries.findIndex((e) => e.strategy === strategy);
128
+ if (idx >= 0) {
129
+ entries[idx] = { strategy, secret: hash };
130
+ }
131
+ else {
132
+ entries.push({ strategy, secret: hash });
133
+ }
134
+ return userPropertyService.put(userId, 'credentials', entries, {
135
+ expectedRevision: existing?.revision,
136
+ });
137
+ });
138
+ }
139
+ async function addAuthenticationMethod(userId, strategy, methodOpts) {
140
+ return withRetry(async () => {
141
+ const existing = await userPropertyService.get(userId, 'authentication');
142
+ const methods = existing ? [...existing.info] : [];
143
+ const idx = methods.findIndex((m) => m.strategy === strategy);
144
+ const entry = {
145
+ strategy,
146
+ accepted: true,
147
+ ...(methodOpts?.refresh_token !== undefined && { refresh_token: methodOpts.refresh_token }),
148
+ ...(methodOpts?.access_token !== undefined && { access_token: methodOpts.access_token }),
149
+ ...(methodOpts?.access_token_expires_at !== undefined && { access_token_expires_at: methodOpts.access_token_expires_at }),
150
+ ...(methodOpts?.oauth_profile !== undefined && { oauth_profile: methodOpts.oauth_profile }),
151
+ };
152
+ if (idx >= 0) {
153
+ methods[idx] = entry;
154
+ }
155
+ else {
156
+ methods.push(entry);
157
+ }
158
+ return userPropertyService.put(userId, 'authentication', methods, {
159
+ expectedRevision: existing?.revision,
160
+ });
161
+ });
162
+ }
163
+ async function disableAuthenticationMethod(userId, strategy) {
164
+ return withRetry(async () => {
165
+ const existing = await userPropertyService.get(userId, 'authentication');
166
+ const methods = existing ? [...existing.info] : [];
167
+ const idx = methods.findIndex((m) => m.strategy === strategy);
168
+ if (idx >= 0) {
169
+ methods[idx] = { ...methods[idx], accepted: false };
170
+ }
171
+ return userPropertyService.put(userId, 'authentication', methods, {
172
+ expectedRevision: existing?.revision,
173
+ });
174
+ });
175
+ }
176
+ async function setAuthorization(userId, identityKey, strategy, trust, expiresIn) {
177
+ const duration = expiresIn ?? defaultSessionDuration;
178
+ const grant = {
179
+ identity_key: identityKey,
180
+ strategy,
181
+ trust,
182
+ granted_at: Date.now(),
183
+ // expiresIn=0 means standing grant (no expiry) — e.g. API keys
184
+ expires_at: duration === 0 ? 0 : Date.now() + duration * 1000,
185
+ granted_duration: duration,
186
+ };
187
+ return withRetry(async () => {
188
+ const existing = await userPropertyService.get(userId, 'authorization');
189
+ const grants = existing ? [...existing.info] : [];
190
+ const idx = grants.findIndex((g) => g.identity_key === identityKey);
191
+ if (idx >= 0) {
192
+ grants[idx] = grant;
193
+ }
194
+ else {
195
+ grants.push(grant);
196
+ }
197
+ return userPropertyService.put(userId, 'authorization', grants, {
198
+ expectedRevision: existing?.revision,
199
+ });
200
+ });
201
+ }
202
+ async function generateSessionToken(userId) {
203
+ const token = generateToken();
204
+ await identityService.create(userId, 'cookie', hashToken(token));
205
+ return token;
206
+ }
207
+ // ---- Login ----
208
+ async function validateCredentialsFn(email, password) {
209
+ const identity = await identityService.findByDomainAndKey('email', email);
210
+ if (!identity)
211
+ throw new AuthError();
212
+ // Check authentication policy — is local auth accepted for this user?
213
+ const methodAccepted = await isMethodAccepted(identity.userId, 'local');
214
+ if (!methodAccepted)
215
+ throw new AuthError();
216
+ const credRecord = await userPropertyService.get(identity.userId, 'credentials', { allowSensitive: true });
217
+ if (!credRecord)
218
+ throw new AuthError();
219
+ const localEntry = credRecord.info.find((e) => e.strategy === 'local');
220
+ if (!localEntry)
221
+ throw new AuthError();
222
+ const match = await bcryptjs_1.default.compare(password, localEntry.secret);
223
+ if (!match)
224
+ throw new AuthError();
225
+ const user = await userService.findById(identity.userId);
226
+ if (!user)
227
+ throw new AuthError();
228
+ return user;
229
+ }
230
+ // Session fixation protection (OWASP): on any privilege-level change (login,
231
+ // re-auth, role escalation) the pre-authentication session token MUST be replaced
232
+ // with a fresh one. If `currentSessionToken` is provided, the old token is expired
233
+ // so an attacker who knew or set the old token can't hijack the authenticated session.
234
+ // See: https://owasp.org/www-community/attacks/Session_fixation
235
+ async function login(email, password, currentSessionToken) {
236
+ const user = await validateCredentialsFn(email, password);
237
+ const sessionToken = await rotateSession(user.id, currentSessionToken);
238
+ await setAuthorization(user.id, sessionToken, 'session', 'authenticated');
239
+ const result = { user, sessionToken };
240
+ await options?.onLogin?.(result);
241
+ return result;
242
+ }
243
+ // ---- Session management ----
244
+ // Session fixation protection (OWASP): when rotating a session, the old token
245
+ // is expired (not reused) so that an attacker who obtained the pre-auth token
246
+ // cannot hijack the session. This MUST happen on any privilege-level change
247
+ // (login, re-auth, role escalation).
248
+ // If no currentSessionToken is provided, a new identity is created without
249
+ // removing existing ones (supports multi-device sessions).
250
+ // If the token doesn't match any identity, a new one is created (graceful fallback).
251
+ // See: https://owasp.org/www-community/attacks/Session_fixation
252
+ async function rotateSession(userId, currentSessionToken) {
253
+ if (currentSessionToken) {
254
+ const hashedCurrent = hashToken(currentSessionToken);
255
+ const existing = await identityService.findByDomainAndKey('cookie', hashedCurrent);
256
+ if (existing && existing.userId === userId) {
257
+ await identityService.endDate('cookie', existing.key);
258
+ }
259
+ }
260
+ return generateSessionToken(userId);
261
+ }
262
+ // ---- Query methods ----
263
+ async function getAuthenticationMethods(userId) {
264
+ const record = await userPropertyService.get(userId, 'authentication');
265
+ return record ? record.info : null;
266
+ }
267
+ async function getAuthorizationStatus(userId, identityKey) {
268
+ const record = await userPropertyService.get(userId, 'authorization');
269
+ if (!record)
270
+ return null;
271
+ return record.info.find((g) => g.identity_key === identityKey) ?? null;
272
+ }
273
+ async function getTrustTier(userId, identityKey) {
274
+ const grant = await getAuthorizationStatus(userId, identityKey);
275
+ if (!grant)
276
+ return null;
277
+ // Expired grants downgrade to recognized. Null/0 = standing grant (no expiry).
278
+ if (grant.expires_at && grant.expires_at < Date.now())
279
+ return 'recognized';
280
+ return grant.trust;
281
+ }
282
+ async function isMethodAccepted(userId, strategy) {
283
+ const methods = await getAuthenticationMethods(userId);
284
+ if (!methods)
285
+ return false;
286
+ const entry = methods.find((m) => m.strategy === strategy);
287
+ return entry?.accepted === true;
288
+ }
289
+ async function isAuthorized(userId, identityKey, requiredTrust = 'authenticated') {
290
+ const grant = await getAuthorizationStatus(userId, identityKey);
291
+ if (!grant)
292
+ return false;
293
+ // Use effective trust tier: expired grants downgrade to 'recognized' (not unauthorized).
294
+ // This matches the spec's request lifecycle: expired grant → trust = 'recognized'.
295
+ // Standing grants (expires_at=0 or null) keep their stored trust tier.
296
+ const effectiveTrust = (grant.expires_at && grant.expires_at < Date.now())
297
+ ? 'recognized'
298
+ : grant.trust;
299
+ return trustLevel(effectiveTrust) >= trustLevel(requiredTrust);
300
+ }
301
+ // ---- Logout and device management ----
302
+ async function logout(userId, sessionToken) {
303
+ // Downgrade this device's authorization grant to 'recognized' — cookie survives
304
+ await withRetry(async () => {
305
+ const record = await userPropertyService.get(userId, 'authorization');
306
+ if (!record)
307
+ return;
308
+ const grants = [...record.info];
309
+ const idx = grants.findIndex((g) => g.identity_key === sessionToken);
310
+ if (idx >= 0) {
311
+ grants[idx] = { ...grants[idx], trust: 'recognized', granted_at: Date.now() };
312
+ await userPropertyService.put(userId, 'authorization', grants, {
313
+ expectedRevision: record.revision,
314
+ });
315
+ }
316
+ });
317
+ }
318
+ async function logoutAll(userId) {
319
+ // Downgrade all session grants to 'recognized'; API key grants unaffected
320
+ await withRetry(async () => {
321
+ const record = await userPropertyService.get(userId, 'authorization');
322
+ if (!record)
323
+ return;
324
+ const grants = record.info.map((g) => g.strategy === 'session'
325
+ ? { ...g, trust: 'recognized', granted_at: Date.now() }
326
+ : g);
327
+ await userPropertyService.put(userId, 'authorization', grants, {
328
+ expectedRevision: record.revision,
329
+ });
330
+ });
331
+ }
332
+ async function forgetDevice(userId, sessionToken) {
333
+ // End-date cookie identity (stored as hash)
334
+ const hashedToken = hashToken(sessionToken);
335
+ const existing = await identityService.findByDomainAndKey('cookie', hashedToken);
336
+ if (existing && existing.userId === userId) {
337
+ await identityService.endDate('cookie', existing.key);
338
+ }
339
+ // Remove the matching grant from authorization array
340
+ await withRetry(async () => {
341
+ const record = await userPropertyService.get(userId, 'authorization');
342
+ if (!record)
343
+ return;
344
+ const grants = record.info.filter((g) => g.identity_key !== sessionToken);
345
+ if (grants.length !== record.info.length) {
346
+ await userPropertyService.put(userId, 'authorization', grants, {
347
+ expectedRevision: record.revision,
348
+ });
349
+ }
350
+ });
351
+ }
352
+ async function forgetAllDevices(userId) {
353
+ // End-date all cookie identities
354
+ const allIdentities = await identityService.findAllByUser(userId);
355
+ const cookieIdentities = allIdentities.filter((i) => i.domain === 'cookie');
356
+ for (const identity of cookieIdentities) {
357
+ await identityService.endDate('cookie', identity.key);
358
+ }
359
+ // Remove all session grants; preserve API key grants
360
+ await withRetry(async () => {
361
+ const record = await userPropertyService.get(userId, 'authorization');
362
+ if (!record)
363
+ return;
364
+ const grants = record.info.filter((g) => g.strategy !== 'session');
365
+ await userPropertyService.put(userId, 'authorization', grants, {
366
+ expectedRevision: record.revision,
367
+ });
368
+ });
369
+ }
370
+ // ---- Trust management ----
371
+ // setTrust sets trust to any tier — callers are responsible for checking
372
+ // current tier before calling if downgrade prevention is desired.
373
+ async function setTrust(userId, identityKey, tier) {
374
+ return withRetry(async () => {
375
+ const record = await userPropertyService.get(userId, 'authorization');
376
+ if (!record) {
377
+ // T10: No authorization exists — bootstrap a new grant. This is intentional:
378
+ // enables TOTP verification flows where setTrust may be called before
379
+ // any login/signup has created a grant for this identity key.
380
+ return setAuthorization(userId, identityKey, 'session', tier);
381
+ }
382
+ const grants = [...record.info];
383
+ const idx = grants.findIndex((g) => g.identity_key === identityKey);
384
+ if (idx >= 0) {
385
+ grants[idx] = { ...grants[idx], trust: tier, granted_at: Date.now() };
386
+ }
387
+ else {
388
+ // No grant for this identity_key — create one
389
+ grants.push({
390
+ identity_key: identityKey,
391
+ strategy: 'session',
392
+ trust: tier,
393
+ granted_at: Date.now(),
394
+ expires_at: Date.now() + defaultSessionDuration * 1000,
395
+ granted_duration: defaultSessionDuration,
396
+ });
397
+ }
398
+ return userPropertyService.put(userId, 'authorization', grants, {
399
+ expectedRevision: record.revision,
400
+ });
401
+ });
402
+ }
403
+ // ---- API key lifecycle ----
404
+ async function createApiKey(userId) {
405
+ const apiKey = (0, node_crypto_1.randomBytes)(32).toString('base64url');
406
+ await setCredentials(userId, 'api-key', apiKey);
407
+ await addAuthenticationMethod(userId, 'api-key');
408
+ await identityService.create(userId, 'api-key', apiKey);
409
+ await setAuthorization(userId, apiKey, 'api-key', 'authenticated', 0);
410
+ return { apiKey };
411
+ }
412
+ async function validateApiKeyFn(apiKey) {
413
+ // 1. Identity lookup — does this key resolve to a user?
414
+ const identity = await identityService.findByDomainAndKey('api-key', apiKey);
415
+ if (!identity)
416
+ throw new AuthError();
417
+ // 2. Policy gate — is api-key auth accepted for this user?
418
+ const methodAccepted = await isMethodAccepted(identity.userId, 'api-key');
419
+ if (!methodAccepted)
420
+ throw new AuthError();
421
+ // 3. Credential verification — does the key match the stored hash?
422
+ const credRecord = await userPropertyService.get(identity.userId, 'credentials', { allowSensitive: true });
423
+ if (!credRecord)
424
+ throw new AuthError();
425
+ const apiKeyEntry = credRecord.info.find((e) => e.strategy === 'api-key');
426
+ if (!apiKeyEntry)
427
+ throw new AuthError();
428
+ const match = await bcryptjs_1.default.compare(apiKey, apiKeyEntry.secret);
429
+ if (!match)
430
+ throw new AuthError();
431
+ // 4. Resolve the user
432
+ const user = await userService.findById(identity.userId);
433
+ if (!user)
434
+ throw new AuthError();
435
+ return user;
436
+ }
437
+ async function revokeApiKey(userId, apiKey) {
438
+ const existing = await identityService.findByDomainAndKey('api-key', apiKey);
439
+ if (existing && existing.userId === userId) {
440
+ await identityService.endDate('api-key', existing.key);
441
+ }
442
+ }
443
+ async function rotateApiKey(userId, currentApiKey) {
444
+ await revokeApiKey(userId, currentApiKey);
445
+ return createApiKey(userId);
446
+ }
447
+ // ---- Email verification ----
448
+ const verificationTokenTtl = options?.verificationTokenTtl ?? 86400; // 24h default
449
+ async function generateVerificationTokenFn(userId) {
450
+ const token = generateToken('EV');
451
+ const hashedToken = hashToken(token);
452
+ const expiresAt = new Date(Date.now() + verificationTokenTtl * 1000).toISOString();
453
+ // Store hashed token as identity for lookup by token
454
+ await identityService.create(userId, 'email-verification', hashedToken);
455
+ // Store expiry metadata as user property
456
+ await withRetry(async () => {
457
+ const existing = await userPropertyService.get(userId, 'email-verification');
458
+ const tokens = existing ? [...existing.info.tokens] : [];
459
+ tokens.push({ hash: hashedToken, expiresAt });
460
+ return userPropertyService.put(userId, 'email-verification', { tokens }, {
461
+ expectedRevision: existing?.revision,
462
+ });
463
+ });
464
+ return token;
465
+ }
466
+ async function verifyEmailFn(token) {
467
+ const hashedToken = hashToken(token);
468
+ // 1. Look up token → user via identity
469
+ const identity = await identityService.findByDomainAndKey('email-verification', hashedToken);
470
+ if (!identity)
471
+ throw new AuthError('Invalid or expired verification token');
472
+ const userId = identity.userId;
473
+ // 2. Check expiry from stored property
474
+ const record = await userPropertyService.get(userId, 'email-verification');
475
+ if (!record)
476
+ throw new AuthError('Invalid or expired verification token');
477
+ const tokenEntry = record.info.tokens.find((t) => t.hash === hashedToken);
478
+ if (!tokenEntry)
479
+ throw new AuthError('Invalid or expired verification token');
480
+ if (new Date(tokenEntry.expiresAt).getTime() < Date.now()) {
481
+ // Expired — clean up and reject
482
+ await identityService.endDate('email-verification', hashedToken);
483
+ throw new AuthError('Invalid or expired verification token');
484
+ }
485
+ // 3. Consume: end-date identity and remove from property (single-use)
486
+ await identityService.endDate('email-verification', hashedToken);
487
+ await withRetry(async () => {
488
+ const current = await userPropertyService.get(userId, 'email-verification');
489
+ if (!current)
490
+ return;
491
+ const remaining = current.info.tokens.filter((t) => t.hash !== hashedToken);
492
+ return userPropertyService.put(userId, 'email-verification', { tokens: remaining }, {
493
+ expectedRevision: current.revision,
494
+ });
495
+ });
496
+ // 4. Mark email as verified in profile
497
+ await withRetry(async () => {
498
+ const profileRecord = await userPropertyService.get(userId, 'profile');
499
+ if (!profileRecord)
500
+ return;
501
+ const profile = { ...profileRecord.info };
502
+ if (profile.email && typeof profile.email === 'object') {
503
+ profile.email = { ...profile.email, verified: true };
504
+ }
505
+ return userPropertyService.put(userId, 'profile', profile, {
506
+ expectedRevision: profileRecord.revision,
507
+ });
508
+ });
509
+ // 5. Upgrade trust to 'verified' for all active session grants
510
+ await withRetry(async () => {
511
+ const authRecord = await userPropertyService.get(userId, 'authorization');
512
+ if (!authRecord)
513
+ return;
514
+ const grants = authRecord.info.map((g) => g.strategy === 'session' && trustLevel(g.trust) < trustLevel('verified')
515
+ ? { ...g, trust: 'verified' }
516
+ : g);
517
+ return userPropertyService.put(userId, 'authorization', grants, {
518
+ expectedRevision: authRecord.revision,
519
+ });
520
+ });
521
+ // 6. Resolve user email for the result
522
+ const user = await userService.findById(userId);
523
+ const email = user?.info?.email ?? '';
524
+ return { userId, email };
525
+ }
526
+ // ---- Convenience ----
527
+ async function signup(input) {
528
+ validateSignupInput(input);
529
+ const user = await createUser({ name: input.name, email: input.email });
530
+ await createIdentity(user.id, 'email', input.email);
531
+ await setProfile(user.id, {
532
+ name: input.name,
533
+ email: { address: input.email, verified: false },
534
+ });
535
+ await setCredentials(user.id, 'local', input.password);
536
+ await addAuthenticationMethod(user.id, 'local');
537
+ const sessionToken = await generateSessionToken(user.id);
538
+ await setAuthorization(user.id, sessionToken, 'session', 'authenticated');
539
+ const result = { user, sessionToken };
540
+ await options?.onSignup?.(result);
541
+ return result;
542
+ }
543
+ return {
544
+ validateSignup: validateSignupInput,
545
+ createUser,
546
+ createIdentity,
547
+ setProfile,
548
+ setCredentials,
549
+ addAuthenticationMethod,
550
+ disableAuthenticationMethod,
551
+ setAuthorization,
552
+ generateSessionToken,
553
+ validateCredentials: validateCredentialsFn,
554
+ login,
555
+ rotateSession,
556
+ getAuthenticationMethods,
557
+ getAuthorizationStatus,
558
+ getTrustTier,
559
+ isMethodAccepted,
560
+ isAuthorized,
561
+ logout,
562
+ logoutAll,
563
+ forgetDevice,
564
+ forgetAllDevices,
565
+ setTrust,
566
+ createApiKey,
567
+ validateApiKey: validateApiKeyFn,
568
+ revokeApiKey,
569
+ rotateApiKey,
570
+ generateVerificationToken: generateVerificationTokenFn,
571
+ verifyEmail: verifyEmailFn,
572
+ signup,
573
+ };
574
+ }
575
+ //# sourceMappingURL=auth-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-service.js","sourceRoot":"","sources":["../src/auth-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { UserIdentity } from './types.js';
2
+ /** Lifecycle callbacks for identity mutations. */
3
+ export interface IdentityServiceOptions {
4
+ onCreated?(identity: UserIdentity): void;
5
+ onUpdated?(identity: UserIdentity): void;
6
+ onEnded?(identity: UserIdentity): void;
7
+ }
8
+ /** Options for queries that can include ended identities. */
9
+ export interface IdentityQueryOptions {
10
+ includeEnded?: boolean;
11
+ }
12
+ /** The service object returned by createIdentityService. */
13
+ export interface IdentityService {
14
+ create(userId: number, domain: string, key: string): Promise<UserIdentity>;
15
+ findByDomainAndKey(domain: string, key: string): Promise<UserIdentity | null>;
16
+ findByUserAndDomain(userId: number, domain: string): Promise<UserIdentity | null>;
17
+ findAllByUser(userId: number, opts?: IdentityQueryOptions): Promise<UserIdentity[]>;
18
+ update(domain: string, key: string, newUserId: number): Promise<UserIdentity>;
19
+ endDate(domain: string, key: string): Promise<UserIdentity>;
20
+ }
21
+ /** Minimal Prisma-like delegate for the user_identities table. */
22
+ interface IdentityDelegate {
23
+ create(args: {
24
+ data: Record<string, unknown>;
25
+ }): Promise<Record<string, unknown>>;
26
+ findUnique(args: {
27
+ where: Record<string, unknown>;
28
+ }): Promise<Record<string, unknown> | null>;
29
+ findFirst(args: {
30
+ where: Record<string, unknown>;
31
+ }): Promise<Record<string, unknown> | null>;
32
+ findMany(args: {
33
+ where: Record<string, unknown>;
34
+ }): Promise<Record<string, unknown>[]>;
35
+ update(args: {
36
+ where: Record<string, unknown>;
37
+ data: Record<string, unknown>;
38
+ }): Promise<Record<string, unknown>>;
39
+ }
40
+ /**
41
+ * Create an identity service for user identity management.
42
+ *
43
+ * Not entity-shaped — identities use (domain, key) compound unique
44
+ * instead of the standard entity pattern.
45
+ */
46
+ export declare function createIdentityService(model: IdentityDelegate, options?: IdentityServiceOptions): IdentityService;
47
+ export {};
48
+ //# sourceMappingURL=identity-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-service.d.ts","sourceRoot":"","sources":["../src/identity-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,kDAAkD;AAClD,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IACzC,SAAS,CAAC,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;CACxC;AAED,6DAA6D;AAC7D,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3E,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9E,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAClF,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACpF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9E,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7D;AAED,kEAAkE;AAClE,UAAU,gBAAgB;IACxB,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClF,UAAU,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9F,SAAS,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7F,QAAQ,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACvF,MAAM,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnH;AAkCD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,gBAAgB,EACvB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,eAAe,CA8DjB"}