fix(auth): harden logout proxy traps from review feedback
- get() now returns undefined for logged-out providers instead of delegating to target.get() which could bypass the guard - getCredential() in provider-auth returns undefined for logged-out providers instead of falling through to authStorage.get() - getAll() skips logged-out providers at top of loop - list() filters modelsJsonApiKeys against loggedOutProviders - Added remove() trap in provider-auth for clearApiKey flow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -157,7 +157,7 @@ export function mergeAuthStorageReads(
|
|||||||
|
|
||||||
const getCredential = (providerId: string) => {
|
const getCredential = (providerId: string) => {
|
||||||
if (loggedOutProviders.has(providerId)) {
|
if (loggedOutProviders.has(providerId)) {
|
||||||
return authStorage.get(providerId) as StoredCredential | undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return selectCredential(providerId, readAuthStorages);
|
return selectCredential(providerId, readAuthStorages);
|
||||||
};
|
};
|
||||||
@@ -190,6 +190,13 @@ export function mergeAuthStorageReads(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prop === "remove") {
|
||||||
|
return (provider: string) => {
|
||||||
|
loggedOutProviders.add(provider);
|
||||||
|
target.remove(provider);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (prop === "set") {
|
if (prop === "set") {
|
||||||
return (provider: string, credential: AuthCredential) => {
|
return (provider: string, credential: AuthCredential) => {
|
||||||
loggedOutProviders.delete(provider);
|
loggedOutProviders.delete(provider);
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export function createFusionAuthStorage(): AuthStorage {
|
|||||||
if (prop === "get") {
|
if (prop === "get") {
|
||||||
return (provider: string) => {
|
return (provider: string) => {
|
||||||
if (loggedOutProviders.has(provider)) {
|
if (loggedOutProviders.has(provider)) {
|
||||||
return target.get(provider);
|
return undefined;
|
||||||
}
|
}
|
||||||
return choosePreferredStoredCredential(
|
return choosePreferredStoredCredential(
|
||||||
target.get(provider) as StoredCredential | undefined,
|
target.get(provider) as StoredCredential | undefined,
|
||||||
@@ -239,9 +239,12 @@ export function createFusionAuthStorage(): AuthStorage {
|
|||||||
]);
|
]);
|
||||||
const merged: Record<string, StoredCredential> = {};
|
const merged: Record<string, StoredCredential> = {};
|
||||||
for (const providerId of providerIds) {
|
for (const providerId of providerIds) {
|
||||||
|
if (loggedOutProviders.has(providerId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const credential = choosePreferredStoredCredential(
|
const credential = choosePreferredStoredCredential(
|
||||||
(target.get(providerId) as StoredCredential | undefined),
|
(target.get(providerId) as StoredCredential | undefined),
|
||||||
loggedOutProviders.has(providerId) ? undefined : supplementalCredentials[providerId],
|
supplementalCredentials[providerId],
|
||||||
);
|
);
|
||||||
if (credential) {
|
if (credential) {
|
||||||
merged[providerId] = credential;
|
merged[providerId] = credential;
|
||||||
@@ -253,7 +256,12 @@ export function createFusionAuthStorage(): AuthStorage {
|
|||||||
|
|
||||||
if (prop === "list") {
|
if (prop === "list") {
|
||||||
return () => {
|
return () => {
|
||||||
const providers = new Set([...target.list(), ...modelsJsonApiKeys.keys()]);
|
const providers = new Set([...target.list()]);
|
||||||
|
for (const p of modelsJsonApiKeys.keys()) {
|
||||||
|
if (!loggedOutProviders.has(p)) {
|
||||||
|
providers.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const p of Object.keys(supplementalCredentials)) {
|
for (const p of Object.keys(supplementalCredentials)) {
|
||||||
if (!loggedOutProviders.has(p)) {
|
if (!loggedOutProviders.has(p)) {
|
||||||
providers.add(p);
|
providers.add(p);
|
||||||
|
|||||||
Reference in New Issue
Block a user