fix(bootstrap): validate access_key server-side, prevent stale cache bypass
When a URL access_key is present, skip the Dexie cache fast-path in lookup_site_domain entirely — the key must be validated against the API. Previously, a stale cached entry with a previously-valid key would be returned immediately, allowing access even after the key changed or was revoked in the URL. Also: add site_domain_access_key to properties_to_save__site_domain so domain-level keys are persisted to Dexie for cache validation; remove shadow access_key re-declaration in +layout.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -139,9 +139,46 @@ export async function load({ fetch, params, parent, route, url }) {
|
||||
if (cached) {
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
'ROOT LOAD: Found cached site domain. Unblocking layout.'
|
||||
'ROOT LOAD: Found cached site domain. Evaluating cache vs URL key.'
|
||||
);
|
||||
result = cached;
|
||||
|
||||
// If the URL contains an access_key, we must ensure the cached
|
||||
// entry is valid for that key. If the cache has no keys or the
|
||||
// keys don't match, force a live lookup to revalidate.
|
||||
if (access_key) {
|
||||
const cachedSiteKey =
|
||||
(cached as any).access_key ||
|
||||
(cached as any).site_access_key ||
|
||||
(cached as any).site_domain_access_key ||
|
||||
'';
|
||||
const cachedDomainKey =
|
||||
(cached as any).site_domain_access_key ||
|
||||
(cached as any).site_access_key ||
|
||||
(cached as any).access_key ||
|
||||
'';
|
||||
|
||||
if (!cachedSiteKey && !cachedDomainKey) {
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
'BOOTSTRAP: Cache has no access keys; forcing live lookup because URL contains a key.'
|
||||
);
|
||||
// leave `result` null so slow-path lookup runs
|
||||
} else if (
|
||||
access_key === cachedSiteKey ||
|
||||
access_key === cachedDomainKey
|
||||
) {
|
||||
if (log_lvl)
|
||||
console.log('BOOTSTRAP: URL key matches cached access key; using cached object.');
|
||||
result = cached as any;
|
||||
} else {
|
||||
if (log_lvl)
|
||||
console.log('BOOTSTRAP: URL key does not match cached keys; forcing live lookup to revalidate.');
|
||||
// leave `result` null so slow-path lookup runs
|
||||
}
|
||||
} else {
|
||||
// No access_key in URL — safe to use cached value
|
||||
result = cached as any;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (log_lvl)
|
||||
@@ -370,8 +407,6 @@ export async function load({ fetch, params, parent, route, url }) {
|
||||
ae_loc_init['key_checked'] = true;
|
||||
ae_loc_init['allow_access'] = true;
|
||||
} else {
|
||||
const access_key = url.searchParams.get('key');
|
||||
|
||||
if (access_key) {
|
||||
if (log_lvl) {
|
||||
console.log(`root +layout.ts: access_key = ${access_key}`);
|
||||
|
||||
Reference in New Issue
Block a user