[PR #5893] fix(common): prevent infinite auth refresh retry loop on permanent token failure #5397

Open
opened 2026-03-17 02:50:57 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/hoppscotch/hoppscotch/pull/5893
Author: @danielalanbates
Created: 2/20/2026
Status: 🔄 Open

Base: mainHead: fix/issue-5885-auth-infinite-retry


📝 Commits (1)

  • f04f3cf fix(common): prevent infinite auth refresh retry loop on permanent token failure (#5885)

📊 Changes

5 files changed (+147 additions, -23 deletions)

View changed files

📝 packages/hoppscotch-common/src/helpers/backend/GQLClient.ts (+37 -2)
📝 packages/hoppscotch-selfhost-web/src/platform/auth/desktop/index.ts (+37 -12)
📝 packages/hoppscotch-selfhost-web/src/platform/auth/web/index.ts (+19 -0)
📝 packages/hoppscotch-sh-admin/src/helpers/auth.ts (+28 -4)
📝 packages/hoppscotch-sh-admin/src/main.ts (+26 -5)

📄 Description

Summary

Closes #5885

When a user's refresh token is permanently invalid (expired, rotated, or cookie deleted), the authExchange in the GQL client enters an infinite retry loop that floods the backend with thousands of GET /v1/auth/refresh requests per minute.

Root cause

In GQLClient.ts, refreshAuth() calls platform.auth.refreshAuthToken() with no retry limit. When didAuthError() returns true, urql calls refreshAuth(). If the refresh fails (returns false), urql retries the original GQL operation, which fails auth again, triggering another refreshAuth() — creating an infinite loop. The same pattern exists in the sh-admin auth exchange.

Additionally, refreshToken() in the selfhost-web auth implementations silently swallow errors and have no mechanism to stop retrying.

Changes

  • packages/hoppscotch-common/src/helpers/backend/GQLClient.ts — Added a consecutive failure counter (AUTH_REFRESH_MAX_RETRIES = 3) to refreshAuth(). After 3 consecutive failures, signs the user out instead of retrying indefinitely. Counter resets to 0 on successful refresh or when a new client is created (e.g. after re-login).

  • packages/hoppscotch-selfhost-web/src/platform/auth/web/index.ts — Added matching failure counter to refreshToken() that short-circuits before making HTTP requests after 3 failures. Counter resets on successful refresh or login.

  • packages/hoppscotch-selfhost-web/src/platform/auth/desktop/index.ts — Same protection for the desktop/Tauri auth flow.

  • packages/hoppscotch-sh-admin/src/main.ts — Added retry limit to the admin panel's authExchange refreshAuth().

  • packages/hoppscotch-sh-admin/src/helpers/auth.ts — Added failure counter to the admin panel's refreshToken().

Behavior after fix

Scenario Before After
Token permanently invalid Infinite retry loop (16,000+ requests/10 min) 3 retries then auto sign-out
Transient network error Infinite retry (eventually recovers) Up to 3 retries, counter resets on success
Successful refresh Works Works (counter reset to 0)
Re-login after sign-out Works Works (counter reset on new client)

Test plan

  • With valid credentials, verify normal auth refresh still works (counter resets on success)
  • Invalidate/delete the refresh token cookie, then trigger a GQL operation — verify the user is signed out after 3 failed refresh attempts instead of looping
  • After being signed out, verify the user can log back in normally
  • Test in the admin panel (sh-admin) with the same invalid token scenario
  • Verify no regressions in the desktop app auth flow

This PR was created with the assistance of Claude Opus 4.6 by Anthropic. Happy to make any adjustments! Reviewed and submitted by a human.

🤖 Generated with Claude Code


Summary by cubic

Stops the infinite auth refresh loop when the refresh token is permanently invalid. Limits retries to 3, then auto signs out to prevent backend request floods. Fixes #5885.

  • Bug Fixes
    • Add a 3-attempt retry cap with consecutive failure counters in GQL client authExchange, selfhost web/desktop refreshToken, and sh-admin.
    • After max failures, sign the user out; counters reset on successful refresh or login.
    • Short-circuit refresh after max failures to avoid unnecessary HTTP calls.

Written for commit f04f3cf495. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/hoppscotch/hoppscotch/pull/5893 **Author:** [@danielalanbates](https://github.com/danielalanbates) **Created:** 2/20/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/issue-5885-auth-infinite-retry` --- ### 📝 Commits (1) - [`f04f3cf`](https://github.com/hoppscotch/hoppscotch/commit/f04f3cf4950ac975603c1d0706320e54ed4e95be) fix(common): prevent infinite auth refresh retry loop on permanent token failure (#5885) ### 📊 Changes **5 files changed** (+147 additions, -23 deletions) <details> <summary>View changed files</summary> 📝 `packages/hoppscotch-common/src/helpers/backend/GQLClient.ts` (+37 -2) 📝 `packages/hoppscotch-selfhost-web/src/platform/auth/desktop/index.ts` (+37 -12) 📝 `packages/hoppscotch-selfhost-web/src/platform/auth/web/index.ts` (+19 -0) 📝 `packages/hoppscotch-sh-admin/src/helpers/auth.ts` (+28 -4) 📝 `packages/hoppscotch-sh-admin/src/main.ts` (+26 -5) </details> ### 📄 Description ## Summary Closes #5885 When a user's refresh token is permanently invalid (expired, rotated, or cookie deleted), the `authExchange` in the GQL client enters an infinite retry loop that floods the backend with thousands of `GET /v1/auth/refresh` requests per minute. ### Root cause In `GQLClient.ts`, `refreshAuth()` calls `platform.auth.refreshAuthToken()` with no retry limit. When `didAuthError()` returns `true`, urql calls `refreshAuth()`. If the refresh fails (returns `false`), urql retries the original GQL operation, which fails auth again, triggering another `refreshAuth()` — creating an infinite loop. The same pattern exists in the `sh-admin` auth exchange. Additionally, `refreshToken()` in the selfhost-web auth implementations silently swallow errors and have no mechanism to stop retrying. ### Changes - **`packages/hoppscotch-common/src/helpers/backend/GQLClient.ts`** — Added a consecutive failure counter (`AUTH_REFRESH_MAX_RETRIES = 3`) to `refreshAuth()`. After 3 consecutive failures, signs the user out instead of retrying indefinitely. Counter resets to 0 on successful refresh or when a new client is created (e.g. after re-login). - **`packages/hoppscotch-selfhost-web/src/platform/auth/web/index.ts`** — Added matching failure counter to `refreshToken()` that short-circuits before making HTTP requests after 3 failures. Counter resets on successful refresh or login. - **`packages/hoppscotch-selfhost-web/src/platform/auth/desktop/index.ts`** — Same protection for the desktop/Tauri auth flow. - **`packages/hoppscotch-sh-admin/src/main.ts`** — Added retry limit to the admin panel's `authExchange` `refreshAuth()`. - **`packages/hoppscotch-sh-admin/src/helpers/auth.ts`** — Added failure counter to the admin panel's `refreshToken()`. ### Behavior after fix | Scenario | Before | After | |----------|--------|-------| | Token permanently invalid | Infinite retry loop (16,000+ requests/10 min) | 3 retries then auto sign-out | | Transient network error | Infinite retry (eventually recovers) | Up to 3 retries, counter resets on success | | Successful refresh | Works | Works (counter reset to 0) | | Re-login after sign-out | Works | Works (counter reset on new client) | ## Test plan - [ ] With valid credentials, verify normal auth refresh still works (counter resets on success) - [ ] Invalidate/delete the refresh token cookie, then trigger a GQL operation — verify the user is signed out after 3 failed refresh attempts instead of looping - [ ] After being signed out, verify the user can log back in normally - [ ] Test in the admin panel (`sh-admin`) with the same invalid token scenario - [ ] Verify no regressions in the desktop app auth flow *This PR was created with the assistance of Claude Opus 4.6 by Anthropic. Happy to make any adjustments! Reviewed and submitted by a human.* 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Stops the infinite auth refresh loop when the refresh token is permanently invalid. Limits retries to 3, then auto signs out to prevent backend request floods. Fixes #5885. - **Bug Fixes** - Add a 3-attempt retry cap with consecutive failure counters in GQL client authExchange, selfhost web/desktop refreshToken, and sh-admin. - After max failures, sign the user out; counters reset on successful refresh or login. - Short-circuit refresh after max failures to avoid unnecessary HTTP calls. <sup>Written for commit f04f3cf4950ac975603c1d0706320e54ed4e95be. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hoppscotch#5397
No description provided.