@rebasepro/server 0.16.1-canary.ge71347e → 0.17.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/{admin_block-BeypnEfb.js → admin_block-BX6YULvJ.js} +8 -8
- package/dist/admin_block-BX6YULvJ.js.map +1 -0
- package/dist/api/ast-schema-editor.d.ts +1 -1
- package/dist/api/rest/idempotency.d.ts +1 -1
- package/dist/{ast-schema-editor-BrarYZCq.js → ast-schema-editor-BLADP9O2.js} +3 -3
- package/dist/ast-schema-editor-BLADP9O2.js.map +1 -0
- package/dist/auth/crypto-utils.d.ts +4 -0
- package/dist/auth/jwt-crypto.d.ts +91 -0
- package/dist/auth/jwt.d.ts +10 -9
- package/dist/auth/middleware.d.ts +1 -1
- package/dist/auth/rate-limiter.d.ts +10 -3
- package/dist/{auth-Cd6qQw_0.js → auth-BVPx33qB.js} +51 -77
- package/dist/auth-BVPx33qB.js.map +1 -0
- package/dist/boot/fetch-bundle.d.ts +18 -1
- package/dist/collections/validate-config.d.ts +14 -1
- package/dist/{cron-store-BFmnkJ2s.js → cron-store-CbFfQhbg.js} +3 -2
- package/dist/{cron-store-BFmnkJ2s.js.map → cron-store-CbFfQhbg.js.map} +1 -1
- package/dist/{ddl-bootstrap-euwN8FOy.js → ddl-bootstrap-5YZCZ8qk.js} +2 -92
- package/dist/ddl-bootstrap-5YZCZ8qk.js.map +1 -0
- package/dist/history-recorder-B67maiTi.js +76 -0
- package/dist/history-recorder-B67maiTi.js.map +1 -0
- package/dist/history-store-oiqhb3HU.js +210 -0
- package/dist/history-store-oiqhb3HU.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +302 -77
- package/dist/index.es.js.map +1 -1
- package/dist/init.d.ts +8 -0
- package/dist/internal-tables-DpxfPaEB.js +97 -0
- package/dist/internal-tables-DpxfPaEB.js.map +1 -0
- package/dist/{jobs-DE0KUNT0.js → jobs-B2ELModo.js} +3 -2
- package/dist/{jobs-DE0KUNT0.js.map → jobs-B2ELModo.js.map} +1 -1
- package/dist/{jwt-DoHkMMWF.js → jwt-5VN4C6ln.js} +230 -38
- package/dist/jwt-5VN4C6ln.js.map +1 -0
- package/dist/metrics/history-recorder.d.ts +18 -0
- package/dist/metrics/history-store.d.ts +123 -0
- package/dist/metrics/index.d.ts +9 -1
- package/dist/{schema-editor-routes-Bf5h5Emf.js → schema-editor-routes-BWCIqZoT.js} +2 -2
- package/dist/{schema-editor-routes-Bf5h5Emf.js.map → schema-editor-routes-BWCIqZoT.js.map} +1 -1
- package/dist/src-B-CmIFMr.js.map +1 -1
- package/dist/src-Cdsw7DqV.js.map +1 -1
- package/dist/storage/keys.d.ts +21 -0
- package/dist/utils/ip-address.d.ts +30 -0
- package/dist/utils/portable-crypto.d.ts +71 -0
- package/dist/utils/request-id.d.ts +20 -0
- package/package.json +5 -5
- package/dist/admin_block-BeypnEfb.js.map +0 -1
- package/dist/ast-schema-editor-BrarYZCq.js.map +0 -1
- package/dist/auth-Cd6qQw_0.js.map +0 -1
- package/dist/ddl-bootstrap-euwN8FOy.js.map +0 -1
- package/dist/jwt-DoHkMMWF.js.map +0 -1
|
@@ -5,8 +5,9 @@ __rebaseCreateRequire(import.meta.url);
|
|
|
5
5
|
import { i as __toESM, n as __exportAll } from "./rolldown-runtime-dW7B1o5h.js";
|
|
6
6
|
import { D as isAnonymousUid, E as ANONYMOUS_USER_ID } from "./src-B-CmIFMr.js";
|
|
7
7
|
import "./src-Cdsw7DqV.js";
|
|
8
|
-
import { n as createDdlBootstrapper, o as
|
|
9
|
-
import { S as canonicalStorageId, T as require_jsonwebtoken, _ as verifyMfaPendingToken, a as generateMfaPendingToken, c as getJwks, d as hasAsymmetricSigningKey, f as hashRefreshToken, g as verifyDownloadToken, h as verifyAccessToken, i as generateDownloadToken, l as getRefreshTokenExpiry, n as configureJwt, o as generateRefreshToken, p as isJwtConfigured, r as generateAccessToken, s as getAccessTokenExpiry, t as MAX_COOKIE_AGE_MS, u as getRefreshTokenTtlMs, w as tryCanonicalStorageKey } from "./jwt-
|
|
8
|
+
import { n as createDdlBootstrapper, o as isSQLAdmin } from "./ddl-bootstrap-5YZCZ8qk.js";
|
|
9
|
+
import { D as randomInt$1, E as constantTimeEqual, O as sha256Hex, S as canonicalStorageId, T as require_jsonwebtoken, _ as verifyMfaPendingToken, a as generateMfaPendingToken, c as getJwks, d as hasAsymmetricSigningKey, f as hashRefreshToken, g as verifyDownloadToken, h as verifyAccessToken, i as generateDownloadToken, l as getRefreshTokenExpiry, n as configureJwt, o as generateRefreshToken, p as isJwtConfigured, r as generateAccessToken, s as getAccessTokenExpiry, t as MAX_COOKIE_AGE_MS, u as getRefreshTokenTtlMs, w as tryCanonicalStorageKey } from "./jwt-5VN4C6ln.js";
|
|
10
|
+
import { t as revokeInternalTableSql } from "./internal-tables-DpxfPaEB.js";
|
|
10
11
|
import { t as logger } from "./logger-DS03e908.js";
|
|
11
12
|
import { n as errorHandler, t as ApiError } from "./errors-DBwpj9N8.js";
|
|
12
13
|
import { a as resolveListLimitParam } from "./query-parser--nstjRCh.js";
|
|
@@ -14,7 +15,7 @@ import { i as object, o as string } from "./schemas-DBxgjM9A.js";
|
|
|
14
15
|
import { createHash, randomBytes, randomInt } from "node:crypto";
|
|
15
16
|
import { Hono } from "hono";
|
|
16
17
|
import { promisify } from "util";
|
|
17
|
-
import { createCipheriv, createDecipheriv, createHash as createHash$1, createHmac, createPublicKey, randomBytes as randomBytes$1, randomUUID
|
|
18
|
+
import { createCipheriv, createDecipheriv, createHash as createHash$1, createHmac, createPublicKey, randomBytes as randomBytes$1, randomUUID, scrypt, timingSafeEqual } from "crypto";
|
|
18
19
|
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
19
20
|
import { createMiddleware } from "hono/factory";
|
|
20
21
|
//#region ../types/src/controllers/storage.ts
|
|
@@ -296,23 +297,16 @@ async function scopeDataDriver(driver, user) {
|
|
|
296
297
|
* Used for comparing service keys, tokens, and other secrets where
|
|
297
298
|
* timing side-channels could leak information about the expected value.
|
|
298
299
|
*
|
|
300
|
+
* The implementation lives in `utils/portable-crypto.ts`, which does this over
|
|
301
|
+
* UTF-8 bytes without `node:crypto` — this function is on the request path, and
|
|
302
|
+
* the byte-level reasoning it depends on is documented there.
|
|
303
|
+
*
|
|
299
304
|
* @param a - First string to compare.
|
|
300
305
|
* @param b - Second string to compare.
|
|
301
306
|
* @returns `true` if the strings are identical, `false` otherwise.
|
|
302
307
|
*/
|
|
303
308
|
function safeCompare(a, b) {
|
|
304
|
-
|
|
305
|
-
const bytesB = Buffer.from(b, "utf8");
|
|
306
|
-
const length = Math.max(bytesA.length, bytesB.length);
|
|
307
|
-
const paddedA = Buffer.alloc(length);
|
|
308
|
-
const paddedB = Buffer.alloc(length);
|
|
309
|
-
bytesA.copy(paddedA);
|
|
310
|
-
bytesB.copy(paddedB);
|
|
311
|
-
try {
|
|
312
|
-
return timingSafeEqual(paddedA, paddedB) && bytesA.length === bytesB.length;
|
|
313
|
-
} catch {
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
309
|
+
return constantTimeEqual(a, b);
|
|
316
310
|
}
|
|
317
311
|
//#endregion
|
|
318
312
|
//#region src/auth/bearer-token.ts
|
|
@@ -351,29 +345,6 @@ function extractBearerToken(authHeader) {
|
|
|
351
345
|
//#endregion
|
|
352
346
|
//#region src/auth/api-keys/api-key-middleware.ts
|
|
353
347
|
/**
|
|
354
|
-
* Hono middleware for authenticating requests via Service API Keys.
|
|
355
|
-
*
|
|
356
|
-
* This middleware is integrated into `createAuthMiddleware()` and
|
|
357
|
-
* activates only when the bearer token starts with `rk_`. It:
|
|
358
|
-
*
|
|
359
|
-
* 1. Hashes the token with SHA-256
|
|
360
|
-
* 2. Looks up the hash in the `rebase.api_keys` table
|
|
361
|
-
* 3. Validates the key is not revoked and not expired
|
|
362
|
-
* 4. Sets `c.set("user", ...)` and `c.set("apiKey", ...)` for downstream use
|
|
363
|
-
* 5. Scopes the DataDriver via `withAuth()` using the API key's service identity
|
|
364
|
-
*
|
|
365
|
-
* Authorization is double-gated for API keys: the key's own permission list
|
|
366
|
-
* (checked by the REST generator) is one ceiling, and Postgres RLS is another,
|
|
367
|
-
* independent one — `withAuth()` runs API-key requests as the restricted
|
|
368
|
-
* `rebase_user` role like any other caller. An `admin` key passes RLS via the
|
|
369
|
-
* injected `default_admin` policies; a non-admin key (roles `["service"]`,
|
|
370
|
-
* uid `api-key:<id>`) only sees rows that a policy explicitly grants to the
|
|
371
|
-
* `service` role or to the public. Owner-style policies
|
|
372
|
-
* (`owner_id = rebase.uid()`) never match an API key's synthetic uid.
|
|
373
|
-
*
|
|
374
|
-
* @module
|
|
375
|
-
*/
|
|
376
|
-
/**
|
|
377
348
|
* Check whether a token looks like a Rebase API key.
|
|
378
349
|
*/
|
|
379
350
|
function isApiKeyToken(token) {
|
|
@@ -381,9 +352,12 @@ function isApiKeyToken(token) {
|
|
|
381
352
|
}
|
|
382
353
|
/**
|
|
383
354
|
* Hash a plaintext API key token for database lookup.
|
|
355
|
+
*
|
|
356
|
+
* Async because it hashes with WebCrypto rather than `node:crypto` — the sole
|
|
357
|
+
* caller was already awaiting the store lookup this feeds.
|
|
384
358
|
*/
|
|
385
359
|
function hashToken$1(token) {
|
|
386
|
-
return
|
|
360
|
+
return sha256Hex(token);
|
|
387
361
|
}
|
|
388
362
|
/**
|
|
389
363
|
* Validate an API key token and populate the Hono context.
|
|
@@ -396,7 +370,7 @@ function hashToken$1(token) {
|
|
|
396
370
|
*/
|
|
397
371
|
async function validateApiKey(c, token, options) {
|
|
398
372
|
const { store, driver } = options;
|
|
399
|
-
const hash = hashToken$1(token);
|
|
373
|
+
const hash = await hashToken$1(token);
|
|
400
374
|
const apiKey = await store.findByKeyHash(hash);
|
|
401
375
|
if (!apiKey) return c.json({ error: {
|
|
402
376
|
message: "Invalid API key",
|
|
@@ -569,7 +543,7 @@ var requireAuth = async (c, next) => {
|
|
|
569
543
|
message: "Authorization header missing or invalid",
|
|
570
544
|
code: "UNAUTHORIZED"
|
|
571
545
|
} }, 401);
|
|
572
|
-
const payload = verifyAccessToken(token);
|
|
546
|
+
const payload = await verifyAccessToken(token);
|
|
573
547
|
if (!payload) return c.json({ error: {
|
|
574
548
|
message: "Invalid or expired token",
|
|
575
549
|
code: "UNAUTHORIZED"
|
|
@@ -606,7 +580,7 @@ function createRequireAuth(options) {
|
|
|
606
580
|
});
|
|
607
581
|
return next();
|
|
608
582
|
}
|
|
609
|
-
const payload = verifyAccessToken(token);
|
|
583
|
+
const payload = await verifyAccessToken(token);
|
|
610
584
|
if (!payload) return c.json({ error: {
|
|
611
585
|
message: "Invalid or expired token",
|
|
612
586
|
code: "UNAUTHORIZED"
|
|
@@ -662,7 +636,7 @@ var optionalAuth = async (c, next) => {
|
|
|
662
636
|
if (c.get("user")) return next();
|
|
663
637
|
const token = extractBearerToken(c.req.header("authorization"));
|
|
664
638
|
if (token !== void 0 && isJwtConfigured()) {
|
|
665
|
-
const payload = verifyAccessToken(token);
|
|
639
|
+
const payload = await verifyAccessToken(token);
|
|
666
640
|
if (payload) c.set("user", payload);
|
|
667
641
|
}
|
|
668
642
|
return next();
|
|
@@ -670,7 +644,7 @@ var optionalAuth = async (c, next) => {
|
|
|
670
644
|
/**
|
|
671
645
|
* Extract user from token - for WebSocket authentication
|
|
672
646
|
*/
|
|
673
|
-
function extractUserFromToken(token) {
|
|
647
|
+
async function extractUserFromToken(token) {
|
|
674
648
|
if (!isJwtConfigured()) return null;
|
|
675
649
|
return verifyAccessToken(token);
|
|
676
650
|
}
|
|
@@ -761,7 +735,7 @@ function createAuthMiddleware(options) {
|
|
|
761
735
|
});
|
|
762
736
|
if (result !== true) return result;
|
|
763
737
|
} else {
|
|
764
|
-
const payload = extractUserFromToken(token);
|
|
738
|
+
const payload = await extractUserFromToken(token);
|
|
765
739
|
if (payload) {
|
|
766
740
|
c.set("user", payload);
|
|
767
741
|
try {
|
|
@@ -823,7 +797,7 @@ var queryTokenAuth = async (c, next) => {
|
|
|
823
797
|
if (extractBearerToken(c.req.header("authorization")) !== void 0) return next();
|
|
824
798
|
const queryToken = c.req.query("token");
|
|
825
799
|
if (queryToken && isJwtConfigured()) {
|
|
826
|
-
const payload = verifyAccessToken(queryToken);
|
|
800
|
+
const payload = await verifyAccessToken(queryToken);
|
|
827
801
|
if (payload) c.set("user", payload);
|
|
828
802
|
}
|
|
829
803
|
return next();
|
|
@@ -946,7 +920,7 @@ var fileTokenAuth = async (c, next) => {
|
|
|
946
920
|
} }, 403);
|
|
947
921
|
const bearerToken = extractBearerToken(authHeader);
|
|
948
922
|
if (bearerToken !== void 0) {
|
|
949
|
-
const payload = verifyDownloadToken(bearerToken);
|
|
923
|
+
const payload = await verifyDownloadToken(bearerToken);
|
|
950
924
|
if (payload) {
|
|
951
925
|
const outcome = evaluateGrant(payload);
|
|
952
926
|
if (outcome === "grant") {
|
|
@@ -965,7 +939,7 @@ var fileTokenAuth = async (c, next) => {
|
|
|
965
939
|
return next();
|
|
966
940
|
}
|
|
967
941
|
if (queryToken) {
|
|
968
|
-
const payload = verifyDownloadToken(queryToken);
|
|
942
|
+
const payload = await verifyDownloadToken(queryToken);
|
|
969
943
|
if (payload) {
|
|
970
944
|
const outcome = evaluateGrant(payload);
|
|
971
945
|
if (outcome === "grant") {
|
|
@@ -2423,10 +2397,10 @@ function createRateLimiter(options = {}) {
|
|
|
2423
2397
|
const trustedProxyHops = resolveTrustedProxyHops(options.trustedProxyHops);
|
|
2424
2398
|
const { windowMs = 900 * 1e3, limit = 100, keyGenerator = (c) => defaultKeyGenerator(c, trustedProxyHops), message = "Too many requests, please try again later.", store = new MemoryRateLimitStore(windowMs), resolveLimit } = options;
|
|
2425
2399
|
return async (c, next) => {
|
|
2426
|
-
const effectiveLimit = resolveLimit ? resolveLimit(c) : limit;
|
|
2400
|
+
const effectiveLimit = resolveLimit ? await resolveLimit(c) : limit;
|
|
2427
2401
|
if (effectiveLimit === null) return next();
|
|
2428
2402
|
const activeLimit = effectiveLimit ?? limit;
|
|
2429
|
-
const decision = await store.hit(keyGenerator(c), windowMs, activeLimit);
|
|
2403
|
+
const decision = await store.hit(await keyGenerator(c), windowMs, activeLimit);
|
|
2430
2404
|
c.header("X-RateLimit-Limit", String(activeLimit));
|
|
2431
2405
|
c.header("X-RateLimit-Remaining", String(decision.remaining));
|
|
2432
2406
|
if (!decision.allowed) {
|
|
@@ -2598,13 +2572,13 @@ function createDataRateLimiter(config = {}) {
|
|
|
2598
2572
|
* to the context; an identity that fails to verify simply buckets by IP,
|
|
2599
2573
|
* exactly as before.
|
|
2600
2574
|
*/
|
|
2601
|
-
const identify = (c) => {
|
|
2575
|
+
const identify = async (c) => {
|
|
2602
2576
|
const user = c.get("user");
|
|
2603
2577
|
if (user?.uid) return isAnonymousUid(user.uid) ? void 0 : user.uid;
|
|
2604
2578
|
if (!isJwtConfigured()) return void 0;
|
|
2605
2579
|
const token = extractBearerToken(c.req.header("authorization"));
|
|
2606
2580
|
if (token === void 0) return void 0;
|
|
2607
|
-
const payload = verifyAccessToken(token);
|
|
2581
|
+
const payload = await verifyAccessToken(token);
|
|
2608
2582
|
if (!payload?.uid || isAnonymousUid(payload.uid)) return void 0;
|
|
2609
2583
|
return payload.uid;
|
|
2610
2584
|
};
|
|
@@ -2612,17 +2586,17 @@ function createDataRateLimiter(config = {}) {
|
|
|
2612
2586
|
windowMs,
|
|
2613
2587
|
store,
|
|
2614
2588
|
message: "Too many requests, please try again later.",
|
|
2615
|
-
keyGenerator: (c) => {
|
|
2589
|
+
keyGenerator: async (c) => {
|
|
2616
2590
|
const key = c.get("apiKey");
|
|
2617
2591
|
if (key) return `api-key:${key.id}`;
|
|
2618
|
-
const uid = identify(c);
|
|
2592
|
+
const uid = await identify(c);
|
|
2619
2593
|
if (uid) return `user:${uid}`;
|
|
2620
2594
|
return `ip:${defaultKeyGenerator(c, trustedProxyHops)}`;
|
|
2621
2595
|
},
|
|
2622
|
-
resolveLimit: (c) => {
|
|
2596
|
+
resolveLimit: async (c) => {
|
|
2623
2597
|
const key = c.get("apiKey");
|
|
2624
2598
|
if (key) return key.rate_limit ?? apiKeyLimit;
|
|
2625
|
-
return identify(c) ? userLimit : anonLimit;
|
|
2599
|
+
return await identify(c) ? userLimit : anonLimit;
|
|
2626
2600
|
}
|
|
2627
2601
|
});
|
|
2628
2602
|
}
|
|
@@ -3164,7 +3138,7 @@ async function openAndRewrap(authRepo, factorId, secretEncrypted) {
|
|
|
3164
3138
|
}
|
|
3165
3139
|
return secret;
|
|
3166
3140
|
}
|
|
3167
|
-
function resolveStepUpPrincipal(c) {
|
|
3141
|
+
async function resolveStepUpPrincipal(c) {
|
|
3168
3142
|
const existing = c.get("user");
|
|
3169
3143
|
if (existing?.uid) return {
|
|
3170
3144
|
uid: existing.uid,
|
|
@@ -3173,13 +3147,13 @@ function resolveStepUpPrincipal(c) {
|
|
|
3173
3147
|
};
|
|
3174
3148
|
const token = extractBearerToken(c.req.header("authorization"));
|
|
3175
3149
|
if (token === void 0) return null;
|
|
3176
|
-
const session = verifyAccessToken(token);
|
|
3150
|
+
const session = await verifyAccessToken(token);
|
|
3177
3151
|
if (session) return {
|
|
3178
3152
|
uid: session.uid,
|
|
3179
3153
|
aal: session.aal === "aal2" ? "aal2" : "aal1",
|
|
3180
3154
|
pending: false
|
|
3181
3155
|
};
|
|
3182
|
-
const pending = verifyMfaPendingToken(token);
|
|
3156
|
+
const pending = await verifyMfaPendingToken(token);
|
|
3183
3157
|
if (pending) return {
|
|
3184
3158
|
uid: pending.uid,
|
|
3185
3159
|
aal: "aal1",
|
|
@@ -3198,7 +3172,7 @@ function resolveStepUpPrincipal(c) {
|
|
|
3198
3172
|
var mfaVerificationLimiter = createRateLimiter({
|
|
3199
3173
|
windowMs: 900 * 1e3,
|
|
3200
3174
|
limit: MFA_VERIFICATION_ATTEMPTS_PER_WINDOW,
|
|
3201
|
-
keyGenerator: (c) => `mfa-verify:${resolveStepUpPrincipal(c)?.uid ?? "unidentified"}`,
|
|
3175
|
+
keyGenerator: async (c) => `mfa-verify:${(await resolveStepUpPrincipal(c))?.uid ?? "unidentified"}`,
|
|
3202
3176
|
message: "Too many verification attempts for this account, please try again later."
|
|
3203
3177
|
});
|
|
3204
3178
|
function mountMfaRoutes(opts) {
|
|
@@ -3302,7 +3276,7 @@ function mountMfaRoutes(opts) {
|
|
|
3302
3276
|
* `MFA_REQUIRED`, or to step an existing session up to `aal2`.
|
|
3303
3277
|
*/
|
|
3304
3278
|
router.post("/mfa/challenge", strictAuthLimiter, async (c) => {
|
|
3305
|
-
const principal = resolveStepUpPrincipal(c);
|
|
3279
|
+
const principal = await resolveStepUpPrincipal(c);
|
|
3306
3280
|
if (!principal) throw ApiError.unauthorized("Not authenticated");
|
|
3307
3281
|
const challengeSchema = object({ factorId: string().min(1, "Factor ID is required") });
|
|
3308
3282
|
const { factorId } = parseBody(challengeSchema, await c.req.json());
|
|
@@ -3323,7 +3297,7 @@ function mountMfaRoutes(opts) {
|
|
|
3323
3297
|
* minted, at `aal2`.
|
|
3324
3298
|
*/
|
|
3325
3299
|
router.post("/mfa/challenge/verify", strictAuthLimiter, mfaVerificationLimiter, async (c) => {
|
|
3326
|
-
const principal = resolveStepUpPrincipal(c);
|
|
3300
|
+
const principal = await resolveStepUpPrincipal(c);
|
|
3327
3301
|
if (!principal) throw ApiError.unauthorized("Not authenticated");
|
|
3328
3302
|
const challengeVerifySchema = object({
|
|
3329
3303
|
challengeId: string().min(1, "Challenge ID is required"),
|
|
@@ -3451,7 +3425,7 @@ async function assertMfaSatisfied(authRepo, uid) {
|
|
|
3451
3425
|
if (!await authRepo.hasVerifiedMfaFactors(uid)) return;
|
|
3452
3426
|
const factors = (await authRepo.getMfaFactors(uid)).filter((f) => f.verified);
|
|
3453
3427
|
const details = {
|
|
3454
|
-
mfaToken: generateMfaPendingToken(uid),
|
|
3428
|
+
mfaToken: await generateMfaPendingToken(uid),
|
|
3455
3429
|
factors: factors.map((f) => ({
|
|
3456
3430
|
id: f.id,
|
|
3457
3431
|
factorType: f.factorType,
|
|
@@ -3553,7 +3527,7 @@ function mountSessionRoutes(opts) {
|
|
|
3553
3527
|
const body = await c.req.json().catch(() => ({}));
|
|
3554
3528
|
const refreshToken = readRefreshToken(c, parseBody(logoutSchema, body), config.cookieAuth);
|
|
3555
3529
|
if (refreshToken) {
|
|
3556
|
-
const tokenHash = hashRefreshToken(refreshToken);
|
|
3530
|
+
const tokenHash = await hashRefreshToken(refreshToken);
|
|
3557
3531
|
const sessionId = (await authRepo.findRefreshTokenByHash(tokenHash).catch(() => null))?.sessionId;
|
|
3558
3532
|
if (sessionId && authRepo.revokeRefreshTokenSession) await authRepo.revokeRefreshTokenSession(sessionId);
|
|
3559
3533
|
else await authRepo.deleteRefreshToken(tokenHash);
|
|
@@ -3561,8 +3535,8 @@ function mountSessionRoutes(opts) {
|
|
|
3561
3535
|
clearRefreshCookie(c, config.cookieAuth);
|
|
3562
3536
|
const accessToken = extractBearerToken(c.req.header("authorization"));
|
|
3563
3537
|
if (ops.afterLogout && accessToken !== void 0) {
|
|
3564
|
-
const { verifyAccessToken } = await import("./jwt-
|
|
3565
|
-
const payload = verifyAccessToken(accessToken);
|
|
3538
|
+
const { verifyAccessToken } = await import("./jwt-5VN4C6ln.js").then((n) => n.m);
|
|
3539
|
+
const payload = await verifyAccessToken(accessToken);
|
|
3566
3540
|
if (payload) ops.afterLogout(payload.uid).catch((err) => {
|
|
3567
3541
|
logger.error("[AuthHooks] afterLogout error", { error: err instanceof Error ? err.message : err });
|
|
3568
3542
|
});
|
|
@@ -3577,7 +3551,7 @@ function mountSessionRoutes(opts) {
|
|
|
3577
3551
|
const userCtx = c.get("user");
|
|
3578
3552
|
if (!userCtx) throw ApiError.unauthorized("Not authenticated");
|
|
3579
3553
|
const currentRefreshToken = c.req.header("x-refresh-token");
|
|
3580
|
-
const currentTokenHash = currentRefreshToken ? hashRefreshToken(currentRefreshToken) : null;
|
|
3554
|
+
const currentTokenHash = currentRefreshToken ? await hashRefreshToken(currentRefreshToken) : null;
|
|
3581
3555
|
const tokens = await authRepo.listRefreshTokensForUser(userCtx.uid);
|
|
3582
3556
|
const bySession = /* @__PURE__ */ new Map();
|
|
3583
3557
|
for (const token of tokens) {
|
|
@@ -3845,7 +3819,7 @@ var OTP_ATTEMPTS_PER_WINDOW = 5;
|
|
|
3845
3819
|
* and one of them is the classic modulo bias.
|
|
3846
3820
|
*/
|
|
3847
3821
|
function generateOtpCode() {
|
|
3848
|
-
return String(randomInt(
|
|
3822
|
+
return String(randomInt$1(10 ** OTP_DIGITS)).padStart(OTP_DIGITS, "0");
|
|
3849
3823
|
}
|
|
3850
3824
|
/**
|
|
3851
3825
|
* What gets hashed and stored.
|
|
@@ -4183,10 +4157,10 @@ function createAuthRoutes(config) {
|
|
|
4183
4157
|
customClaims = await ops.customizeAccessToken(defaultClaims, user);
|
|
4184
4158
|
}
|
|
4185
4159
|
}
|
|
4186
|
-
const accessToken = generateAccessToken(uid, roleIds, aal, customClaims);
|
|
4160
|
+
const accessToken = await generateAccessToken(uid, roleIds, aal, customClaims);
|
|
4187
4161
|
const refreshToken = generateRefreshToken();
|
|
4188
|
-
await authRepo.createRefreshToken(uid, hashRefreshToken(refreshToken), getRefreshTokenExpiry(), userAgent, ipAddress, {
|
|
4189
|
-
id: randomUUID
|
|
4162
|
+
await authRepo.createRefreshToken(uid, await hashRefreshToken(refreshToken), getRefreshTokenExpiry(), userAgent, ipAddress, {
|
|
4163
|
+
id: randomUUID(),
|
|
4190
4164
|
startedAt: /* @__PURE__ */ new Date(),
|
|
4191
4165
|
aal
|
|
4192
4166
|
});
|
|
@@ -4550,7 +4524,7 @@ function createAuthRoutes(config) {
|
|
|
4550
4524
|
const body = await c.req.json().catch(() => ({}));
|
|
4551
4525
|
const refreshToken = readRefreshToken(c, parseBody(refreshSchema, body), config.cookieAuth);
|
|
4552
4526
|
if (!refreshToken) throw ApiError.unauthenticated("No refresh token presented", "NO_SESSION");
|
|
4553
|
-
const tokenHash = hashRefreshToken(refreshToken);
|
|
4527
|
+
const tokenHash = await hashRefreshToken(refreshToken);
|
|
4554
4528
|
const storedToken = await authRepo.findRefreshTokenByHash(tokenHash);
|
|
4555
4529
|
if (!storedToken) throw ApiError.unauthorized("Invalid refresh token", "INVALID_TOKEN");
|
|
4556
4530
|
if (storedToken.revoked) {
|
|
@@ -4598,7 +4572,7 @@ function createAuthRoutes(config) {
|
|
|
4598
4572
|
};
|
|
4599
4573
|
customClaims = await ops.customizeAccessToken(defaultClaims, user);
|
|
4600
4574
|
}
|
|
4601
|
-
const newAccessToken = generateAccessToken(storedToken.uid, roleIds, sessionAal, customClaims);
|
|
4575
|
+
const newAccessToken = await generateAccessToken(storedToken.uid, roleIds, sessionAal, customClaims);
|
|
4602
4576
|
const newRefreshToken = generateRefreshToken();
|
|
4603
4577
|
const userAgent = c.req.header("user-agent") || "unknown";
|
|
4604
4578
|
const ipAddress = c.req.header("x-forwarded-for") || "unknown";
|
|
@@ -4609,7 +4583,7 @@ function createAuthRoutes(config) {
|
|
|
4609
4583
|
};
|
|
4610
4584
|
if (!supersededAt) if (authRepo.markRefreshTokenRotated) await authRepo.markRefreshTokenRotated(tokenHash);
|
|
4611
4585
|
else await authRepo.deleteRefreshToken(tokenHash);
|
|
4612
|
-
await authRepo.createRefreshToken(storedToken.uid, hashRefreshToken(newRefreshToken), getRefreshTokenExpiry(), userAgent, ipAddress, session);
|
|
4586
|
+
await authRepo.createRefreshToken(storedToken.uid, await hashRefreshToken(newRefreshToken), getRefreshTokenExpiry(), userAgent, ipAddress, session);
|
|
4613
4587
|
authRepo.pruneRefreshTokens?.(storedToken.uid, session.id, new Date(Date.now() - reuseWindowMs)).catch((err) => {
|
|
4614
4588
|
logger.warn("[Auth] Refresh token prune failed", { error: err instanceof Error ? err.message : String(err) });
|
|
4615
4589
|
});
|
|
@@ -5089,7 +5063,7 @@ function createBuiltinAuthAdapter(config) {
|
|
|
5089
5063
|
isAdmin: true,
|
|
5090
5064
|
rawToken: token
|
|
5091
5065
|
};
|
|
5092
|
-
const payload = verifyAccessToken(token);
|
|
5066
|
+
const payload = await verifyAccessToken(token);
|
|
5093
5067
|
if (!payload) return null;
|
|
5094
5068
|
if (await isAccessTokenRevoked(authRepository, payload)) {
|
|
5095
5069
|
logger.warn("[Security Audit] Refused a revoked access token", {
|
|
@@ -5125,7 +5099,7 @@ function createBuiltinAuthAdapter(config) {
|
|
|
5125
5099
|
isAdmin: true,
|
|
5126
5100
|
rawToken: token
|
|
5127
5101
|
};
|
|
5128
|
-
const payload = verifyAccessToken(token);
|
|
5102
|
+
const payload = await verifyAccessToken(token);
|
|
5129
5103
|
if (!payload) return null;
|
|
5130
5104
|
if (await isAccessTokenRevoked(authRepository, payload)) {
|
|
5131
5105
|
logger.warn("[Security Audit] Refused a revoked access token", {
|
|
@@ -7035,4 +7009,4 @@ var auth_exports = /* @__PURE__ */ __exportAll({
|
|
|
7035
7009
|
//#endregion
|
|
7036
7010
|
export { html as $, activeDevEmailSink as A, hashPassword as B, providerVerifiedEmail as C, PUBLIC_STORAGE_PREFIX as Ct, createDataRateLimiter as D, DEFAULT_FUNCTIONS_ANONYMOUS_LIMIT as E, SMTPEmailService as F, getEmailVerificationTemplate as G, verifyPassword as H, createEmailService as I, getUserInvitationTemplate as J, getMagicLinkTemplate as K, assertEmailLinkBases as L, createDevEmailSink as M, extractLinks as N, defaultAuthLimiter as O, registerDevEmailSink as P, escapeHtml as Q, resolveEmailLinkBase as R, pkceTokenParams as S, isOperationAllowed as St, createBuiltinAuthAdapter as T, generateSecurePassword as U, validatePasswordStrength as V, getEmailOtpTemplate as W, resolveEmailBranding as X, getWelcomeEmailTemplate as Y, RawHtml as Z, verifyOidcIdToken as _, safeCompare as _t, resolveRateLimitStoreKind as a, fileTokenAuth as at, createGoogleProvider as b, hasAdministrativeRole as bt, createSlackProvider as c, queryTokenAuth as ct, createDiscordProvider as d, createApiKeyPreAuth as dt, raw as et, createTwitterProvider as f, createFunctionApiKeyGuard as ft, tryVerifyOidcIdToken as g, extractBearerToken as gt, createMicrosoftProvider as h, validateApiKey as ht, createApiKeyStore as i, extractUserFromToken as it, clearActiveDevEmailSink as j, MemoryRateLimitStore as k, createBitbucketProvider as l, requireAdmin as lt, createAppleProvider as m, isApiKeyToken as mt, createCustomAuthAdapter as n, createAuthMiddleware as nt, createSqlRateLimitStore as o, optionalAuth as ot, createFacebookProvider as p, createStorageApiKeyGuard as pt, getPasswordResetTemplate as q, createApiKeyRoutes as r, createRequireAuth as rt, createSpotifyProvider as s, publicObjectAuth as st, auth_exports as t, createAdapterAuthMiddleware as tt, createGitLabProvider as u, requireAuth as ut, createGitHubProvider as v, SERVICE_IDENTITY as vt, createJwksRoutes as w, isPublicStoragePath as wt, oauthCodeFlowSchema as x, httpMethodToOperation as xt, createLinkedinProvider as y, scopeDataDriver as yt, resolveAuthHooks as z };
|
|
7037
7011
|
|
|
7038
|
-
//# sourceMappingURL=auth-
|
|
7012
|
+
//# sourceMappingURL=auth-BVPx33qB.js.map
|