fix(auth): bind current local registry and CORS
This commit is contained in:
@@ -81,13 +81,26 @@ export interface LocalSessionUser {
|
||||
roles: readonly Role[];
|
||||
}
|
||||
|
||||
export interface CurrentLocalSessionUser {
|
||||
revision: string;
|
||||
user: LocalSessionUser | undefined;
|
||||
}
|
||||
|
||||
/** Operational validity-source failures must not masquerade as revoked credentials. */
|
||||
export class AuthSessionOperationalError extends Error {
|
||||
constructor() {
|
||||
super("auth_session_operational_error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The route layer supplies the current installation revision and local-registry lookup.
|
||||
* Supplying this hook makes every resolve an authorization-generation check.
|
||||
*/
|
||||
export interface AuthSessionValidity {
|
||||
currentAuthConfigRevision(): string | Promise<string>;
|
||||
findLocalUser(subject: string): LocalSessionUser | undefined | Promise<LocalSessionUser | undefined>;
|
||||
findLocalUser?(subject: string): LocalSessionUser | undefined | Promise<LocalSessionUser | undefined>;
|
||||
currentLocalUser?(subject: string): CurrentLocalSessionUser | Promise<CurrentLocalSessionUser>;
|
||||
}
|
||||
|
||||
export interface AuthSessionStore {
|
||||
@@ -682,10 +695,15 @@ async function recordIsCurrent(record: AuthSessionRecord, validity: AuthSessionV
|
||||
// A root-only store remains useful for creation/diagnostics, but is intentionally incapable
|
||||
// of authenticating a principal. Task 8 must supply config and local-registry dependencies.
|
||||
if (!validity) return false;
|
||||
if (record.method === "local" && validity.currentLocalUser) {
|
||||
const current = await validity.currentLocalUser(record.subject);
|
||||
return typeof current.revision === "string" && current.revision === record.authConfigRevision
|
||||
&& validLocalUser(current.user, record);
|
||||
}
|
||||
const revision = await validity.currentAuthConfigRevision();
|
||||
if (typeof revision !== "string" || revision !== record.authConfigRevision) return false;
|
||||
if (record.method !== "local") return true;
|
||||
return validLocalUser(await validity.findLocalUser(record.subject), record);
|
||||
return validity.findLocalUser === undefined ? false : validLocalUser(await validity.findLocalUser(record.subject), record);
|
||||
}
|
||||
|
||||
const locks = new Map<string, Promise<void>>();
|
||||
@@ -799,7 +817,8 @@ export function createFileAuthSessionStore(
|
||||
}
|
||||
try {
|
||||
if (await recordIsCurrent(record, validity)) return record;
|
||||
} catch {
|
||||
} catch (error) {
|
||||
if (error instanceof AuthSessionOperationalError) throw error;
|
||||
await bridge.remove(root, "sessions", filename);
|
||||
throw invalid();
|
||||
}
|
||||
@@ -815,7 +834,8 @@ export function createFileAuthSessionStore(
|
||||
}
|
||||
try {
|
||||
if (await recordIsCurrent(trusted.value, validity)) return trusted.value;
|
||||
} catch {
|
||||
} catch (error) {
|
||||
if (error instanceof AuthSessionOperationalError) throw error;
|
||||
removeTrusted(directories.sessions, filename, trusted.identity);
|
||||
throw invalid();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user