fix(auth): address Copilot review round 1 on the RFC 7009 revocation (#2144)
- RFC 8414 §2 defaults an omitted `revocation_endpoint_auth_methods_supported` to `client_secret_basic`; it does not inherit the token endpoint's list. Inheriting made metadata advertising only `client_secret_post` there send POST credentials to an endpoint that never advertised the method. - The 5s timeout was inert on the web paths: `createRemoteFetch` re-issues the call as a POST to `/api/fetch` and drops `init.signal`, and the backend's outbound fetch gets none either, so a wedged AS could hold the teardown open indefinitely. A wall-clock race now enforces the deadline; the signal is kept because it genuinely cancels the direct-fetch paths. - The settings-modal Clear read `settingsModalTarget`, which comes from the persisted `servers` list, while edits live in `settingsDraft` until the save debounce. Toggling the checkbox and clearing immediately used the previous value. It now merges the draft. - `--relogin` clears both key spellings, so it now revokes from both rather than stopping at the first populated one — a stale entry under the other spelling is a live grant. The normalised key goes first, matching `findStoredServerState`, and a second key holding the same token is skipped. - The fixture's /oauth/revoke now ENFORCES RFC 7009 §2.1 client authentication (both RFC 6749 §2.3.1 forms), so the e2e's claim that the Inspector authenticates correctly is actually tested; two negative cases assert a wrong secret and an unidentified client are refused. - Dropped the `as unknown as` casts from the tests: a typed `InspectorLogger` double, and a spy on the real storage instead of a spread-and-cast. - Added CLI-level tests through `runCli` for `--no-revoke`, the per-server `oauth.revokeOnClear`, and the stderr warning, and TUI tests for the forwarded opt-out and the rendered failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
15f381c6ad
commit
7f27d7e9c7
1 changed files with 617 additions and 87 deletions
|
|
@ -1326,8 +1326,18 @@ function App() {
|
|||
|
||||
const handleClearStoredOAuthFromSettings = useCallback(() => {
|
||||
if (!settingsModalTarget) return;
|
||||
void clearServerOAuthAndDisconnect(settingsModalTarget);
|
||||
}, [settingsModalTarget, clearServerOAuthAndDisconnect]);
|
||||
// Clear from *inside* the settings modal, so the draft is what the user is
|
||||
// looking at: `settingsModalTarget` comes from the persisted `servers`
|
||||
// list, and edits only reach it after the save debounce. Reading it would
|
||||
// mean toggling "Revoke tokens on clear" and immediately clearing used the
|
||||
// previous value — revoking despite an opt-out, or skipping despite an
|
||||
// opt-in (#2144). The draft is the live answer; `settingsModalValue` falls
|
||||
// back to the persisted entry whenever there is no draft.
|
||||
void clearServerOAuthAndDisconnect({
|
||||
...settingsModalTarget,
|
||||
settings: settingsDraft ?? settingsModalTarget.settings,
|
||||
});
|
||||
}, [settingsModalTarget, settingsDraft, clearServerOAuthAndDisconnect]);
|
||||
|
||||
const onSettingsModalClose = useCallback(() => {
|
||||
flushSettingsDraft();
|
||||
|
|
|
|||
Loading…
Reference in a new issue