@cogenta/auth 0.1.2 → 0.3.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.
- package/dist/api-keys.d.ts +19 -0
- package/dist/api-keys.d.ts.map +1 -0
- package/dist/api-keys.js +112 -0
- package/dist/api-keys.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/login.d.ts +31 -14
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +40 -49
- package/dist/login.js.map +1 -1
- package/dist/mfa.d.ts +1 -0
- package/dist/mfa.d.ts.map +1 -1
- package/dist/mfa.js +14 -4
- package/dist/mfa.js.map +1 -1
- package/dist/rate-limit.d.ts +33 -0
- package/dist/rate-limit.d.ts.map +1 -1
- package/dist/rate-limit.js +29 -0
- package/dist/rate-limit.js.map +1 -1
- package/dist/resets.d.ts +53 -0
- package/dist/resets.d.ts.map +1 -0
- package/dist/resets.js +89 -0
- package/dist/resets.js.map +1 -0
- package/dist/store.d.ts +5 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +4 -0
- package/dist/store.js.map +1 -1
- package/dist/tables.d.ts +2 -0
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +40 -0
- package/dist/tables.js.map +1 -1
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
import type { ApiKey, CreateApiKeyInput, IssuedApiKey } from './types.js';
|
|
3
|
+
/** A raw bearer token is an API key only if it has this shape — checked before any DB lookup. */
|
|
4
|
+
export declare function looksLikeApiKey(token: string): boolean;
|
|
5
|
+
export interface ApiKeyStore {
|
|
6
|
+
/** Mints a key and returns the raw secret once. It is never stored or returned again. */
|
|
7
|
+
create(input: CreateApiKeyInput): Promise<IssuedApiKey>;
|
|
8
|
+
/** Never the raw key or its hash — a prefix is all a list ever shows. */
|
|
9
|
+
list(): Promise<readonly ApiKey[]>;
|
|
10
|
+
revoke(id: string): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Resolves a raw bearer token to the key it names, or `null` if it does not
|
|
13
|
+
* exist, is revoked, or has expired. Touches `lastUsedAt` on success, the
|
|
14
|
+
* same sliding-window courtesy a session gets.
|
|
15
|
+
*/
|
|
16
|
+
verify(rawKey: string): Promise<ApiKey | null>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createApiKeyStore(db: DatabaseHandle, now?: () => number): ApiKeyStore;
|
|
19
|
+
//# sourceMappingURL=api-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-keys.d.ts","sourceRoot":"","sources":["../src/api-keys.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAEzF,OAAO,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAkCzE,iGAAiG;AACjG,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAsCD,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACvD,yEAAyE;IACzE,IAAI,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;IAClC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CAC/C;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,WAAW,CA8D/F"}
|
package/dist/api-keys.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { CogentaError, identifier, newId, sql } from '@cogenta/core';
|
|
3
|
+
import { TABLES } from './tables.js';
|
|
4
|
+
/**
|
|
5
|
+
* Machine-to-machine bearer credentials (L13 task 8).
|
|
6
|
+
*
|
|
7
|
+
* `resolveActor` in `@cogenta/api` already recognises one bearer-token shape:
|
|
8
|
+
* a session, minted at sign-in for a human. This store mints the other
|
|
9
|
+
* shape — a long-lived key, minted once by an admin for a script or an
|
|
10
|
+
* integration — kept deliberately close to `sessions.ts` in every way that
|
|
11
|
+
* matters: an opaque random secret, hashed before it ever reaches disk, and
|
|
12
|
+
* looked up by that hash, never by the secret itself.
|
|
13
|
+
*
|
|
14
|
+
* A key is not a password. A password is chosen by a person and has to
|
|
15
|
+
* survive being typed and remembered, which is exactly what makes it
|
|
16
|
+
* guessable and worth slowing down with scrypt. A key is generated here,
|
|
17
|
+
* 256 bits of randomness no human ever picks — the same property a session
|
|
18
|
+
* token has — so it is hashed the same fast way a session is, and the
|
|
19
|
+
* defence against guessing is the key space, not the hash cost.
|
|
20
|
+
*/
|
|
21
|
+
const KEY_BYTES = 32;
|
|
22
|
+
const KEY_PREFIX = 'cogenta_sk_';
|
|
23
|
+
/** How much of the raw key stays visible forever, so a list of keys is recognisable. */
|
|
24
|
+
const VISIBLE_PREFIX_LENGTH = 12;
|
|
25
|
+
function issueKey() {
|
|
26
|
+
return `${KEY_PREFIX}${randomBytes(KEY_BYTES).toString('base64url')}`;
|
|
27
|
+
}
|
|
28
|
+
/** Stored hashed, like a session token — a leaked table hands out nothing live. */
|
|
29
|
+
function hashKey(key) {
|
|
30
|
+
return createHash('sha256').update(key).digest('base64url');
|
|
31
|
+
}
|
|
32
|
+
/** A raw bearer token is an API key only if it has this shape — checked before any DB lookup. */
|
|
33
|
+
export function looksLikeApiKey(token) {
|
|
34
|
+
return token.startsWith(KEY_PREFIX) && token.length > KEY_PREFIX.length;
|
|
35
|
+
}
|
|
36
|
+
function fromRow(row) {
|
|
37
|
+
return {
|
|
38
|
+
id: row.id,
|
|
39
|
+
name: row.name,
|
|
40
|
+
prefix: row.key_prefix,
|
|
41
|
+
scope: JSON.parse(row.scope),
|
|
42
|
+
createdBy: row.created_by,
|
|
43
|
+
createdAt: row.created_at,
|
|
44
|
+
expiresAt: row.expires_at ?? undefined,
|
|
45
|
+
revokedAt: row.revoked_at ?? undefined,
|
|
46
|
+
lastUsedAt: row.last_used_at ?? undefined,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function assertScope(scope) {
|
|
50
|
+
if (scope.length === 0 || scope.some((role) => role.trim().length === 0)) {
|
|
51
|
+
throw new CogentaError({
|
|
52
|
+
code: 'QUERY_INVALID',
|
|
53
|
+
message: 'An API key must be granted at least one non-empty role name.',
|
|
54
|
+
hint: 'A key with no role can authenticate and do nothing at all — pass at least one role in "scope".',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function createApiKeyStore(db, now = Date.now) {
|
|
59
|
+
const table = identifier(TABLES.apiKeys, db.dialect);
|
|
60
|
+
return {
|
|
61
|
+
create: async (input) => {
|
|
62
|
+
assertScope(input.scope);
|
|
63
|
+
const key = issueKey();
|
|
64
|
+
const id = newId(now);
|
|
65
|
+
const created = new Date(now()).toISOString();
|
|
66
|
+
const prefix = key.slice(0, VISIBLE_PREFIX_LENGTH);
|
|
67
|
+
await db.query(sql `
|
|
68
|
+
insert into ${table}
|
|
69
|
+
(id, name, key_hash, key_prefix, scope, created_by, created_at, expires_at, revoked_at, last_used_at)
|
|
70
|
+
values
|
|
71
|
+
(${id}, ${input.name}, ${hashKey(key)}, ${prefix}, ${JSON.stringify(input.scope)},
|
|
72
|
+
${input.createdBy}, ${created}, ${input.expiresAt ?? null}, ${null}, ${null})`);
|
|
73
|
+
return {
|
|
74
|
+
id,
|
|
75
|
+
name: input.name,
|
|
76
|
+
prefix,
|
|
77
|
+
scope: input.scope,
|
|
78
|
+
createdBy: input.createdBy,
|
|
79
|
+
createdAt: created,
|
|
80
|
+
expiresAt: input.expiresAt,
|
|
81
|
+
revokedAt: undefined,
|
|
82
|
+
lastUsedAt: undefined,
|
|
83
|
+
key,
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
list: async () => {
|
|
87
|
+
const result = await db.query(sql `select * from ${table} order by created_at desc`);
|
|
88
|
+
return result.rows.map(fromRow);
|
|
89
|
+
},
|
|
90
|
+
revoke: async (id) => {
|
|
91
|
+
const revokedAt = new Date(now()).toISOString();
|
|
92
|
+
await db.query(sql `update ${table} set revoked_at = ${revokedAt} where id = ${id} and revoked_at is null`);
|
|
93
|
+
},
|
|
94
|
+
verify: async (rawKey) => {
|
|
95
|
+
if (!looksLikeApiKey(rawKey))
|
|
96
|
+
return null;
|
|
97
|
+
const targetHash = hashKey(rawKey);
|
|
98
|
+
const result = await db.query(sql `select * from ${table} where key_hash = ${targetHash}`);
|
|
99
|
+
const row = result.rows[0];
|
|
100
|
+
if (row === undefined)
|
|
101
|
+
return null;
|
|
102
|
+
if (row.revoked_at !== null)
|
|
103
|
+
return null;
|
|
104
|
+
if (row.expires_at !== null && new Date(row.expires_at).getTime() <= now())
|
|
105
|
+
return null;
|
|
106
|
+
const lastUsedAt = new Date(now()).toISOString();
|
|
107
|
+
await db.query(sql `update ${table} set last_used_at = ${lastUsedAt} where id = ${row.id}`);
|
|
108
|
+
return fromRow({ ...row, last_used_at: lastUsedAt });
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=api-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../src/api-keys.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* bearer sessions, login-attempt backoff, MFA enforcement for sensitive
|
|
8
8
|
* roles, and the hash-chained audit log L4's agents will write to as well.
|
|
9
9
|
*/
|
|
10
|
+
export type { ApiKeyStore } from './api-keys.js';
|
|
11
|
+
export { createApiKeyStore, looksLikeApiKey } from './api-keys.js';
|
|
10
12
|
export type { AuditFilter, AuditLog } from './audit.js';
|
|
11
13
|
export { createAuditLog } from './audit.js';
|
|
12
14
|
export type { CredentialStore, WebAuthnCredentialData } from './credentials.js';
|
|
@@ -15,8 +17,10 @@ export type { AuthService, AuthServiceOptions, LoginResult } from './login.js';
|
|
|
15
17
|
export { createAuthService } from './login.js';
|
|
16
18
|
export { requiresMfa, sensitiveRoles } from './mfa.js';
|
|
17
19
|
export { hashPassword, verifyPassword } from './password.js';
|
|
18
|
-
export type { RateLimiter } from './rate-limit.js';
|
|
19
|
-
export { createRateLimiter } from './rate-limit.js';
|
|
20
|
+
export type { LoginAttemptSummary, RateLimiter } from './rate-limit.js';
|
|
21
|
+
export { createRateLimiter, LOGIN_ATTEMPT_WINDOW_MS } from './rate-limit.js';
|
|
22
|
+
export type { IssuedPasswordReset, PasswordResetOutcome, PasswordResetStore, } from './resets.js';
|
|
23
|
+
export { createPasswordResetStore, PASSWORD_RESET_TTL_MS } from './resets.js';
|
|
20
24
|
export type { SessionStore } from './sessions.js';
|
|
21
25
|
export { createSessionStore } from './sessions.js';
|
|
22
26
|
export type { AuthStore, AuthStoreOptions } from './store.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAClE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC5D,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAC7E,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,aAAa,CAAA;AACrE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,OAAO,EACP,UAAU,GACX,MAAM,WAAW,CAAA;AAClB,cAAc,YAAY,CAAA;AAC1B,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,4BAA4B,EAC5B,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,eAAe,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
* bearer sessions, login-attempt backoff, MFA enforcement for sensitive
|
|
8
8
|
* roles, and the hash-chained audit log L4's agents will write to as well.
|
|
9
9
|
*/
|
|
10
|
+
export { createApiKeyStore, looksLikeApiKey } from './api-keys.js';
|
|
10
11
|
export { createAuditLog } from './audit.js';
|
|
11
12
|
export { createCredentialStore } from './credentials.js';
|
|
12
13
|
export { createAuthService } from './login.js';
|
|
13
14
|
export { requiresMfa, sensitiveRoles } from './mfa.js';
|
|
14
15
|
export { hashPassword, verifyPassword } from './password.js';
|
|
15
|
-
export { createRateLimiter } from './rate-limit.js';
|
|
16
|
+
export { createRateLimiter, LOGIN_ATTEMPT_WINDOW_MS } from './rate-limit.js';
|
|
17
|
+
export { createPasswordResetStore, PASSWORD_RESET_TTL_MS } from './resets.js';
|
|
16
18
|
export { createSessionStore } from './sessions.js';
|
|
17
19
|
export { createAuthStore } from './store.js';
|
|
18
20
|
export { ensureAuthTables, TABLES as AUTH_TABLES } from './tables.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAM5E,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAE7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,aAAa,CAAA;AAErE,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,OAAO,EACP,UAAU,GACX,MAAM,WAAW,CAAA;AAClB,cAAc,YAAY,CAAA;AAE1B,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAO5C,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,eAAe,CAAA"}
|
package/dist/login.d.ts
CHANGED
|
@@ -3,6 +3,15 @@ import type { CollectionDefinition } from '@cogenta/schema';
|
|
|
3
3
|
import type { AuthenticationResponseJSON, PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON, RegistrationResponseJSON } from '@simplewebauthn/server';
|
|
4
4
|
import type { IssuedSession, User } from './types.js';
|
|
5
5
|
import { type WebAuthnConfig } from './webauthn.js';
|
|
6
|
+
/**
|
|
7
|
+
* Two outcomes, not three.
|
|
8
|
+
*
|
|
9
|
+
* There used to be a third, `totp_setup_required`: a sensitive role with no
|
|
10
|
+
* second factor was refused a session and handed a ticket to enrol one on the
|
|
11
|
+
* spot. ADR-0021 removed it. MFA is now something an account turns on from its
|
|
12
|
+
* own profile and the site *recommends* through a persistent admin notice —
|
|
13
|
+
* never something that stands between a correct password and a session.
|
|
14
|
+
*/
|
|
6
15
|
export type LoginResult = {
|
|
7
16
|
readonly status: 'session';
|
|
8
17
|
readonly session: IssuedSession;
|
|
@@ -11,15 +20,6 @@ export type LoginResult = {
|
|
|
11
20
|
readonly status: 'mfa_required';
|
|
12
21
|
readonly ticket: string;
|
|
13
22
|
readonly availableFactors: readonly ('totp' | 'webauthn')[];
|
|
14
|
-
} | {
|
|
15
|
-
/**
|
|
16
|
-
* A sensitive role with no second factor set up yet. Not an error: the
|
|
17
|
-
* password was correct, and the only thing standing between this
|
|
18
|
-
* attempt and a session is enrolling TOTP right now, with the ticket
|
|
19
|
-
* this result carries.
|
|
20
|
-
*/
|
|
21
|
-
readonly status: 'totp_setup_required';
|
|
22
|
-
readonly ticket: string;
|
|
23
23
|
};
|
|
24
24
|
export interface TotpSetup {
|
|
25
25
|
readonly secret: string;
|
|
@@ -38,7 +38,13 @@ export interface AuthServiceOptions {
|
|
|
38
38
|
readonly db: DatabaseHandle;
|
|
39
39
|
/** From `COGENTA_AUTH_SIGNING_KEY`, never from a config file (rule R7). */
|
|
40
40
|
readonly signingKey: string;
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Kept for the shape `createAuthStore` already passes and for what callers
|
|
43
|
+
* build on top of it, not read by sign-in any more: since ADR-0021 the
|
|
44
|
+
* second-factor challenge follows what a person actually enrolled, not what
|
|
45
|
+
* their role is. `sensitiveRoles`/`requiresMfa` still read collections — for
|
|
46
|
+
* the recommendation, not for the gate.
|
|
47
|
+
*/
|
|
42
48
|
readonly collections: readonly CollectionDefinition[];
|
|
43
49
|
/** Shown in the authenticator app next to the account name. Defaults to "Cogenta". */
|
|
44
50
|
readonly issuer?: string;
|
|
@@ -51,10 +57,21 @@ export interface AuthService {
|
|
|
51
57
|
totpLogin(ticket: string, token: string): Promise<LoginResult>;
|
|
52
58
|
/** Issues a session directly: a verified passkey already proved a strong second factor. */
|
|
53
59
|
sessionForVerifiedUser(userId: string): Promise<LoginResult>;
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Generates a fresh TOTP secret for an already-signed-in account and stores
|
|
62
|
+
* it, unconfirmed. `userId` comes from the caller's session, never from the
|
|
63
|
+
* request body — this is self-service, so the only account it can ever touch
|
|
64
|
+
* is the one making the call.
|
|
65
|
+
*/
|
|
66
|
+
beginTotpEnrolment(userId: string): Promise<TotpSetup>;
|
|
67
|
+
/** Confirms the code from the authenticator app, which is what makes the factor real. */
|
|
68
|
+
confirmTotpEnrolment(userId: string, token: string): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Turns TOTP back off. No second proof is asked for: the caller already
|
|
71
|
+
* holds a live session for this account, which — if TOTP was on — they could
|
|
72
|
+
* only have obtained by passing it.
|
|
73
|
+
*/
|
|
74
|
+
disableTotp(userId: string): Promise<void>;
|
|
58
75
|
/** Adding a passkey to an already-identified account — `userId` comes from an existing session. */
|
|
59
76
|
beginWebAuthnRegistration(userId: string): Promise<WebAuthnRegistrationChallenge>;
|
|
60
77
|
completeWebAuthnRegistration(ticket: string, response: RegistrationResponseJSON, label?: string): Promise<void>;
|
package/dist/login.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,KAAK,EACV,0BAA0B,EAC1B,sCAAsC,EACtC,qCAAqC,EACrC,wBAAwB,EACzB,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"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"}
|
package/dist/login.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
2
2
|
import { CogentaError } from '@cogenta/core';
|
|
3
3
|
import { createCredentialStore } from './credentials.js';
|
|
4
|
-
import { requiresMfa } from './mfa.js';
|
|
5
4
|
import { createRateLimiter } from './rate-limit.js';
|
|
6
5
|
import { createSessionStore } from './sessions.js';
|
|
7
6
|
import { generateTotpSecret, totpUri, verifyTotp } from './totp.js';
|
|
@@ -22,7 +21,7 @@ const TICKET_TTL_MS = 5 * 60 * 1000;
|
|
|
22
21
|
* something single-use that lives seconds.
|
|
23
22
|
*
|
|
24
23
|
* `purpose` is part of what gets signed, not a separate check layered on
|
|
25
|
-
* top: a login ticket and a
|
|
24
|
+
* top: a login ticket and a WebAuthn registration ticket (or a WebAuthn
|
|
26
25
|
* registration ticket and a WebAuthn login ticket) must not be
|
|
27
26
|
* interchangeable, and folding the purpose into the signature is what makes
|
|
28
27
|
* swapping one for another a signature mismatch rather than a bug to
|
|
@@ -73,7 +72,11 @@ function webauthnNotConfigured() {
|
|
|
73
72
|
});
|
|
74
73
|
}
|
|
75
74
|
export function createAuthService(options) {
|
|
76
|
-
|
|
75
|
+
// `options.collections` is deliberately not read here any more: since
|
|
76
|
+
// ADR-0021 the second-factor challenge follows what a person enrolled, not
|
|
77
|
+
// what their role is. It stays on the options type because `createAuthStore`
|
|
78
|
+
// passes it and the recommendation source still needs the same list.
|
|
79
|
+
const { db, signingKey, webauthn: webauthnConfig } = options;
|
|
77
80
|
const issuer = options.issuer ?? 'Cogenta';
|
|
78
81
|
const now = options.now ?? Date.now;
|
|
79
82
|
const users = createUserStore(db, now);
|
|
@@ -84,28 +87,24 @@ export function createAuthService(options) {
|
|
|
84
87
|
const session = await sessions.create(user.id);
|
|
85
88
|
return { status: 'session', session, user };
|
|
86
89
|
}
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
/**
|
|
91
|
+
* The second factors this account has actually finished setting up.
|
|
92
|
+
*
|
|
93
|
+
* A TOTP secret only counts once it has been confirmed. An unconfirmed one
|
|
94
|
+
* means someone opened the enrolment screen and walked away; treating that as
|
|
95
|
+
* a usable factor would challenge them for a code their authenticator app
|
|
96
|
+
* never received, and there would be no way back.
|
|
97
|
+
*/
|
|
98
|
+
async function enrolledFactors(userId) {
|
|
89
99
|
const available = [];
|
|
90
|
-
|
|
100
|
+
const totp = await credentials.totpSecret(userId);
|
|
101
|
+
if (totp !== null && totp.verified)
|
|
91
102
|
available.push('totp');
|
|
92
|
-
if (
|
|
103
|
+
if ((await credentials.webAuthnCredentials(userId)).length > 0)
|
|
93
104
|
available.push('webauthn');
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// exactly that — it proves the password step happened, and nothing
|
|
98
|
-
// more, the same as the ordinary MFA ticket proves the same thing for
|
|
99
|
-
// completing a second factor that already exists.
|
|
100
|
-
return {
|
|
101
|
-
status: 'totp_setup_required',
|
|
102
|
-
ticket: signTicket(signingKey, {
|
|
103
|
-
purpose: 'totp_setup',
|
|
104
|
-
userId: user.id,
|
|
105
|
-
expiresAt: now() + TICKET_TTL_MS,
|
|
106
|
-
}),
|
|
107
|
-
};
|
|
108
|
-
}
|
|
105
|
+
return available;
|
|
106
|
+
}
|
|
107
|
+
function mfaChallenge(user, available) {
|
|
109
108
|
return {
|
|
110
109
|
status: 'mfa_required',
|
|
111
110
|
ticket: signTicket(signingKey, {
|
|
@@ -131,7 +130,13 @@ export function createAuthService(options) {
|
|
|
131
130
|
});
|
|
132
131
|
}
|
|
133
132
|
await rateLimit.clear(subject);
|
|
134
|
-
|
|
133
|
+
// What decides the challenge is what this person enrolled, not what
|
|
134
|
+
// their role is (ADR-0021). A brand-new admin signs straight in; an
|
|
135
|
+
// account that turned TOTP on still has to produce a code, because
|
|
136
|
+
// ignoring a factor someone deliberately enabled would be a silent
|
|
137
|
+
// downgrade of their own security.
|
|
138
|
+
const factors = await enrolledFactors(user.id);
|
|
139
|
+
return factors.length === 0 ? issueSession(user) : mfaChallenge(user, factors);
|
|
135
140
|
},
|
|
136
141
|
totpLogin: async (ticket, token) => {
|
|
137
142
|
const verified = verifyTicket(signingKey, 'login', ticket, now());
|
|
@@ -172,31 +177,23 @@ export function createAuthService(options) {
|
|
|
172
177
|
}
|
|
173
178
|
return issueSession(user);
|
|
174
179
|
},
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
if (
|
|
178
|
-
throw invalidTicket();
|
|
179
|
-
const user = await users.byId(verified.userId);
|
|
180
|
-
if (user === null) {
|
|
180
|
+
beginTotpEnrolment: async (userId) => {
|
|
181
|
+
const user = await users.byId(userId);
|
|
182
|
+
if (user === null || user.status !== 'active') {
|
|
181
183
|
throw new CogentaError({
|
|
182
184
|
code: 'AUTH_USER_NOT_FOUND',
|
|
183
|
-
message: 'This account no longer exists.',
|
|
184
|
-
hint: '
|
|
185
|
+
message: 'This account no longer exists or is disabled.',
|
|
186
|
+
hint: 'Sign in again.',
|
|
185
187
|
});
|
|
186
188
|
}
|
|
187
|
-
// A fresh secret every
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
// requested can ever be confirmed.
|
|
189
|
+
// A fresh secret on every call: asking for the QR code again (a slow
|
|
190
|
+
// scan, the wrong app) must not leave two different secrets both
|
|
191
|
+
// plausibly "current" — only the last one requested can be confirmed.
|
|
191
192
|
const secret = generateTotpSecret();
|
|
192
193
|
await credentials.setTotpSecret(user.id, secret);
|
|
193
194
|
return { secret, uri: totpUri(secret, issuer, user.email) };
|
|
194
195
|
},
|
|
195
|
-
|
|
196
|
-
const verified = verifyTicket(signingKey, 'totp_setup', ticket, now());
|
|
197
|
-
if (verified === null || verified.userId === null)
|
|
198
|
-
throw invalidTicket();
|
|
199
|
-
const userId = verified.userId;
|
|
196
|
+
confirmTotpEnrolment: async (userId, token) => {
|
|
200
197
|
await rateLimit.check(`totp-setup:${userId}`);
|
|
201
198
|
const stored = await credentials.totpSecret(userId);
|
|
202
199
|
const ok = stored !== null && verifyTotp(token, stored.secret, { now: Math.floor(now() / 1000) });
|
|
@@ -208,17 +205,11 @@ export function createAuthService(options) {
|
|
|
208
205
|
hint: 'Check the code from your authenticator app. Codes are valid for 30 seconds.',
|
|
209
206
|
});
|
|
210
207
|
}
|
|
211
|
-
const user = await users.byId(userId);
|
|
212
|
-
if (user === null) {
|
|
213
|
-
throw new CogentaError({
|
|
214
|
-
code: 'AUTH_USER_NOT_FOUND',
|
|
215
|
-
message: 'This account no longer exists.',
|
|
216
|
-
hint: 'It may have been deleted since the password step. Sign in again.',
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
208
|
await rateLimit.clear(`totp-setup:${userId}`);
|
|
220
209
|
await credentials.confirmTotp(userId);
|
|
221
|
-
|
|
210
|
+
},
|
|
211
|
+
disableTotp: async (userId) => {
|
|
212
|
+
await credentials.removeTotp(userId);
|
|
222
213
|
},
|
|
223
214
|
beginWebAuthnRegistration: async (userId) => {
|
|
224
215
|
if (webauthnConfig === undefined)
|
package/dist/login.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"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"}
|
package/dist/mfa.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CollectionDefinition } from '@cogenta/schema';
|
|
2
2
|
export declare function sensitiveRoles(collections: readonly CollectionDefinition[]): ReadonlySet<string>;
|
|
3
|
+
/** Whether this set of roles is one MFA is recommended for. Never a gate — see above. */
|
|
3
4
|
export declare function requiresMfa(userRoles: readonly string[], collections: readonly CollectionDefinition[]): boolean;
|
|
4
5
|
//# sourceMappingURL=mfa.d.ts.map
|
package/dist/mfa.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AA2B3D,wBAAgB,cAAc,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAMhG;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CACzB,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,WAAW,EAAE,SAAS,oBAAoB,EAAE,GAC3C,OAAO,CAGT"}
|
package/dist/mfa.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Which roles are sensitive enough that a second factor is *recommended*.
|
|
3
3
|
*
|
|
4
4
|
* The spec names `content.publish` and `site.config_write` — contract C's
|
|
5
5
|
* permission taxonomy, for an agent tool. L2 has no tool permissions yet; the
|
|
@@ -8,9 +8,18 @@
|
|
|
8
8
|
* the `admin` role always, since site configuration has no dedicated model in
|
|
9
9
|
* L2 and `admin` is where that power concentrates until it does.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* ADR-0021 changed what this answer is *for*. It used to decide who was turned
|
|
12
|
+
* away at sign-in until they enrolled a second factor — which meant the very
|
|
13
|
+
* first admin of a brand-new site had to complete a TOTP ceremony before they
|
|
14
|
+
* could see a single screen, and an admin without a phone to hand could not get
|
|
15
|
+
* in at all. It now decides who *receives the recommendation* to turn MFA on
|
|
16
|
+
* (`@cogenta/api`'s notices), which is persistent and impossible to lose track
|
|
17
|
+
* of, but never blocks. Enrolment is still real and still enforced at sign-in
|
|
18
|
+
* once it exists — see `passwordLogin` in `login.ts`.
|
|
19
|
+
*
|
|
20
|
+
* Still not configurable per site, for the reason it never was: a setting that
|
|
21
|
+
* can be turned off is a setting that will be, by whoever is in the biggest
|
|
22
|
+
* hurry the day it matters.
|
|
14
23
|
*/
|
|
15
24
|
const ALWAYS_SENSITIVE_ROLES = new Set(['admin']);
|
|
16
25
|
export function sensitiveRoles(collections) {
|
|
@@ -21,6 +30,7 @@ export function sensitiveRoles(collections) {
|
|
|
21
30
|
}
|
|
22
31
|
return roles;
|
|
23
32
|
}
|
|
33
|
+
/** Whether this set of roles is one MFA is recommended for. Never a gate — see above. */
|
|
24
34
|
export function requiresMfa(userRoles, collections) {
|
|
25
35
|
const sensitive = sensitiveRoles(collections);
|
|
26
36
|
return userRoles.some((role) => sensitive.has(role));
|
package/dist/mfa.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mfa.js","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"mfa.js","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;AAEjD,MAAM,UAAU,cAAc,CAAC,WAA4C;IACzE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAC7C,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,WAAW,CAAC,OAAO,IAAI,EAAE;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC1E,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,WAAW,CACzB,SAA4B,EAC5B,WAA4C;IAE5C,MAAM,SAAS,GAAG,cAAc,CAAC,WAAW,CAAC,CAAA;IAC7C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;AACtD,CAAC"}
|
package/dist/rate-limit.d.ts
CHANGED
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
/** How long failed attempts keep counting. Exported so a reader shares the exact window. */
|
|
3
|
+
export declare const LOGIN_ATTEMPT_WINDOW_MS: number;
|
|
4
|
+
/**
|
|
5
|
+
* What the failed attempts inside the window add up to, for one subject
|
|
6
|
+
* (L14 task 4).
|
|
7
|
+
*
|
|
8
|
+
* The table has been written to since L2 and never read by anything but the
|
|
9
|
+
* limiter's own counter, so "somebody is hammering this site" was information
|
|
10
|
+
* the site had and never showed anyone.
|
|
11
|
+
*/
|
|
12
|
+
export interface LoginAttemptSummary {
|
|
13
|
+
/** The email tried, or `mfa:<id>` / `totp-setup:<id>` for the second-factor limits. */
|
|
14
|
+
readonly subject: string;
|
|
15
|
+
readonly attempts: number;
|
|
16
|
+
readonly firstAt: string;
|
|
17
|
+
readonly lastAt: string;
|
|
18
|
+
/** True when the attempts have crossed a backoff threshold. */
|
|
19
|
+
readonly blocked: boolean;
|
|
20
|
+
}
|
|
2
21
|
export interface RateLimiter {
|
|
3
22
|
/** Throws `AUTH_RATE_LIMITED` if the subject is currently backed off. */
|
|
4
23
|
check(subject: string): Promise<void>;
|
|
5
24
|
record(subject: string): Promise<void>;
|
|
6
25
|
/** Called after a successful login: past failures stop counting against them. */
|
|
7
26
|
clear(subject: string): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Failed attempts still inside the window, worst first.
|
|
29
|
+
*
|
|
30
|
+
* Also prunes everything that has fallen out of the window. Nothing else
|
|
31
|
+
* ever deletes a row for a subject that never went on to succeed — `clear`
|
|
32
|
+
* only runs after a *successful* sign-in — so without this the table grows
|
|
33
|
+
* for as long as a script keeps guessing, which is exactly the case where it
|
|
34
|
+
* grows fastest.
|
|
35
|
+
*/
|
|
36
|
+
recentFailures(options?: {
|
|
37
|
+
/** Ignore subjects below this count. Defaults to the first backoff threshold. */
|
|
38
|
+
readonly minAttempts?: number;
|
|
39
|
+
readonly limit?: number;
|
|
40
|
+
}): Promise<readonly LoginAttemptSummary[]>;
|
|
8
41
|
}
|
|
9
42
|
export declare function createRateLimiter(db: DatabaseHandle, now?: () => number): RateLimiter;
|
|
10
43
|
//# sourceMappingURL=rate-limit.d.ts.map
|
package/dist/rate-limit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAmBzF,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,iFAAiF;IACjF,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAmBzF,4FAA4F;AAC5F,eAAO,MAAM,uBAAuB,QAAY,CAAA;AAKhD;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,uFAAuF;IACvF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,iFAAiF;IACjF,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;;;;;;;;OAQG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE;QACvB,iFAAiF;QACjF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;QAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KACxB,GAAG,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAAA;CAC5C;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,WAAW,CAoE/F"}
|
package/dist/rate-limit.js
CHANGED
|
@@ -15,6 +15,10 @@ const THRESHOLDS = [
|
|
|
15
15
|
{ attempts: 15, delayMs: 60_000 },
|
|
16
16
|
{ attempts: 20, delayMs: 15 * 60 * 1000 },
|
|
17
17
|
];
|
|
18
|
+
/** How long failed attempts keep counting. Exported so a reader shares the exact window. */
|
|
19
|
+
export const LOGIN_ATTEMPT_WINDOW_MS = WINDOW_MS;
|
|
20
|
+
/** The number of attempts past which a subject is being backed off at all. */
|
|
21
|
+
const FIRST_THRESHOLD = THRESHOLDS[0]?.attempts ?? 5;
|
|
18
22
|
export function createRateLimiter(db, now = Date.now) {
|
|
19
23
|
const table = identifier(TABLES.loginAttempts, db.dialect);
|
|
20
24
|
async function countRecent(subject) {
|
|
@@ -42,6 +46,31 @@ export function createRateLimiter(db, now = Date.now) {
|
|
|
42
46
|
clear: async (subject) => {
|
|
43
47
|
await db.query(sql `delete from ${table} where subject = ${subject}`);
|
|
44
48
|
},
|
|
49
|
+
recentFailures: async (options) => {
|
|
50
|
+
const since = new Date(now() - WINDOW_MS).toISOString();
|
|
51
|
+
const minAttempts = options?.minAttempts ?? FIRST_THRESHOLD;
|
|
52
|
+
const limit = options?.limit ?? 20;
|
|
53
|
+
// Pruned before counting, not after: a row outside the window can never
|
|
54
|
+
// change an answer, so deleting it first keeps the aggregate honest even
|
|
55
|
+
// if the delete and the select were to see slightly different clocks.
|
|
56
|
+
await db.query(sql `delete from ${table} where at < ${since}`);
|
|
57
|
+
const result = await db.query(sql `
|
|
58
|
+
select subject, count(*) as n, min(at) as first_at, max(at) as last_at
|
|
59
|
+
from ${table}
|
|
60
|
+
where at >= ${since}
|
|
61
|
+
group by subject
|
|
62
|
+
order by count(*) desc`);
|
|
63
|
+
return result.rows
|
|
64
|
+
.map((row) => ({
|
|
65
|
+
subject: row.subject,
|
|
66
|
+
attempts: Number(row.n),
|
|
67
|
+
firstAt: row.first_at,
|
|
68
|
+
lastAt: row.last_at,
|
|
69
|
+
blocked: Number(row.n) >= FIRST_THRESHOLD,
|
|
70
|
+
}))
|
|
71
|
+
.filter((summary) => summary.attempts >= minAttempts)
|
|
72
|
+
.slice(0, limit);
|
|
73
|
+
},
|
|
45
74
|
};
|
|
46
75
|
}
|
|
47
76
|
//# sourceMappingURL=rate-limit.js.map
|
package/dist/rate-limit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AACzF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC;;;;;;;GAOG;AACH,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAChC,MAAM,UAAU,GAAuE;IACrF,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAC/B,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;IACjC,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;IACjC,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE;CAC1C,CAAA;
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"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"}
|
package/dist/resets.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* 30 minutes. Long enough to walk to the inbox and back, short enough that a
|
|
4
|
+
* reset link sitting in a mailbox archive is worthless within the hour — a
|
|
5
|
+
* reset token is a full account takeover if it leaks, so it gets a far
|
|
6
|
+
* shorter life than the 30-day session it can be exchanged for.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PASSWORD_RESET_TTL_MS: number;
|
|
9
|
+
export interface IssuedPasswordReset {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly userId: string;
|
|
12
|
+
/** Shown once, to be put in the link. Never stored, never recoverable. */
|
|
13
|
+
readonly token: string;
|
|
14
|
+
readonly expiresAt: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* What redeeming a token found. Separate cases rather than a boolean, so the
|
|
18
|
+
* caller can say *why* a link did not work — "this link has already been
|
|
19
|
+
* used" and "this link has expired" send a person to different next steps.
|
|
20
|
+
*/
|
|
21
|
+
export type PasswordResetOutcome = {
|
|
22
|
+
readonly kind: 'invalid';
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: 'expired';
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: 'used';
|
|
27
|
+
} | {
|
|
28
|
+
readonly kind: 'ready';
|
|
29
|
+
readonly userId: string;
|
|
30
|
+
readonly resetId: string;
|
|
31
|
+
};
|
|
32
|
+
export interface PasswordResetStore {
|
|
33
|
+
/**
|
|
34
|
+
* Issues a token for a user, invalidating any still outstanding for them.
|
|
35
|
+
*
|
|
36
|
+
* Only one live reset per person: asking again because the first mail never
|
|
37
|
+
* arrived must not leave two working links behind, and the newest request
|
|
38
|
+
* is always the one the person is actually looking at.
|
|
39
|
+
*/
|
|
40
|
+
issue(userId: string, options?: {
|
|
41
|
+
readonly ttlMs?: number;
|
|
42
|
+
}): Promise<IssuedPasswordReset>;
|
|
43
|
+
/**
|
|
44
|
+
* Consumes a token. Redeeming is the single-use point: a `ready` outcome is
|
|
45
|
+
* returned at most once for a given token, ever, even if two processes ask
|
|
46
|
+
* at the same instant.
|
|
47
|
+
*/
|
|
48
|
+
redeem(token: string): Promise<PasswordResetOutcome>;
|
|
49
|
+
/** Invalidates every outstanding reset for a user, used or not. */
|
|
50
|
+
revokeAllFor(userId: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export declare function createPasswordResetStore(db: DatabaseHandle, now?: () => number): PasswordResetStore;
|
|
53
|
+
//# sourceMappingURL=resets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resets.d.ts","sourceRoot":"","sources":["../src/resets.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAA0B,MAAM,eAAe,CAAA;AAoC3E;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAiB,CAAA;AAEnD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC1F;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACpD,mEAAmE;IACnE,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5C;AAiBD,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,cAAc,EAClB,GAAG,GAAE,MAAM,MAAiB,GAC3B,kBAAkB,CAmDpB"}
|
package/dist/resets.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { identifier, newId, sql } from '@cogenta/core';
|
|
3
|
+
import { TABLES } from './tables.js';
|
|
4
|
+
/**
|
|
5
|
+
* Password reset: a single-use, short-lived token bound to one user.
|
|
6
|
+
*
|
|
7
|
+
* Until now a person who forgot their password had no way back in — the only
|
|
8
|
+
* account command was `users create`, so the recovery procedure was "ask an
|
|
9
|
+
* administrator to make you a second account". This is the missing half.
|
|
10
|
+
*
|
|
11
|
+
* The token is opaque random bytes stored only as a hash, for the same reason
|
|
12
|
+
* a session token is (`sessions.ts`): a leaked table must hand out nothing
|
|
13
|
+
* live. It is deliberately **not** a signed/HMAC'd payload. A signature would
|
|
14
|
+
* let a link be validated without touching the database, and that is exactly
|
|
15
|
+
* what must not happen here — single use and revocation are properties of a
|
|
16
|
+
* row, not of a signature, and a signed token that has already been used is
|
|
17
|
+
* still a valid signature. The database round trip is the feature.
|
|
18
|
+
*/
|
|
19
|
+
const TOKEN_BYTES = 32;
|
|
20
|
+
/**
|
|
21
|
+
* Hex, not base64url — and that is not a stylistic preference.
|
|
22
|
+
*
|
|
23
|
+
* base64url's alphabet contains `-`. Roughly one token in sixty-four therefore
|
|
24
|
+
* *starts* with a dash, and `cogenta users reset-password --token -Xy...` is
|
|
25
|
+
* then parsed as an unknown option rather than as a value: the command refuses
|
|
26
|
+
* a perfectly valid token with a usage error, for one person in sixty-four.
|
|
27
|
+
* That is exactly the kind of defect that never shows up in a test written
|
|
28
|
+
* once and passes for months. Hex costs 32 characters of length and has no
|
|
29
|
+
* character that any shell, URL or argument parser treats as special.
|
|
30
|
+
*/
|
|
31
|
+
function encodeToken(bytes) {
|
|
32
|
+
return bytes.toString('hex');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 30 minutes. Long enough to walk to the inbox and back, short enough that a
|
|
36
|
+
* reset link sitting in a mailbox archive is worthless within the hour — a
|
|
37
|
+
* reset token is a full account takeover if it leaks, so it gets a far
|
|
38
|
+
* shorter life than the 30-day session it can be exchanged for.
|
|
39
|
+
*/
|
|
40
|
+
export const PASSWORD_RESET_TTL_MS = 30 * 60 * 1000;
|
|
41
|
+
function issueToken() {
|
|
42
|
+
return encodeToken(randomBytes(TOKEN_BYTES));
|
|
43
|
+
}
|
|
44
|
+
function hashToken(token) {
|
|
45
|
+
return createHash('sha256').update(token).digest('base64url');
|
|
46
|
+
}
|
|
47
|
+
export function createPasswordResetStore(db, now = Date.now) {
|
|
48
|
+
const table = identifier(TABLES.passwordResets, db.dialect);
|
|
49
|
+
async function markUsed(id, at) {
|
|
50
|
+
// The `used_at is null` guard is what makes single use real rather than
|
|
51
|
+
// hoped for: two concurrent redemptions both read a usable row, but only
|
|
52
|
+
// one UPDATE matches, and the other sees zero rows affected.
|
|
53
|
+
const result = await db.query(sql `update ${table} set used_at = ${at} where id = ${id} and used_at is null`);
|
|
54
|
+
return result.rowsAffected > 0;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
issue: async (userId, options) => {
|
|
58
|
+
await db.query(sql `delete from ${table} where user_id = ${userId} and used_at is null`);
|
|
59
|
+
const token = issueToken();
|
|
60
|
+
const id = newId(now);
|
|
61
|
+
const created = new Date(now()).toISOString();
|
|
62
|
+
const expires = new Date(now() + (options?.ttlMs ?? PASSWORD_RESET_TTL_MS)).toISOString();
|
|
63
|
+
await db.query(sql `
|
|
64
|
+
insert into ${table} (id, user_id, token_hash, created_at, expires_at, used_at)
|
|
65
|
+
values (${id}, ${userId}, ${hashToken(token)}, ${created}, ${expires}, ${null})`);
|
|
66
|
+
return { id, userId, token, expiresAt: expires };
|
|
67
|
+
},
|
|
68
|
+
redeem: async (token) => {
|
|
69
|
+
const result = await db.query(sql `select * from ${table} where token_hash = ${hashToken(token)}`);
|
|
70
|
+
const row = result.rows[0];
|
|
71
|
+
if (row === undefined)
|
|
72
|
+
return { kind: 'invalid' };
|
|
73
|
+
if (row.used_at !== null)
|
|
74
|
+
return { kind: 'used' };
|
|
75
|
+
const at = now();
|
|
76
|
+
if (new Date(row.expires_at).getTime() <= at)
|
|
77
|
+
return { kind: 'expired' };
|
|
78
|
+
const claimed = await markUsed(row.id, new Date(at).toISOString());
|
|
79
|
+
// Lost the race: another caller consumed it between the read and here.
|
|
80
|
+
if (!claimed)
|
|
81
|
+
return { kind: 'used' };
|
|
82
|
+
return { kind: 'ready', userId: row.user_id, resetId: row.id };
|
|
83
|
+
},
|
|
84
|
+
revokeAllFor: async (userId) => {
|
|
85
|
+
await db.query(sql `delete from ${table} where user_id = ${userId}`);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=resets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resets.js","sourceRoot":"","sources":["../src/resets.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { DatabaseHandle } from '@cogenta/core';
|
|
2
2
|
import type { CollectionDefinition } from '@cogenta/schema';
|
|
3
|
+
import { createApiKeyStore } from './api-keys.js';
|
|
3
4
|
import { createAuditLog } from './audit.js';
|
|
4
5
|
import { createCredentialStore } from './credentials.js';
|
|
5
6
|
import { createAuthService } from './login.js';
|
|
6
7
|
import { createRateLimiter } from './rate-limit.js';
|
|
8
|
+
import { createPasswordResetStore } from './resets.js';
|
|
7
9
|
import { createSessionStore } from './sessions.js';
|
|
8
10
|
import { createUserStore } from './users.js';
|
|
9
11
|
import type { WebAuthnConfig } from './webauthn.js';
|
|
@@ -25,6 +27,9 @@ export interface AuthStore {
|
|
|
25
27
|
readonly audit: ReturnType<typeof createAuditLog>;
|
|
26
28
|
readonly rateLimit: ReturnType<typeof createRateLimiter>;
|
|
27
29
|
readonly login: ReturnType<typeof createAuthService>;
|
|
30
|
+
/** Self-service "forgot password" tokens (L13's HTTP route, `resets.ts`). */
|
|
31
|
+
readonly resets: ReturnType<typeof createPasswordResetStore>;
|
|
32
|
+
readonly apiKeys: ReturnType<typeof createApiKeyStore>;
|
|
28
33
|
}
|
|
29
34
|
export declare function createAuthStore(options: AuthStoreOptions): Promise<AuthStore>;
|
|
30
35
|
//# sourceMappingURL=store.d.ts.map
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACrD,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAC5B;AAED,0EAA0E;AAC1E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;IAClD,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IAC9D,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;IACxD,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;IACjD,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;IACxD,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACrD,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAC5B;AAED,0EAA0E;AAC1E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;IAClD,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IAC9D,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;IACxD,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;IACjD,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;IACxD,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;IACpD,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAA;IAC5D,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;CACvD;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAqBnF"}
|
package/dist/store.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { createApiKeyStore } from './api-keys.js';
|
|
1
2
|
import { createAuditLog } from './audit.js';
|
|
2
3
|
import { createCredentialStore } from './credentials.js';
|
|
3
4
|
import { createAuthService } from './login.js';
|
|
4
5
|
import { createRateLimiter } from './rate-limit.js';
|
|
6
|
+
import { createPasswordResetStore } from './resets.js';
|
|
5
7
|
import { createSessionStore } from './sessions.js';
|
|
6
8
|
import { ensureAuthTables } from './tables.js';
|
|
7
9
|
import { createUserStore } from './users.js';
|
|
@@ -14,6 +16,8 @@ export async function createAuthStore(options) {
|
|
|
14
16
|
sessions: createSessionStore(options.db, now),
|
|
15
17
|
audit: createAuditLog(options.db, now),
|
|
16
18
|
rateLimit: createRateLimiter(options.db, now),
|
|
19
|
+
resets: createPasswordResetStore(options.db, now),
|
|
20
|
+
apiKeys: createApiKeyStore(options.db, now),
|
|
17
21
|
login: createAuthService({
|
|
18
22
|
db: options.db,
|
|
19
23
|
signingKey: options.signingKey,
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA2B5C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAyB;IAC7D,MAAM,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAA;IAEnC,OAAO;QACL,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QACvC,WAAW,EAAE,qBAAqB,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QACnD,QAAQ,EAAE,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QAC7C,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QACtC,SAAS,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QAC7C,MAAM,EAAE,wBAAwB,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QACjD,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC;QAC3C,KAAK,EAAE,iBAAiB,CAAC;YACvB,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,GAAG;YACH,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;SAC1E,CAAC;KACH,CAAA;AACH,CAAC"}
|
package/dist/tables.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export declare const TABLES: {
|
|
|
4
4
|
readonly credentials: 'cogenta_credentials';
|
|
5
5
|
readonly sessions: 'cogenta_sessions';
|
|
6
6
|
readonly loginAttempts: 'cogenta_login_attempts';
|
|
7
|
+
readonly passwordResets: 'cogenta_password_resets';
|
|
7
8
|
readonly auditLog: 'cogenta_audit_log';
|
|
9
|
+
readonly apiKeys: 'cogenta_api_keys';
|
|
8
10
|
};
|
|
9
11
|
/**
|
|
10
12
|
* Every table this package owns.
|
package/dist/tables.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EAKpB,MAAM,eAAe,CAAA;AAEtB,eAAO,MAAM,MAAM;aACjB,KAAK,EAAE,eAAe;aACtB,WAAW,EAAE,qBAAqB;aAClC,QAAQ,EAAE,kBAAkB;aAC5B,aAAa,EAAE,wBAAwB;aACvC,QAAQ,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EAKpB,MAAM,eAAe,CAAA;AAEtB,eAAO,MAAM,MAAM;aACjB,KAAK,EAAE,eAAe;aACtB,WAAW,EAAE,qBAAqB;aAClC,QAAQ,EAAE,kBAAkB;aAC5B,aAAa,EAAE,wBAAwB;aACvC,cAAc,EAAE,yBAAyB;aACzC,QAAQ,EAAE,mBAAmB;aAC7B,OAAO,EAAE,kBAAkB;CACnB,CAAA;AAWV;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6HxE"}
|
package/dist/tables.js
CHANGED
|
@@ -4,7 +4,9 @@ export const TABLES = {
|
|
|
4
4
|
credentials: 'cogenta_credentials',
|
|
5
5
|
sessions: 'cogenta_sessions',
|
|
6
6
|
loginAttempts: 'cogenta_login_attempts',
|
|
7
|
+
passwordResets: 'cogenta_password_resets',
|
|
7
8
|
auditLog: 'cogenta_audit_log',
|
|
9
|
+
apiKeys: 'cogenta_api_keys',
|
|
8
10
|
};
|
|
9
11
|
/** `varchar` on Postgres/MySQL, `text` on SQLite — encapsulated once, here. */
|
|
10
12
|
function textColumn(dialect, length) {
|
|
@@ -26,7 +28,9 @@ export async function ensureAuthTables(db) {
|
|
|
26
28
|
const credentials = identifier(TABLES.credentials, d);
|
|
27
29
|
const sessions = identifier(TABLES.sessions, d);
|
|
28
30
|
const loginAttempts = identifier(TABLES.loginAttempts, d);
|
|
31
|
+
const passwordResets = identifier(TABLES.passwordResets, d);
|
|
29
32
|
const auditLog = identifier(TABLES.auditLog, d);
|
|
33
|
+
const apiKeys = identifier(TABLES.apiKeys, d);
|
|
30
34
|
const t512 = textColumn(d, 512);
|
|
31
35
|
const t255 = textColumn(d, 255);
|
|
32
36
|
const t64 = textColumn(d, 64);
|
|
@@ -79,6 +83,19 @@ export async function ensureAuthTables(db) {
|
|
|
79
83
|
at ${t64} not null
|
|
80
84
|
)`);
|
|
81
85
|
await db.query(sql `
|
|
86
|
+
create table if not exists ${passwordResets} (
|
|
87
|
+
id ${t64} not null primary key,
|
|
88
|
+
user_id ${t64} not null,
|
|
89
|
+
-- Hashed like a session token: a leaked table must not hand out a live
|
|
90
|
+
-- account takeover. Unique so the same token can never name two rows.
|
|
91
|
+
token_hash ${t512} not null unique,
|
|
92
|
+
created_at ${t64} not null,
|
|
93
|
+
expires_at ${t64} not null,
|
|
94
|
+
-- Null while the token is still usable; stamped once, and the stamping
|
|
95
|
+
-- is what makes the token single-use (see resets.ts).
|
|
96
|
+
used_at ${t64}
|
|
97
|
+
)`);
|
|
98
|
+
await db.query(sql `
|
|
82
99
|
create table if not exists ${auditLog} (
|
|
83
100
|
id ${t64} not null primary key,
|
|
84
101
|
at ${t64} not null,
|
|
@@ -91,9 +108,32 @@ export async function ensureAuthTables(db) {
|
|
|
91
108
|
hash ${t64} not null,
|
|
92
109
|
previous_hash ${t64}
|
|
93
110
|
)`);
|
|
111
|
+
await db.query(sql `
|
|
112
|
+
create table if not exists ${apiKeys} (
|
|
113
|
+
id ${t64} not null primary key,
|
|
114
|
+
name ${t255} not null,
|
|
115
|
+
-- Hashed like a session token (sha256 over a 256-bit random secret):
|
|
116
|
+
-- unlike a password, this secret is never chosen by a person, so there
|
|
117
|
+
-- is no low-entropy guess for a slow, memory-hard hash to protect
|
|
118
|
+
-- against. A leaked table still hands out nothing live.
|
|
119
|
+
key_hash ${t512} not null unique,
|
|
120
|
+
-- The first 12 characters of the raw key, stored in the clear so a
|
|
121
|
+
-- list of keys is recognisable without ever showing the rest again.
|
|
122
|
+
key_prefix ${t64} not null,
|
|
123
|
+
-- An open set of role names, exactly like a user's roles (contract A)
|
|
124
|
+
-- — a key acts as a machine actor scoped to exactly these roles, never
|
|
125
|
+
-- to more than it was granted.
|
|
126
|
+
scope text not null,
|
|
127
|
+
created_by ${t64},
|
|
128
|
+
created_at ${t64} not null,
|
|
129
|
+
expires_at ${t64},
|
|
130
|
+
revoked_at ${t64},
|
|
131
|
+
last_used_at ${t64}
|
|
132
|
+
)`);
|
|
94
133
|
await createIndexIfMissing(db, 'cogenta_credentials_user', credentials, sql `(user_id)`);
|
|
95
134
|
await createIndexIfMissing(db, 'cogenta_sessions_user', sessions, sql `(user_id)`);
|
|
96
135
|
await createIndexIfMissing(db, 'cogenta_login_attempts_subject_at', loginAttempts, sql `(subject, at)`);
|
|
136
|
+
await createIndexIfMissing(db, 'cogenta_password_resets_user', passwordResets, sql `(user_id)`);
|
|
97
137
|
}
|
|
98
138
|
async function createIndexIfMissing(db, name, table, columns) {
|
|
99
139
|
await db
|
package/dist/tables.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,UAAU,EAEV,GAAG,EACH,SAAS,GACV,MAAM,eAAe,CAAA;AAEtB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,EAAE,eAAe;IACtB,WAAW,EAAE,qBAAqB;IAClC,QAAQ,EAAE,kBAAkB;IAC5B,aAAa,EAAE,wBAAwB;IACvC,QAAQ,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -61,4 +61,34 @@ export interface RecordAuditInput {
|
|
|
61
61
|
readonly entryId?: string | undefined;
|
|
62
62
|
readonly diff?: Readonly<Record<string, unknown>> | undefined;
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* A machine-to-machine bearer credential (L13 task 8).
|
|
66
|
+
*
|
|
67
|
+
* A key is scoped to an explicit, open set of role names — exactly like a
|
|
68
|
+
* user's `roles` — chosen once at creation and never derived from the
|
|
69
|
+
* account that created it. A key can act with fewer permissions than an
|
|
70
|
+
* admin has, but never with more than it was granted.
|
|
71
|
+
*/
|
|
72
|
+
export interface ApiKey {
|
|
73
|
+
readonly id: string;
|
|
74
|
+
readonly name: string;
|
|
75
|
+
/** The first 12 characters of the raw key, safe to show forever. */
|
|
76
|
+
readonly prefix: string;
|
|
77
|
+
readonly scope: readonly string[];
|
|
78
|
+
readonly createdBy: string | null;
|
|
79
|
+
readonly createdAt: string;
|
|
80
|
+
readonly expiresAt: string | undefined;
|
|
81
|
+
readonly revokedAt: string | undefined;
|
|
82
|
+
readonly lastUsedAt: string | undefined;
|
|
83
|
+
}
|
|
84
|
+
export interface CreateApiKeyInput {
|
|
85
|
+
readonly name: string;
|
|
86
|
+
readonly scope: readonly string[];
|
|
87
|
+
readonly createdBy: string | null;
|
|
88
|
+
readonly expiresAt?: string | undefined;
|
|
89
|
+
}
|
|
90
|
+
/** An API key as returned once, at creation — `key` is never stored or shown again. */
|
|
91
|
+
export interface IssuedApiKey extends ApiKey {
|
|
92
|
+
readonly key: string;
|
|
93
|
+
}
|
|
64
94
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,gBAAgB,YAAI,UAAU,EAAE,MAAM,EAAE,UAAU,CAAU,CAAA;AACzE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9D,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAA;IACvD,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAA;CAC9D"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cogenta/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Identity, sessions and credentials: password, TOTP and WebAuthn, plus the append-only audit log.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@simplewebauthn/server": "^13.3.2",
|
|
31
|
-
"@cogenta/core": "0.
|
|
32
|
-
"@cogenta/schema": "0.
|
|
31
|
+
"@cogenta/core": "0.4.0",
|
|
32
|
+
"@cogenta/schema": "0.3.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"typescript": "^7.0.2",
|