mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-09 03:32:54 -05:00
[Feature] OIDC Refresh Tokens #2190
Closed
opened 2026-02-28 20:05:58 -06:00 by GiteaMirror
·
4 comments
No Branch/Tag Specified
master
claude/fix-simplefin-ssrf-T31gX
claude/release-notes-validation-X7rvR
matiss/7155
claude/fix-simplefin-batch-sync-O8LcD
ai/custom-theme-dual-prefs
matiss/fix-6804
add-claude-github-actions-1772738270730
claude/analyze-internal-errors-4k6O2
react-query-rules
react-query-useSchedules
matiss/separate-lint-format
dependabot/npm_and_yarn/ajv-6.14.0
cursor/sync-performance-notification-9899
react-query-prefs
matiss/chunked-sync-and-progress-ux
v26.2.1
copilot/sub-pr-6880
fix-react-query-clear-on-close-budget
copilot/sub-pr-6140
feat/auto-note
feat/scoped-bank-sync
cursor/desktop-transactions-react-table-1d0c
fix-exhaustive-deps-App
copilot/fix-find-replace-bug
release/v26.2.0-pre
matiss/browser-tests
mobile-fix-drag-and-drop-across-groups
budget-table-v2
PayeeAutocomplete2
pglite
bugfix/plugins/fix-plugins-sw
feat/plugins/plugins-core-package
prerelease
matiss/unicode-minus-fix
cursor/fix-actual-github-issue-6206-gemini-3-pro-preview-9c37
TransactionFormPage
cursor/implement-mortgage-and-loan-account-type-78ca
tests-update-fill-with-pressSequentially
mobile/link-modal
deps/25.11
cursor/fix-update-vrt-apply-ci-job-dispatch-b324
sync-server-plugins
cursor/propose-patch-for-github-issue-5680-2a18
fix/compiler-preserve-inner-dollar-escapes
cursor/analyze-actual-budget-issue-and-propose-fix-5b70
coderabbitai/docstrings/0c070e5
cursor/add-wip-prefix-and-comment-to-prs-d78d
jfdoming/08-21-auto-focus-on-navigate-in-all-browsers
show-totals-on-mobile-budget-banners
allow-child-transactions-make-transfer
mobile-calculator-keyboard
payee-geolocation
enhance/restore_scroll_position
dm-fix-second-click-on-mobile-new-transaction-2
scrollToLocationBudget
alert-autofix-38
tsconfig-composite
mobile-fix-uncategorized-transactions-on-tracking-budgets
server-budget-handlers
fix-sql-injection-in-cleanup-template
non-chrome-draggable-workaround
mobile-budget-page-swipe-navigation
ts-db-all
stable
dark-theme-with-brand-colors
fix-mobile-delete-group
ts-db-select
UnderKoen/reconcile-context-menu
master-before-server-merge
v25.2.1
ts-runQuery
rename-redux-hooks
UnderKoen/3557-persist-state-in-history
remove-redux-CLOSE_BUDGET
fix-exhaustive-deps-errors-FinancesApp
redux-toolkit-createSlice-backup
accounts-function-component
ts-useSplitsExpanded
loot-core-server-package
useTransactios-in-TransactionEdit
react-aria-input
move-redux-to-desktop-client
QueryState-type
fix-themes-applied-late
mobile-vrts
revert-3295-spendingCardFix
react-aria-button-4
split-payee-on-mobile
twk3/pin-apis-crdt
notes-tag-autocomplete
ts-LoadBackup
dnd-kit
package-upgrades
v26.3.0
v26.2.1
v26.2.0
v26.1.0
v25.12.0
v25.11.0
v25.10.0
v25.9.0
v25.8.0
v25.7.1
v25.7.0
v25.6.1
v25.6.0
v25.5.0
v25.4.0
v25.3.1
v25.3.0
v25.2.1
v25.2.0
v25.1.0
v24.12.0
v24.11.0
v24.10.1
v24.10.0
v24.9.0
v24.8.0
v24.7.0
v24.6.0
v24.5.0
v24.4.0
v24.3.0
v24.2.0
v24.1.0
v23.12.0
v23.11.0
v23.10.0
v23.9.0
v23.8.1
v23.8.0
v23.7.2
v23.7.1
v23.7.0
v23.6.0
v23.5.0
v23.4.2
v23.4.1
v23.4.0
v23.3.2
v23.3.0
v23.2.9
v23.2.5
v23.1.12
v22.12.9
Labels
Clear labels
AI generated
API
bank sync
budgeting
bug
can’t replicate
dependencies
docker
documentation
electron
experimental feature
feature
feedback
goal templates
good first issue
help wanted
importers
maintenance
needs info
needs testing
needs triage
needs votes
openid
payees
pull-request
regression
reports
responsive
rules
schedules
server
✨ merged
split transactions
tech debt
theme
transaction import
transaction reconciliation
transactions
translations
upstream
user interface
✅ approved
wontfix
Mirrored from GitHub Pull Request
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/actual#2190
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @joneshf on GitHub (Jun 11, 2025).
Verified feature request does not already exist?
💻
Pitch: what problem are you trying to solve?
The best practice for an OpenID Provider (OP) is to use short-lived access tokens (some default to 5-15 minutes). Actual seems to only implement the Authorization Code Flow without Refresh Tokens. What that means in practice for Actual is that using OIDC logs you out frequently (whenever the Access Token expires) and you're forced to re-login frequently.
Although there's nothing technically wrong with the current implementation, I doubt most folks would expect this UX. I think most folks expect that with OIDC, they would appear to be logged in for a longer amount of time by way of Actual refreshing tokens transparently.
Describe your ideal solution to this problem
It seems like Actual should implement Refresh Tokens.
The
openid-clientpackage mentions that it supports Refresh Tokens in the README. It also has slightly more detailed API documentation. So it seems like the package can be used to do the heavy lifting.I imagine that there would need to be a new column added to the
sessionstable for storing refresh tokens. Something like:The idea being that if a session's
authcolumn isopenid, it can optionally have a Refresh Token. It should also prevent a data anomaly like a session with anauthcolumn ofpasswordhaving a Refresh Token (which doesn't seem to be a valid use case for Actual). Since therefresh_tokencolumn is nullable, it should allow the current behavior of not using Refresh Tokens if someone doesn't want to use them, an OP doesn't support them, or whatever other reason. Refresh Tokens should be per-session to support uses cases like a person can logging in from multiple devices.I'm not familiar enough with OIDC to know whether or not the OP would give back an expiration for a Refresh Token. But regardless, it doesn't seem like it would be useful to store it, as the OP is the source of truth on expiration of the Refresh Token. I.e. the Refresh Token may expire for a different reason on the OP's side that isn't time-related.
In order to implement Refresh Tokens, it seems like one of two things needs to happen:
For OPs that support the
offline_accessscope (like Authelia, Authentik, Keycloak, etc.) it needs to be added to the scopes requested to implement Refresh Tokens. For OPs that have an ad-hoc method of implementing Refresh tokens using a non-standard URL parameter (Dropbox'stoken_access_type=offline, Google'saccess_type=offline, maybe others) it needs to be added to the authorization URL to implement Refresh Tokens.Refresh tokens are an optional scope/URL parameter. The Design Strategy of Actual seems to hint that this shouldn't actually be optional, but required, in order to limit configuration sprawl. But given that Refresh Tokens are implementation-specific (the OP might support scopes, or an ad-hoc URL parameter) it seems like this will need to be two new OIDC environment variables. Maybe something like
ACTUAL_OPENID_SCOPESthat is all scopes (e.g.ACTUAL_OPENID_SCOPES='openid email profile offline_access') andACTUAL_OPENID_AUTHORIZATION_URL_ADDITIONAL_PARAMETERSthat get appended to the authorization URL (e.g.ACTUAL_OPENID_AUTHORIZATION_URL_ADDITIONAL_PARAMETERS='access_type=offline&prompt=consent). It's not ideal to have structured data be encoded as strings like this, but I'm not sure there are much better options. In any case, I don't currently have a strong opinion one way or the other how this would be implemented.I checked the box mentioning that I'd be willing to submit a PR, but I'm not sure when I'd be able to do that. I've looked briefly at the code, but don't fully understand all the code paths to know where to make the change. All this to say, I wouldn't wait for me to implement this feature. Some pointers about where to start implementing would be helpful for myself or anyone else that might be interested in contributing.
Teaching and learning
I think this feature, and the OIDC configuration in general, could be more discoverable with documentation about the scopes requested. Right now, OIDC is requesting
openid,email, andprofile:a025d2b621/packages/sync-server/src/accounts/openid.js (L160)These scopes are fine, but near as I can tell, they're not documented anywhere.
openidis required, so there's no getting away from that. But it doesn't hurt to say that explicitly.emailandprofileare used to upsert information for the user:a025d2b621/packages/sync-server/src/accounts/openid.js (L227-L232)a025d2b621/packages/sync-server/src/accounts/openid.js (L258-L267)a025d2b621/packages/sync-server/src/accounts/openid.js (L287-L290)The reasons for them all make sense, but it's not very visible.
Refresh Tokens need the
offline_accessscope. Unless folks have done their own research to figure out what theoffline_accessscope means (and why it's normal to request it) it's an oddly named scope to request. The documentation could definitely benefit from at least explaining thatoffline_accessis a common/normal scope that provides the UX of long lasting sessions in a secure manner, and importantly is required for this feature to work properly.@github-actions[bot] commented on GitHub (Jun 11, 2025):
✨ Thanks for sharing your idea! ✨
This repository uses lodash style issue management for enhancements. That means enhancement issues are automatically closed. This doesn’t mean we don’t accept feature requests, though! We will consider implementing ones that receive many upvotes, and we welcome contributions for any feature requests marked as needing votes (just post a comment first so we can help you make a successful contribution).
The enhancement backlog can be found here: https://github.com/actualbudget/actual/issues?q=label%3A%22needs+votes%22+sort%3Areactions-%2B1-desc+
Don’t forget to upvote the top comment with 👍!
@Mansarde commented on GitHub (Jun 11, 2025):
Now that's a high-quality feature request.
Not just well researched, links to everything, as well as suggestions for how it could be implemented, but also written in a nice broken-up structure so it's easy to consume.
You don't see that every day. Kudos for putting in the effort, ser! 🍻
@joneshf commented on GitHub (Jun 11, 2025):
Well I can't take credit for this. I used the feature request issue template. It provided the structure. I would've given less detail without it 😅.
@Mansarde commented on GitHub (Jun 11, 2025):
It's the effort and quality content you put in though that deserves appreciation.
I don't do well with praise myself, so if it's the same for you, then you have my apologies.
You'll get my kudos regardless though, as I feel that effort like this should be lauded when it happens, to encourage others to strive for the same. 👏
But I'll shut up about it now though. 🤐