[PR #4706] [MERGED] Reload on all redirects to handle Cloudflare Access auth expiration #5545

Closed
opened 2026-02-28 21:14:10 -06:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/actualbudget/actual/pull/4706
Author: @rgoldfinger
Created: 3/29/2025
Status: Merged
Merged: 4/17/2025
Merged by: @matt-fidd

Base: masterHead: rgoldfinger-patch-1


📝 Commits (7)

📊 Changes

2 files changed (+14 additions, -7 deletions)

View changed files

📝 packages/loot-core/src/platform/server/fetch/index.ts (+8 -7)
upcoming-release-notes/4706.md (+6 -0)

📄 Description

Fixes #4422

This PR addresses an issue when running Actual behind Cloudflare Access. When the Access token expires, the client is unable to reach the server. This is especially problematic on mobile Safari which seems to have no way to force a hard reload.

When this happens, requests to the Actual server are 302 redirected to the Cloudflare login page, but the redirected url hits a CORS error.

Access to fetch at 'https://<cf-account-name>.cloudflareaccess.com/cdn-cgi/access/login/<fqdn>?kid=<redacted>&redirect_url=%2Fsync%2Fsync&meta=<redacted>' (redirected from 'https://<fqdn>/sync/sync') from origin 'https://<fqdn>' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Critically, the fetch request throws an error TypeError: Failed to fetch where it's not possible to detect that it's redirected.

The solution implemented here was inspired by a similar fix to the same issue in Silver Bullet.

By setting redirect: 'manual when making the fetch request, we can detect this redirect, since we'll get a response back rather than an error.

"manual"
Retrieves an opaque-redirect filtered response when a request is met with a redirect, to allow a service worker to replay the redirect offline.

https://fetch.spec.whatwg.org/#concept-request-redirect-mode

With this option, the response we get back will have type: 'opaqueredirect' when redirected:

opaqueredirect: The fetch request was made with redirect: "manual". The Response's status is 0, headers are empty, body is null and trailer is empty.

https://developer.mozilla.org/en-US/docs/Web/API/Response/type

Is this change safe to make?

In https://github.com/actualbudget/actual/pull/3286, we started reloading whenever the origin changed. Therefore, this change should only catch the additional case of redirects where the origin stayed the same, but the path changed.

I have searched the codebase for any cases when this might be happening, and could not find any. I searched for .redirect (res.redirect), redirect, 301, 302, and .location (res.location).


🔄 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/actualbudget/actual/pull/4706 **Author:** [@rgoldfinger](https://github.com/rgoldfinger) **Created:** 3/29/2025 **Status:** ✅ Merged **Merged:** 4/17/2025 **Merged by:** [@matt-fidd](https://github.com/matt-fidd) **Base:** `master` ← **Head:** `rgoldfinger-patch-1` --- ### 📝 Commits (7) - [`312cb8f`](https://github.com/actualbudget/actual/commit/312cb8f2a25b19d74f86e691e9c41205ff3f1e5f) Reload on all redirects - [`124f921`](https://github.com/actualbudget/actual/commit/124f921821bf6e28e07213b8f92923722a196685) Update index.ts - [`076968e`](https://github.com/actualbudget/actual/commit/076968e5ad53a688a60762a684d272695f5d01d7) Create release notes - [`af1c92b`](https://github.com/actualbudget/actual/commit/af1c92ba3338d35b94f61dc7446d07d83e21a4b8) Update index.ts - [`9425e72`](https://github.com/actualbudget/actual/commit/9425e72b117b28111953865a5f663012e3665ef7) Update index.ts - [`f957d79`](https://github.com/actualbudget/actual/commit/f957d79e22400a19a46b71752ab74380b3ea5e78) Update 4706.md - [`4ee9f09`](https://github.com/actualbudget/actual/commit/4ee9f09f097d2d6cfedb8a750d9a67c96a42e1ff) Merge branch 'master' into rgoldfinger-patch-1 ### 📊 Changes **2 files changed** (+14 additions, -7 deletions) <details> <summary>View changed files</summary> 📝 `packages/loot-core/src/platform/server/fetch/index.ts` (+8 -7) ➕ `upcoming-release-notes/4706.md` (+6 -0) </details> ### 📄 Description Fixes #4422 This PR addresses an issue when running Actual behind Cloudflare Access. When the Access token expires, the client is unable to reach the server. This is especially problematic on mobile Safari which seems to have no way to force a hard reload. When this happens, requests to the Actual server are 302 redirected to the Cloudflare login page, but the redirected url hits a CORS error. ``` Access to fetch at 'https://<cf-account-name>.cloudflareaccess.com/cdn-cgi/access/login/<fqdn>?kid=<redacted>&redirect_url=%2Fsync%2Fsync&meta=<redacted>' (redirected from 'https://<fqdn>/sync/sync') from origin 'https://<fqdn>' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. ``` Critically, the fetch request throws an error `TypeError: Failed to fetch` where it's not possible to detect that it's redirected. The solution implemented here was inspired by a [similar fix to the same issue in Silver Bullet](https://github.com/silverbulletmd/silverbullet/issues/1091). By setting `redirect: 'manual` when making the fetch request, we can detect this redirect, since we'll get a response back rather than an error. > "manual" > Retrieves an [opaque-redirect filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect) when a request is met with a redirect, to allow a service worker to replay the redirect offline. https://fetch.spec.whatwg.org/#concept-request-redirect-mode With this option, the response we get back will have `type: 'opaqueredirect'` when redirected: > `opaqueredirect`: The fetch request was made with redirect: "manual". The Response's status is 0, headers are empty, body is null and trailer is empty. https://developer.mozilla.org/en-US/docs/Web/API/Response/type ### Is this change safe to make? In https://github.com/actualbudget/actual/pull/3286, we started reloading whenever the origin changed. Therefore, this change should only catch the additional case of redirects where the origin stayed the same, but the path changed. I have searched the codebase for any cases when this might be happening, and could not find any. I searched for `.redirect` (`res.redirect`), `redirect`, `301`, `302`, and `.location` (`res.location`). --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-02-28 21:14:10 -06:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#5545