Skip to content
This repository was archived by the owner on Sep 21, 2026. It is now read-only.

fix(oauth2): keep the consent buttons disabled while the redirect is in flight - #3203

Closed
ChiragAgg5k wants to merge 1 commit into
mainfrom
fix-oauth2-consent-redirect-busy
Closed

ChiragAgg5k wants to merge 1 commit into
mainfrom
fix-oauth2-consent-redirect-busy

Conversation

@ChiragAgg5k

@ChiragAgg5k ChiragAgg5k commented Sep 21, 2026

Copy link
Copy Markdown
Member

What

The consent card re-enabled its Authorize and Cancel buttons right after assigning window.location.href, because the finally block reset the busy flag before the browser had actually left the page. The browser keeps the consent page on screen until the redirect target returns its first byte. For a Sites preview that is the whole edge callback chain plus the runtime cold start, which can take many seconds, so the user could keep pressing Authorize.

A second press hits POST /oauth2/console/grants/:id/approve on a grant whose code was already issued, which Cloud rejects with grant-not-found. The user then sees an error toast for a flow that is in fact succeeding.

Fix

  • Add a redirecting state that is set right before the web redirect is issued and folded into busy, so both buttons stay disabled for the whole redirect chain and cold start.
  • Show the spinner and Redirecting… on the Authorize button while in that state.
  • Clear redirecting on pageshow when the page is restored from the bfcache after a back navigation, so the card is not left stuck disabled.
  • Same treatment for the reject path.

The already-consented fast path in consent/+page.svelte already stays in the loading phase during a web redirect, so it is unchanged.

Test plan

  • Open a protected Sites preview whose runtime is cold, authorize, and confirm the button switches to Redirecting… and stays disabled until the site renders
  • Press back from the site and confirm the consent card is interactive again
  • Cancel path shows the same behaviour

Verification

Reproduced with Playwright against the dev server: the console API is mocked, approve returns a redirect to a route that never sends its first byte (a preview cold-starting behind edge), then the Authorize button is pressed once and three more times over the next ~2 seconds.

Before After
Button after the first press Authorize, enabled Redirecting…, disabled
Approve calls sent 4 1
Before After
before after

…in flight

The approve and reject handlers reset their busy flag right after handing the browser a redirect, so the buttons re-enabled while the client was still loading. On a slow client (a Sites preview cold-starting behind edge) the user could press Authorize again and get a grant-not-found error for a flow that was succeeding.
@appwrite

appwrite Bot commented Sep 21, 2026

Copy link
Copy Markdown

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Preview deployments create instant URLs for every branch and commit

@greptile-apps

greptile-apps Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR appears safe to merge, with non-blocking follow-up needed for the misleading Cancel-path progress UI and automated browser coverage.

Fix All in Claude CodeFindings

  1. P2 Cancel Progress Appears Elsewhere
  2. P2 Redirect Lifecycle Lacks Coverage
Fix with agent prompt
### Issue 1
src/routes/(public)/oauth2/consent-card.svelte:851-859
After Cancel starts a web redirect, `finally` clears `rejecting` while `redirecting` remains true. Because only the Authorize button renders the shared redirect state, Cancel returns to its idle label while Authorize misleadingly shows the spinner and “Redirecting…”. Track which action started the redirect so its progress appears on the correct button.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

### Issue 2
src/routes/(public)/oauth2/consent-card.svelte:86-94
The new redirect lifecycle has no automated observable-behavior coverage. Regressions in the persisted `pageshow` reset or either slow redirect path could leave the controls disabled or show progress on the wrong action without being caught. Add browser-level tests for slow approve and reject redirects plus back-navigation restoration, without asserting internal state flags.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR keeps OAuth consent actions disabled while an HTTP(S) approval or denial redirect remains in flight and restores interactivity when the consent page returns from the browser’s back-forward cache.

  • Adds redirect-specific busy state to both consent actions.
  • Adds persisted pageshow handling for back-navigation restoration.
  • Adds redirect progress text, although rejection currently displays that progress on the Authorize action.
  • The browser lifecycle behavior is not covered by automated tests.

Reviews (1) · Last reviewed commit: "fix(oauth2): keep the consent buttons di..."

Comment on lines +851 to 859
{#if approving || redirecting}
<Spinner size="s" />
{:else}
<Icon icon={IconCheck} slot="start" size="s" />
{/if}
{approving ? 'Authorizing…' : 'Authorize'}
{redirecting ? 'Redirecting…' : approving ? 'Authorizing…' : 'Authorize'}
</Button>
<Button fullWidth secondary disabled={busy} on:click={reject}>
{rejecting ? 'Cancelling…' : 'Cancel'}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Cancel progress appears elsewhere

After Cancel starts a web redirect, finally clears rejecting while redirecting remains true. Because only the Authorize button renders the shared redirect state, Cancel returns to its idle label while Authorize misleadingly shows the spinner and “Redirecting…”. Track which action started the redirect so its progress appears on the correct button.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/routes/(public)/oauth2/consent-card.svelte
Line: 851-859

Comment:
**Cancel progress appears elsewhere**

After Cancel starts a web redirect, `finally` clears `rejecting` while `redirecting` remains true. Because only the Authorize button renders the shared redirect state, Cancel returns to its idle label while Authorize misleadingly shows the spinner and “Redirecting…”. Track which action started the redirect so its progress appears on the correct button.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code Fix in Codex

Comment on lines +86 to +94
onMount(() => {
// A back navigation restores this page from the bfcache with `redirecting`
// still set; the user must be able to act again.
const restore = (event: PageTransitionEvent) => {
if (event.persisted) redirecting = false;
};
window.addEventListener('pageshow', restore);
return () => window.removeEventListener('pageshow', restore);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redirect lifecycle lacks coverage

The new redirect lifecycle has no automated observable-behavior coverage. Regressions in the persisted pageshow reset or either slow redirect path could leave the controls disabled or show progress on the wrong action without being caught. Add browser-level tests for slow approve and reject redirects plus back-navigation restoration, without asserting internal state flags.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/routes/(public)/oauth2/consent-card.svelte
Line: 86-94

Comment:
**Redirect lifecycle lacks coverage**

The new redirect lifecycle has no automated observable-behavior coverage. Regressions in the persisted `pageshow` reset or either slow redirect path could leave the controls disabled or show progress on the wrong action without being caught. Add browser-level tests for slow approve and reject redirects plus back-navigation restoration, without asserting internal state flags.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

@ChiragAgg5k

Copy link
Copy Markdown
Member Author

Closing: the consent page users actually hit is served by the new console; the fix moves there.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant