mirror of
https://github.com/actualbudget/actual.git
synced 2026-07-16 23:26:48 -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
sqlparam-nullable-query-params
cross-version-sync-stage2
claude/transaction-column-manager-cp0u0w
claude/verify-migration-guardrails-i82c8m
dependabot/npm_and_yarn/npm_and_yarn-cd62b4b37a
tabedzki/feat/replacing-month-picker-with-day-picker
delay-initial-sync-until-loaded
jfdoming/mobile-app-build
cross-version-sync-compat
jfdoming/api-tokens-part-1
jfdoming/api-tokens-part-2
jfdoming/api-tokens-part-3
jfdoming/mobile-app-updates
claude/budget-version-migration-compat-151jlr
claude/worker-error-serialization-9iqtl7
claude/react-table-library-research-afx83z
claude/issue-8401-regression-test-9nw9l3
jfdoming/mobile-app-foundation-part-1
jfdoming/mobile-app-scaffold
release
ai-fix-cleanup-def-8290
claude/relaxed-shannon-jusywa
claude/fervent-keller-s6f2fq
claude/determined-feynman-st1y9z
claude/wizardly-einstein-vi2wce
claude/sweet-albattani-7nseio
feat/bank-sync-per-budget-file
claude/affectionate-cannon-y0kc82
claude/dependabot-findings-m9pgmb
claude/mac-app-ios-publish-zjs1lz
claude/vigilant-tesla-aiiyos
depot-migrate-secrets-1781296330308
claude/quirky-cerf-v5qck7
claude/animation-removal-alternative-2etfh1
claude/netlify-preview-comments-consolidate-9XPYa
osc/7391-error-boundaries-reports
claude/pensive-dijkstra-7DYui
claude/server-app-version-mismatch-HTCGv
claude/pr-8027-review-feedback-mELuO
claude/zealous-wozniak-e5pO0
claude/intelligent-heisenberg-BSHJq
claude/translation-download-refactor-jFRsO
claude/mobile-performance-ideas-G9PAO
claude/github-issue-7988-5A5ly
blacksmith-migration-ff70d2d
claude/great-mayer-KRvOk
claude/react-native-ios-compilation-fcJh5
claude/serene-goldberg-58xv0
claude/kind-euler-LVG3K
release-automation/edge-nightly
7710-bundle-migrations
claude/fix-docker-build-error-WMfed
claude/llm-compatible-release-notes-t20Nr
7710-tests-tdd
cursor/transaction-table-rewrite-f077
claude/plan-ci-secure-context-OtEe1
claude/fix-issue-7667-DPXi3
cursor/resolve-pr-7449-ee11
claude/fix-typescript-build-error-JPtZ5
copilot/add-repository-configs-to-packages
worktree-compressed-drifting-ritchie
claude/api-consumer-verification-kfz1K
pr-7454
claude/fix-issue-7410-LLLQ4
revert-7281-generate-icons
react-query-useSchedules
copilot/sub-pr-6140
package-upgrades
v26.7.0
v26.6.0
v26.5.2
v26.5.1
v26.5.0
v26.4.0
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
tech-support
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. 🤐