Skip to content

fix(backend): revoke placeholder UserApiKey on OAuth callback denial#616

Merged
kaiweijw merged 1 commit intomainfrom
fix/oauth-callback-mark-placeholder-revoked
May 4, 2026
Merged

fix(backend): revoke placeholder UserApiKey on OAuth callback denial#616
kaiweijw merged 1 commit intomainfrom
fix/oauth-callback-mark-placeholder-revoked

Conversation

@kaiweijw
Copy link
Copy Markdown
Collaborator

@kaiweijw kaiweijw commented May 4, 2026

Summary

Completes the OAuth-denial detection story started in #614. When the OAuth provider returns error=access_denied (e.g. the user clicked Cancel on the provider page), the backend now revokes the placeholder UserApiKey instead of leaving it in pending_auth until TTL. The wizard's polling — which already recognizes revoked as a terminal failure status (#614) — exits within ~2 seconds with the user-friendly "canceled or denied" message instead of waiting the full 5-minute deadline.

closes #599

What changed

  • New user_api_key_service::revoke_pending_placeholders_for_provider helper that finds (user_id, provider_config_id, status: pending_auth, credential_type != "node_managed") placeholders and revokes each through the existing atomic revoke_api_key_if_pending (race-safe against late OAuth-success callbacks).
  • generic_oauth_callback_impl's error branch now best-effort-peeks the OAuth state, resolves the effective owner (target_user_id first, then user_id), and revokes the matching placeholder. Every failure mode (missing state, invalid state, DB error) still returns the redirect — the audit log captures the failure for ops triage.

Notes for reviewers

  • We deliberately do NOT add a new denied status. The existing revoked status keeps the enum lean and PR fix: detect OAuth/device-code denial in CLI and wizard polling #614 already wired the frontend to recognize revoked / failed / expired as terminal.
  • node_managed placeholders are excluded because they don't authorize via OAuth — they're configured on the node agent.
  • Any admin-on-behalf-of flow (oauth_state.target_user_id set) correctly revokes the placeholder under the SA / org user, not the initiating admin.

Test plan

  • cargo test -p nyxid revoke_pending_placeholders_for_provider — 5 service-level tests (pending revoke, skip active, skip node_managed, empty DB, provider scoping)
  • cargo test -p nyxid generic_oauth_callback — 3 handler tests (denial + state revokes, denial without state redirects only, denial + invalid state tolerated)
  • cargo test (full suite)
  • Manual: trigger the wizard for any OAuth provider (e.g. nyxid service add llm-anthropic), click Cancel on the provider page, confirm the wizard exits within ~2 seconds with "Authorization didn't complete (it may have been canceled or denied on the provider page). Cancel and re-run to try again."

@kaiweijw kaiweijw merged commit 8bd9ce1 into main May 4, 2026
10 checks passed
@kaiweijw kaiweijw deleted the fix/oauth-callback-mark-placeholder-revoked branch May 4, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] [CLI Wizard] Local wizard page does not sync final state after OAuth success or cancellation

1 participant