@nacre.work/api 0.17.5 → 0.19.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/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -1
- package/dist/login.d.ts +166 -1
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +210 -3
- package/dist/login.js.map +1 -1
- package/dist/main.js +71 -1
- package/dist/main.js.map +1 -1
- package/dist/recovery.d.ts +91 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +199 -0
- package/dist/recovery.js.map +1 -0
- package/dist/second-factor.d.ts +202 -0
- package/dist/second-factor.d.ts.map +1 -0
- package/dist/second-factor.js +479 -0
- package/dist/second-factor.js.map +1 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +747 -38
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { configureLogging, collectDatabaseGauges, createMetrics, createPool, loadConfig, loadedExtensions, loadModules, logger, loadJwtKeys, keyFingerprint, protectedResourceMetadata, Redis, RedisCache, Registry, S3, VectorStore, vectorStoreOptions, pendingMigrations, withOrg, ConfigError, installGuards, onListenError, } from '@nacre.work/core';
|
|
1
|
+
import { configureLogging, collectDatabaseGauges, createMetrics, createPool, loadConfig, loadedExtensions, loadModules, logger, loadJwtKeys, createMailer, loadMailConfig, loadSecondFactorKey, keyFingerprint, protectedResourceMetadata, Redis, RedisCache, Registry, S3, VectorStore, vectorStoreOptions, pendingMigrations, withOrg, ConfigError, installGuards, onListenError, } from '@nacre.work/core';
|
|
2
2
|
import { HttpEmbedder, NacreIngest, NacreSearchService, PostgresAudit, PostgresAuditReader, PostgresDocuments, PostgresGrants, PostgresJobs, PostgresLayers, PostgresReferenceQueries, PostgresReindex, PostgresEmbeddingProviders, PostgresWorkspaces, } from './adapters.js';
|
|
3
3
|
import { SignJWT } from 'jose';
|
|
4
4
|
import { Idempotency } from './idempotency.js';
|
|
5
5
|
import { Login } from './login.js';
|
|
6
|
+
import { PasswordRecovery } from './recovery.js';
|
|
7
|
+
import { SecondFactors } from './second-factor.js';
|
|
6
8
|
import { PostgresOAuthAuthorizations, PostgresOAuthClients, PostgresOAuthConsents, PostgresOAuthRefreshTokens, } from './oauth-store.js';
|
|
7
9
|
import { rerankerFor } from './rerank.js';
|
|
8
10
|
import { RateLimiter } from './limits.js';
|
|
@@ -92,6 +94,70 @@ async function main() {
|
|
|
92
94
|
logger.warn('idempotency cache unavailable; request processed uncached', { error: String(error).slice(0, 200) });
|
|
93
95
|
},
|
|
94
96
|
});
|
|
97
|
+
/*
|
|
98
|
+
* The second factor, and the two kinds are configured differently.
|
|
99
|
+
*
|
|
100
|
+
* TOTP needs `NACRE_2FA_KEY` — its secret is shared, so it has to be kept and
|
|
101
|
+
* therefore sealed, and there is no mode where one is stored unsealed.
|
|
102
|
+
* WebAuthn needs no key at all: what is stored is a public key and a counter,
|
|
103
|
+
* and a dump of those produces no assertion. So this is constructed on every
|
|
104
|
+
* deployment, and `SecondFactors.kinds` is what decides which of the two a
|
|
105
|
+
* screen may offer.
|
|
106
|
+
*
|
|
107
|
+
* The relying party comes from `NACRE_CANONICAL_URL`, which every deployment
|
|
108
|
+
* already sets, rather than from a variable of its own. A `NACRE_WEBAUTHN_*`
|
|
109
|
+
* would be a second answer to "what is this installation's address", and a
|
|
110
|
+
* second answer to that is how a deployment ends up with credentials bound to
|
|
111
|
+
* a name it no longer serves.
|
|
112
|
+
*/
|
|
113
|
+
const secondFactorKey = loadSecondFactorKey();
|
|
114
|
+
const canonical = new URL(config.canonicalUrl);
|
|
115
|
+
const secondFactors = new SecondFactors({
|
|
116
|
+
pool,
|
|
117
|
+
key: secondFactorKey,
|
|
118
|
+
// What an authenticator prints above the account. The issuer of the
|
|
119
|
+
// tokens is what this installation already calls itself, so a person
|
|
120
|
+
// with two Nacre deployments sees two distinguishable entries.
|
|
121
|
+
issuer: config.jwtIssuer,
|
|
122
|
+
relyingParty: {
|
|
123
|
+
// The **host** and never the origin: a relying party id is a registrable
|
|
124
|
+
// domain, so a scheme or a port in it is a credential no authenticator
|
|
125
|
+
// will make.
|
|
126
|
+
id: canonical.hostname,
|
|
127
|
+
name: canonical.hostname,
|
|
128
|
+
/*
|
|
129
|
+
* Where a page may run the ceremony from. The canonical origin, plus the
|
|
130
|
+
* browser origins this API already admits — the console is served from
|
|
131
|
+
* the API's own origin unless a deployment has said otherwise, and if it
|
|
132
|
+
* has, it has said so in `NACRE_API_ALLOWED_ORIGINS`.
|
|
133
|
+
*
|
|
134
|
+
* Compared for equality by the verifier. A suffix match would admit
|
|
135
|
+
* `evil-nacre.work`, which is the hole a phishing-resistant factor exists
|
|
136
|
+
* to close.
|
|
137
|
+
*/
|
|
138
|
+
origins: [canonical.origin, ...config.apiAllowedOrigins],
|
|
139
|
+
},
|
|
140
|
+
role: APP_ROLE,
|
|
141
|
+
});
|
|
142
|
+
/*
|
|
143
|
+
* The sender, when the deployment configured one.
|
|
144
|
+
*
|
|
145
|
+
* `undefined` otherwise, and every route that would send is then not mounted
|
|
146
|
+
* — `/v1/auth/methods` reports it, so the console leaves the recovery link
|
|
147
|
+
* off the screen rather than showing one that answers 404.
|
|
148
|
+
*/
|
|
149
|
+
const mailer = createMailer(loadMailConfig());
|
|
150
|
+
const recovery = mailer === undefined
|
|
151
|
+
? undefined
|
|
152
|
+
: new PasswordRecovery({
|
|
153
|
+
pool,
|
|
154
|
+
mailer,
|
|
155
|
+
// From configuration and never from a `Host` header: a recovery link
|
|
156
|
+
// built from a request header is a recovery link pointing wherever
|
|
157
|
+
// the requester said.
|
|
158
|
+
consoleBase: config.canonicalUrl,
|
|
159
|
+
role: APP_ROLE,
|
|
160
|
+
});
|
|
95
161
|
const login = new Login({
|
|
96
162
|
pool,
|
|
97
163
|
// The signing key, which for Ed25519 is the private half — the only place
|
|
@@ -105,6 +171,7 @@ async function main() {
|
|
|
105
171
|
accessTokenTtl: config.accessTokenTtl,
|
|
106
172
|
refreshTokenTtl: config.refreshTokenTtl,
|
|
107
173
|
role: APP_ROLE,
|
|
174
|
+
...(secondFactors === undefined ? {} : { secondFactors }),
|
|
108
175
|
});
|
|
109
176
|
// What this process cannot serve a request without.
|
|
110
177
|
//
|
|
@@ -260,6 +327,9 @@ async function main() {
|
|
|
260
327
|
layers: new PostgresLayers(pool, vectors, APP_ROLE, principalsCache),
|
|
261
328
|
workspaces: new PostgresWorkspaces(pool, APP_ROLE, principalsCache),
|
|
262
329
|
embeddingProviders: new PostgresEmbeddingProviders(pool, APP_ROLE),
|
|
330
|
+
...(secondFactors === undefined ? {} : { secondFactors }),
|
|
331
|
+
...(recovery === undefined ? {} : { recovery }),
|
|
332
|
+
...(mailer === undefined ? {} : { mailer }),
|
|
263
333
|
grants: new PostgresGrants(pool, APP_ROLE, principalsCache),
|
|
264
334
|
serviceAccounts: new PostgresServiceAccounts(pool, APP_ROLE),
|
|
265
335
|
users: new PostgresUsers(pool, APP_ROLE),
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,MAAM,EACN,WAAW,EACX,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,yBAAyB,EACzB,KAAK,EACL,UAAU,EACV,QAAQ,EACR,EAAE,EACF,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,OAAO,EACP,WAAW,EACX,aAAa,EACb,aAAa,GACd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,WAAW,EAAmC,MAAM,aAAa,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC;;;;;;GAMG;AAEH,MAAM,QAAQ,GAAG,WAAW,CAAA;AAE5B,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAE3B,+EAA+E;IAC/E,+EAA+E;IAC/E,qCAAqC;IACrC,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;IAEtE,8EAA8E;IAC9E,+EAA+E;IAC/E,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAM,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAEjC,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;IAEzB,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;IAClF,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3D,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAEvE,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;IAC/B,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;IACvC,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEhE,2EAA2E;IAC3E,6EAA6E;IAC7E,kEAAkE;IAClE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEjD,wEAAwE;IACxE,8EAA8E;IAC9E,yEAAyE;IACzE,2EAA2E;IAC3E,iBAAiB;IACjB,EAAE;IACF,8EAA8E;IAC9E,wEAAwE;IACxE,6EAA6E;IAC7E,gDAAgD;IAChD,MAAM,eAAe,GAAG,EAAE,KAAK,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,CAAA;IAGxF,MAAM,aAAa,GAAkC;QACnD,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,gBAAgB,EAAE,aAAa,EAAE,EAAE,EAAE;QAC7D,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,IAAI,EAAE;QAChE,4EAA4E;QAC5E,yEAAyE;QACzE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,GAAG,EAAE;QAC9D,uEAAuE;QACvE,wEAAwE;QACxE,4DAA4D;QAC5D,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,uBAAuB,EAAE,aAAa,EAAE,GAAG,EAAE;KAC5E,CAAA;IAED,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC;QAC7B,KAAK;QACL,QAAQ,EAAE,aAAa;QACvB,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;YAC9B,wEAAwE;YACxE,qEAAqE;YACrE,qEAAqE;YACrE,6CAA6C;YAC7C,EAAE;YACF,yEAAyE;YACzE,kEAAkE;YAClE,mEAAmE;YACnE,wCAAwC;YACxC,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;YAC9C,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE,EAAE,QAAQ;gBACnE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3C,CAAC;KACF,CAAC,CAAA;IAEF,oEAAoE;IACpE,yEAAyE;IACzE,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAEpC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC;QAClC,KAAK;QACL,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,CAAC,IAAI,CAAC,2DAA2D,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QAClH,CAAC;KACF,CAAC,CAAA;IAEF;;;;;;;;;;;;;;;OAeG;IACH,MAAM,eAAe,GAAG,mBAAmB,EAAE,CAAA;IAC7C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IAC9C,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC;QACtC,IAAI;QACJ,GAAG,EAAE,eAAe;QACpB,oEAAoE;QACpE,qEAAqE;QACrE,+DAA+D;QAC/D,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,YAAY,EAAE;YACZ,yEAAyE;YACzE,uEAAuE;YACvE,aAAa;YACb,EAAE,EAAE,SAAS,CAAC,QAAQ;YACtB,IAAI,EAAE,SAAS,CAAC,QAAQ;YACxB;;;;;;;;;eASG;YACH,OAAO,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,iBAAiB,CAAC;SACzD;QACD,IAAI,EAAE,QAAQ;KACf,CAAC,CAAA;IAEF;;;;;;OAMG;IACH,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,EAAE,CAAC,CAAA;IAC7C,MAAM,QAAQ,GACZ,MAAM,KAAK,SAAS;QAClB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,gBAAgB,CAAC;YACnB,IAAI;YACJ,MAAM;YACN,qEAAqE;YACrE,mEAAmE;YACnE,sBAAsB;YACtB,WAAW,EAAE,MAAM,CAAC,YAAY;YAChC,IAAI,EAAE,QAAQ;SACf,CAAC,CAAA;IAER,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,IAAI;QACJ,0EAA0E;QAC1E,0EAA0E;QAC1E,OAAO;QACP,GAAG,EAAE,GAAG,CAAC,OAAO;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;QACxD,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,QAAQ,EAAE,MAAM,CAAC,WAAW;QAC5B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,IAAI,EAAE,QAAQ;QACd,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;KAC1D,CAAC,CAAA;IAEF,oDAAoD;IACpD,EAAE;IACF,6EAA6E;IAC7E,qEAAqE;IACrE,+EAA+E;IAC/E,6EAA6E;IAC7E,gEAAgE;IAChE,EAAE;IACF,4EAA4E;IAC5E,6EAA6E;IAC7E,sEAAsE;IACtE,aAAa;IACb,MAAM,KAAK,GAAG,KAAK,IAAsC,EAAE;QACzD,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAClE,OAAO,CAAC,IAAI,EAAE,sCAAsC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;gBAChE,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;gBACzB,OAAO,IAAI,CAAA;YACb,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YACzC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YAClC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YAC/B,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;YACvF,6DAA6D;YAC7D,EAAE;YACF,wEAAwE;YACxE,uEAAuE;YACvE,sEAAsE;YACtE,yEAAyE;YACzE,mEAAmE;YACnE,sDAAsD;YACtD,EAAE;YACF,kEAAkE;YAClE,8DAA8D;YAC9D,EAAE;YACF,qEAAqE;YACrE,wEAAwE;YACxE,mEAAmE;YACnE,qEAAqE;YACrE,uEAAuE;YACvE,iEAAiE;YACjE,EAAE;YACF,kEAAkE;YAClE,uEAAuE;YACvE,iCAAiC;YACjC,iBAAiB,CAAC,IAAI,CAAC;iBACpB,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gBAChB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,IAAI,CAAA;gBACrC,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE;oBACzC,OAAO,EAAE,OAAO,CAAC,MAAM;oBACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;iBACjB,CAAC,CAAA;gBACF,OAAO,KAAK,CAAA;YACd,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxB,mEAAmE;gBACnE,qEAAqE;gBACrE,uCAAuC;gBACvC,MAAM,CAAC,IAAI,CAAC,qCAAqC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;gBAC5E,OAAO,KAAK,CAAA;YACd,CAAC,CAAC;SACL,CAAC,CAAA;QACF,OAAO;YACL,QAAQ;YACR,MAAM;YACN,KAAK,EAAE,OAAO;YACd,MAAM;YACN,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;SAC5C,CAAA;IACH,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,SAAS,CAAC;QACvB,MAAM,EAAE;YACN,GAAG,EAAE,GAAG,CAAC,YAAY;YACrB,yEAAyE;YACzE,kEAAkE;YAClE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;YACtE,UAAU,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC;YAC3B,MAAM,EAAE,MAAM,CAAC,SAAS;YACxB,QAAQ,EAAE,MAAM,CAAC,WAAW;YAC5B,sEAAsE;YACtE,wEAAwE;YACxE,8BAA8B;YAC9B,GAAG,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC;SACxC;QACD,OAAO,EAAE,QAAQ;QACjB,gBAAgB,EAAE,yBAAyB,CAAC;YAC1C,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,6DAA6D;YAC7D,wEAAwE;YACxE,0EAA0E;YAC1E,yEAAyE;YACzE,mEAAmE;YACnE,iDAAiD;YACjD,mBAAmB,EACjB,MAAM,CAAC,wBAAwB,KAAK,EAAE;gBACpC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACzC,CAAC,CAAC,MAAM,CAAC,wBAAwB;SACtC,CAAC;QACF,4EAA4E;QAC5E,4EAA4E;QAC5E,wEAAwE;QACxE,UAAU;QACV,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QACrD,0EAA0E;QAC1E,uEAAuE;QACvE,iCAAiC;QACjC,OAAO,EAAE,OAAO;QAChB,KAAK;QACL,YAAY,EAAE,MAAM,CAAC,gBAAgB;QACrC,qEAAqE;QACrE,mEAAmE;QACnE,aAAa,EAAE,OAAO,KAAK,SAAS;QACpC,MAAM;QACN,aAAa;QACb,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;QACnF,cAAc,EAAE,MAAM,CAAC,iBAAiB;QACxC,WAAW;QACX,KAAK;QACL,WAAW,EAAE,IAAI,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC;QACrE,OAAO,EAAE,IAAI,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC;QACtE,gBAAgB,EAAE,IAAI,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC;QAC/E,SAAS,EAAE,IAAI,iBAAiB,CAC9B,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,eAAe,EACf,OAAO,KAAK,SAAS;YACnB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CACtE;QACD,MAAM,EAAE,IAAI,kBAAkB,CAAC;YAC7B,eAAe;YACf,IAAI;YACJ,OAAO;YACP,uEAAuE;YACvE,2CAA2C;YAC3C,WAAW,EAAE,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;YAC5D,IAAI,EAAE,QAAQ;YACd,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;YAC/C,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE;gBACxB,qEAAqE;gBACrE,qEAAqE;gBACrE,sEAAsE;gBACtE,mEAAmE;gBACnE,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YACtG,CAAC;SACF,CAAC;QACF,MAAM,EAAE,IAAI,WAAW,CAAC;YACtB,IAAI;YACJ,eAAe;YACf,SAAS,EAAE,OAAO;YAClB,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;YAC7C,IAAI,EAAE,QAAQ;SACf,CAAC;QACF,KAAK,EAAE,IAAI,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC;QACxC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,IAAI,EAAE,IAAI,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC;QACvD,MAAM,EAAE,IAAI,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC;QACpE,UAAU,EAAE,IAAI,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC;QACnE,kBAAkB,EAAE,IAAI,0BAA0B,CAAC,IAAI,EAAE,QAAQ,CAAC;QAClE,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;QACzD,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3C,MAAM,EAAE,IAAI,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,CAAC;QAC3D,eAAe,EAAE,IAAI,uBAAuB,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC5D,KAAK,EAAE,IAAI,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC;QACxC,MAAM,EAAE,IAAI,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC;QAE1C;;;;;;;;;WASG;QACH,KAAK,EAAE;YACL,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,iEAAiE;YACjE,wEAAwE;YACxE,yEAAyE;YACzE,+BAA+B;YAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,OAAO,EAAE,IAAI,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC;YACjD,cAAc,EAAE,IAAI,2BAA2B,CAAC,IAAI,EAAE,QAAQ,CAAC;YAC/D,QAAQ,EAAE,IAAI,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC;YACnD,aAAa,EAAE,IAAI,0BAA0B,CAAC,IAAI,EAAE,QAAQ,CAAC;YAC7D,mEAAmE;YACnE,uEAAuE;YACvE,mEAAmE;YACnE,yEAAyE;YACzE,iBAAiB,EAAE,MAAM,CAAC,eAAe;YACzC,gBAAgB,EAAE,MAAM,CAAC,cAAc;YACvC;;;;;;;;;;;;;;;;;eAiBG;YACH,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,CAAA;gBACjC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;gBACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,CAAA;gBACpD,MAAM,WAAW,GAAG,MAAM,IAAI,OAAO,CAAC;oBACpC,GAAG,EAAE,QAAQ,CAAC,KAAK;oBACnB,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB;oBACtD,IAAI,EAAE,QAAQ;oBACd,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAClD,CAAC;qBACC,kBAAkB,CAAC;oBAClB,GAAG,EAAE,GAAG,CAAC,SAAS;oBAClB,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;iBACvD,CAAC;qBACD,UAAU,CACT,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM;oBAChC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;oBACzB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CACtC;qBACA,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;qBAC3B,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC;qBAC/B,WAAW,CAAC,GAAG,CAAC;qBAChB,iBAAiB,CAAC,GAAG,GAAG,GAAG,CAAC;qBAC5B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBACpB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;YACxC,CAAC;SACF;KACF,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;IAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACvB,4EAA4E;QAC5E,wEAAwE;QACxE,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI;YAC/B,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,MAAM,EAAE,MAAM,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,SAAS;YACtB,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC;YACzC,uEAAuE;YACvE,kEAAkE;YAClE,mCAAmC;YACnC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;gBAC7B,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7D,sEAAsE;YACtE,qEAAqE;YACrE,qEAAqE;YACrE,0CAA0C;YAC1C,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IAElC,aAAa,CAAC;QACZ,OAAO,EAAE,KAAK;QACd,wEAAwE;QACxE,wEAAwE;QACxE,2EAA2E;QAC3E,uEAAuE;QACvE,4EAA4E;QAC5E,uEAAuE;QACvE,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACnE,KAAK,CAAC,KAAK,EAAE,CAAA;YACb,MAAM,IAAI,CAAC,GAAG,EAAE,CAAA;QAClB,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type Mailer } from '@nacre.work/core';
|
|
2
|
+
import type { Pool } from 'pg';
|
|
3
|
+
/**
|
|
4
|
+
* Recovering a password, by email, without a `psql` session.
|
|
5
|
+
*
|
|
6
|
+
* ## The hole this closes
|
|
7
|
+
*
|
|
8
|
+
* `POST /v1/users/{id}/password` is an **administrator** setting somebody
|
|
9
|
+
* else's. The person who forgot theirs had no route, and on a
|
|
10
|
+
* single-administrator installation — which the open core mostly is — the
|
|
11
|
+
* administrator who forgot theirs had no route that did not go through the
|
|
12
|
+
* database. That is the model-offers-it-and-the-product-gives-no-route shape
|
|
13
|
+
* this repository keeps closing.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the token carries its organization
|
|
16
|
+
*
|
|
17
|
+
* `<org_id>.<secret>`. Redemption therefore knows the tenant before it reads
|
|
18
|
+
* anything, so this table is read through `withOrg` like every other and the
|
|
19
|
+
* one path a stranger can reach unauthenticated opens no cross-tenant read.
|
|
20
|
+
*
|
|
21
|
+
* Migration 0008 says `users` gets no `authenticating` policy "as a decision
|
|
22
|
+
* rather than an omission"; this keeps that decision rather than arguing with
|
|
23
|
+
* it. The organization id is not a secret from the person holding the link —
|
|
24
|
+
* it is in their own `/v1/me` — and the half beside it is.
|
|
25
|
+
*
|
|
26
|
+
* ## What a reset does not do
|
|
27
|
+
*
|
|
28
|
+
* **It does not touch a second factor.** If it did, an email account would be a
|
|
29
|
+
* way around one, which is the whole thing a second factor exists to not be.
|
|
30
|
+
* Somebody who resets a password still produces a code afterwards.
|
|
31
|
+
*
|
|
32
|
+
* It *does* end every other session: a reset is what somebody does when they
|
|
33
|
+
* think their password is known, and leaving the refresh tokens alive would
|
|
34
|
+
* leave whoever knows it signed in.
|
|
35
|
+
*/
|
|
36
|
+
/** An hour. Long enough to reach an inbox, short enough to be worth stealing. */
|
|
37
|
+
export declare const RESET_TTL_SECONDS = 3600;
|
|
38
|
+
/**
|
|
39
|
+
* The shortest password this will accept from a person choosing their own.
|
|
40
|
+
*
|
|
41
|
+
* Length and nothing else — no composition rule. A rule demanding a digit and a
|
|
42
|
+
* symbol produces `Password1!` and a person who writes it down; length is the
|
|
43
|
+
* only requirement that reliably buys entropy. The passwords this product
|
|
44
|
+
* *generates* are six words and a number, and are longer than this.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MIN_PASSWORD_LENGTH = 12;
|
|
47
|
+
export interface RecoveryDeps {
|
|
48
|
+
readonly pool: Pool;
|
|
49
|
+
readonly mailer: Mailer;
|
|
50
|
+
/** Where the link points. From configuration, never from a request header. */
|
|
51
|
+
readonly consoleBase: string;
|
|
52
|
+
readonly role?: string;
|
|
53
|
+
readonly now?: () => Date;
|
|
54
|
+
}
|
|
55
|
+
export type Redemption = 'reset' | 'refused' | 'too-short';
|
|
56
|
+
export declare class PasswordRecovery {
|
|
57
|
+
private readonly deps;
|
|
58
|
+
constructor(deps: RecoveryDeps);
|
|
59
|
+
private get scope();
|
|
60
|
+
private get clock();
|
|
61
|
+
/**
|
|
62
|
+
* Send a link, or do nothing, and answer the same either way.
|
|
63
|
+
*
|
|
64
|
+
* The caller writes one `204` whatever happened here. An address that has an
|
|
65
|
+
* account and one that does not must be indistinguishable, or this endpoint
|
|
66
|
+
* becomes the account-enumeration oracle that the sign-in path is careful not
|
|
67
|
+
* to be — and it is reachable without a credential.
|
|
68
|
+
*
|
|
69
|
+
* An address in two organizations is the same silence, for the reason the
|
|
70
|
+
* login path gives: telling somebody how many tenants an address appears in
|
|
71
|
+
* is telling them about tenants.
|
|
72
|
+
*/
|
|
73
|
+
request(email: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Spend a link and set the password, or refuse.
|
|
76
|
+
*
|
|
77
|
+
* The spend is the UPDATE that finds it, so two requests cannot both succeed
|
|
78
|
+
* — a read followed by a write is a race with a stolen link on the other side
|
|
79
|
+
* of it.
|
|
80
|
+
*/
|
|
81
|
+
redeem(token: string, password: string): Promise<Redemption>;
|
|
82
|
+
/**
|
|
83
|
+
* The one user this address names, or nothing.
|
|
84
|
+
*
|
|
85
|
+
* The same shape the login path uses, and for the same reasons: two matches
|
|
86
|
+
* is silence rather than a choice, and the scan stops at two so the cost does
|
|
87
|
+
* not grow with how many tenants a deployment has.
|
|
88
|
+
*/
|
|
89
|
+
private findUser;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4B,KAAK,MAAM,EAAW,MAAM,kBAAkB,CAAA;AACjF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAIrC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAA;AAE1D,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,YAAY;IAE/C,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkD3C;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAuElE;;;;;;OAMG;YACW,QAAQ;CAgCvB"}
|
package/dist/recovery.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { consoleUrl, hashPassword, withOrg } from '@nacre.work/core';
|
|
3
|
+
/**
|
|
4
|
+
* Recovering a password, by email, without a `psql` session.
|
|
5
|
+
*
|
|
6
|
+
* ## The hole this closes
|
|
7
|
+
*
|
|
8
|
+
* `POST /v1/users/{id}/password` is an **administrator** setting somebody
|
|
9
|
+
* else's. The person who forgot theirs had no route, and on a
|
|
10
|
+
* single-administrator installation — which the open core mostly is — the
|
|
11
|
+
* administrator who forgot theirs had no route that did not go through the
|
|
12
|
+
* database. That is the model-offers-it-and-the-product-gives-no-route shape
|
|
13
|
+
* this repository keeps closing.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the token carries its organization
|
|
16
|
+
*
|
|
17
|
+
* `<org_id>.<secret>`. Redemption therefore knows the tenant before it reads
|
|
18
|
+
* anything, so this table is read through `withOrg` like every other and the
|
|
19
|
+
* one path a stranger can reach unauthenticated opens no cross-tenant read.
|
|
20
|
+
*
|
|
21
|
+
* Migration 0008 says `users` gets no `authenticating` policy "as a decision
|
|
22
|
+
* rather than an omission"; this keeps that decision rather than arguing with
|
|
23
|
+
* it. The organization id is not a secret from the person holding the link —
|
|
24
|
+
* it is in their own `/v1/me` — and the half beside it is.
|
|
25
|
+
*
|
|
26
|
+
* ## What a reset does not do
|
|
27
|
+
*
|
|
28
|
+
* **It does not touch a second factor.** If it did, an email account would be a
|
|
29
|
+
* way around one, which is the whole thing a second factor exists to not be.
|
|
30
|
+
* Somebody who resets a password still produces a code afterwards.
|
|
31
|
+
*
|
|
32
|
+
* It *does* end every other session: a reset is what somebody does when they
|
|
33
|
+
* think their password is known, and leaving the refresh tokens alive would
|
|
34
|
+
* leave whoever knows it signed in.
|
|
35
|
+
*/
|
|
36
|
+
/** An hour. Long enough to reach an inbox, short enough to be worth stealing. */
|
|
37
|
+
export const RESET_TTL_SECONDS = 3600;
|
|
38
|
+
/**
|
|
39
|
+
* The shortest password this will accept from a person choosing their own.
|
|
40
|
+
*
|
|
41
|
+
* Length and nothing else — no composition rule. A rule demanding a digit and a
|
|
42
|
+
* symbol produces `Password1!` and a person who writes it down; length is the
|
|
43
|
+
* only requirement that reliably buys entropy. The passwords this product
|
|
44
|
+
* *generates* are six words and a number, and are longer than this.
|
|
45
|
+
*/
|
|
46
|
+
export const MIN_PASSWORD_LENGTH = 12;
|
|
47
|
+
const digest = (token) => createHash('sha256').update(token).digest('hex');
|
|
48
|
+
export class PasswordRecovery {
|
|
49
|
+
deps;
|
|
50
|
+
constructor(deps) {
|
|
51
|
+
this.deps = deps;
|
|
52
|
+
}
|
|
53
|
+
get scope() {
|
|
54
|
+
return this.deps.role === undefined ? {} : { role: this.deps.role };
|
|
55
|
+
}
|
|
56
|
+
get clock() {
|
|
57
|
+
return this.deps.now?.() ?? new Date();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Send a link, or do nothing, and answer the same either way.
|
|
61
|
+
*
|
|
62
|
+
* The caller writes one `204` whatever happened here. An address that has an
|
|
63
|
+
* account and one that does not must be indistinguishable, or this endpoint
|
|
64
|
+
* becomes the account-enumeration oracle that the sign-in path is careful not
|
|
65
|
+
* to be — and it is reachable without a credential.
|
|
66
|
+
*
|
|
67
|
+
* An address in two organizations is the same silence, for the reason the
|
|
68
|
+
* login path gives: telling somebody how many tenants an address appears in
|
|
69
|
+
* is telling them about tenants.
|
|
70
|
+
*/
|
|
71
|
+
async request(email) {
|
|
72
|
+
const address = email.trim().toLowerCase();
|
|
73
|
+
if (address === '')
|
|
74
|
+
return;
|
|
75
|
+
const found = await this.findUser(address);
|
|
76
|
+
if (found === undefined)
|
|
77
|
+
return;
|
|
78
|
+
const secret = randomBytes(32).toString('base64url');
|
|
79
|
+
const token = `${found.orgId}.${secret}`;
|
|
80
|
+
const expiresAt = new Date(this.clock.getTime() + RESET_TTL_SECONDS * 1000);
|
|
81
|
+
await withOrg(this.deps.pool, found.orgId, async (client) => {
|
|
82
|
+
// Any older link this person holds stops working. Two live links is two
|
|
83
|
+
// things to steal for one account, and somebody asking again is
|
|
84
|
+
// somebody who does not have the first.
|
|
85
|
+
await client.query(`UPDATE password_reset_tokens SET used_at = now()
|
|
86
|
+
WHERE org_id = $1 AND user_id = $2 AND used_at IS NULL`, [found.orgId, found.userId]);
|
|
87
|
+
await client.query(`INSERT INTO password_reset_tokens (org_id, user_id, token_hash, expires_at)
|
|
88
|
+
VALUES ($1, $2, $3, $4)`, [found.orgId, found.userId, digest(token), expiresAt]);
|
|
89
|
+
}, this.scope);
|
|
90
|
+
const link = consoleUrl(this.deps.consoleBase, `#/reset?token=${encodeURIComponent(token)}`);
|
|
91
|
+
await this.deps.mailer.send({
|
|
92
|
+
to: address,
|
|
93
|
+
subject: 'Reset your Nacre password',
|
|
94
|
+
text: [
|
|
95
|
+
'Somebody asked to reset the password for this address.',
|
|
96
|
+
'',
|
|
97
|
+
link,
|
|
98
|
+
'',
|
|
99
|
+
`The link works once and expires in ${String(Math.round(RESET_TTL_SECONDS / 60))} minutes.`,
|
|
100
|
+
'If it was not you, nothing has changed and you can ignore this message.',
|
|
101
|
+
'',
|
|
102
|
+
'Resetting a password does not remove a second factor: you will still be',
|
|
103
|
+
'asked for a code afterwards.',
|
|
104
|
+
].join('\n'),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Spend a link and set the password, or refuse.
|
|
109
|
+
*
|
|
110
|
+
* The spend is the UPDATE that finds it, so two requests cannot both succeed
|
|
111
|
+
* — a read followed by a write is a race with a stolen link on the other side
|
|
112
|
+
* of it.
|
|
113
|
+
*/
|
|
114
|
+
async redeem(token, password) {
|
|
115
|
+
if (password.length < MIN_PASSWORD_LENGTH)
|
|
116
|
+
return 'too-short';
|
|
117
|
+
const [orgId, secret] = token.split('.');
|
|
118
|
+
if (orgId === undefined || secret === undefined || !UUID.test(orgId))
|
|
119
|
+
return 'refused';
|
|
120
|
+
const hash = await hashPassword(password);
|
|
121
|
+
const address = await withOrg(this.deps.pool, orgId, async (client) => {
|
|
122
|
+
const { rows } = await client.query(`UPDATE password_reset_tokens SET used_at = now()
|
|
123
|
+
WHERE org_id = $1 AND token_hash = $2 AND used_at IS NULL AND expires_at > now()
|
|
124
|
+
RETURNING user_id`, [orgId, digest(token)]);
|
|
125
|
+
const userId = rows[0]?.user_id;
|
|
126
|
+
if (userId === undefined)
|
|
127
|
+
return undefined;
|
|
128
|
+
const { rows: people } = await client.query('SELECT email, disabled_at FROM users WHERE org_id = $1 AND id = $2', [orgId, userId]);
|
|
129
|
+
const person = people[0];
|
|
130
|
+
// A disabled account is refused, and the token is spent anyway: it was
|
|
131
|
+
// issued before the account was disabled, and leaving it live would be
|
|
132
|
+
// a link that starts working again if the account is ever re-enabled.
|
|
133
|
+
if (person === undefined || person.disabled_at !== null)
|
|
134
|
+
return undefined;
|
|
135
|
+
await client.query('UPDATE users SET password_hash = $2 WHERE id = $1', [userId, hash]);
|
|
136
|
+
// Every other session ends. A reset is what somebody does when they
|
|
137
|
+
// think their password is known, and leaving the refresh tokens alive
|
|
138
|
+
// would leave whoever knows it signed in.
|
|
139
|
+
await client.query(`UPDATE refresh_tokens SET revoked_at = now()
|
|
140
|
+
WHERE org_id = $1 AND user_id = $2 AND revoked_at IS NULL`, [orgId, userId]);
|
|
141
|
+
return person.email;
|
|
142
|
+
}, this.scope);
|
|
143
|
+
if (address === undefined)
|
|
144
|
+
return 'refused';
|
|
145
|
+
// A notice, not a confirmation: the person who receives this and did not do
|
|
146
|
+
// it is the one who needs to know, and they need to know now.
|
|
147
|
+
await this.deps.mailer
|
|
148
|
+
.send({
|
|
149
|
+
to: address,
|
|
150
|
+
subject: 'Your Nacre password was changed',
|
|
151
|
+
text: [
|
|
152
|
+
'The password for this address has just been changed using a recovery link.',
|
|
153
|
+
'',
|
|
154
|
+
'Every other session was signed out. Any second factor on the account is',
|
|
155
|
+
'untouched and is still required.',
|
|
156
|
+
'',
|
|
157
|
+
'If this was not you, whoever did it can read your mail — change the',
|
|
158
|
+
'password again from a device you trust and tell your administrator.',
|
|
159
|
+
].join('\n'),
|
|
160
|
+
})
|
|
161
|
+
// Dropped rather than raised: the password *is* changed, and refusing the
|
|
162
|
+
// request over a notice would be worse than a notice that did not arrive.
|
|
163
|
+
.catch(() => undefined);
|
|
164
|
+
return 'reset';
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The one user this address names, or nothing.
|
|
168
|
+
*
|
|
169
|
+
* The same shape the login path uses, and for the same reasons: two matches
|
|
170
|
+
* is silence rather than a choice, and the scan stops at two so the cost does
|
|
171
|
+
* not grow with how many tenants a deployment has.
|
|
172
|
+
*/
|
|
173
|
+
async findUser(email) {
|
|
174
|
+
const client = await this.deps.pool.connect();
|
|
175
|
+
let orgIds;
|
|
176
|
+
try {
|
|
177
|
+
const { rows } = await client.query('SELECT id FROM organizations WHERE deleted_at IS NULL');
|
|
178
|
+
orgIds = rows.map((row) => row.id);
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
client.release();
|
|
182
|
+
}
|
|
183
|
+
const found = [];
|
|
184
|
+
for (const orgId of orgIds) {
|
|
185
|
+
const row = await withOrg(this.deps.pool, orgId, async (scoped) => {
|
|
186
|
+
const { rows } = await scoped.query(`SELECT id FROM users
|
|
187
|
+
WHERE org_id = $1 AND email = $2 AND disabled_at IS NULL AND password_hash IS NOT NULL`, [orgId, email]);
|
|
188
|
+
return rows[0];
|
|
189
|
+
}, this.scope);
|
|
190
|
+
if (row !== undefined)
|
|
191
|
+
found.push({ orgId, userId: row.id });
|
|
192
|
+
if (found.length > 1)
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
return found[0];
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
|
|
199
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"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"}
|