Fix Kobo sync in fully-local mode (no Kobo account) on modern firmware#1367
Open
thijsdezoete wants to merge 2 commits into
Open
Fix Kobo sync in fully-local mode (no Kobo account) on modern firmware#1367thijsdezoete wants to merge 2 commits into
thijsdezoete wants to merge 2 commits into
Conversation
When Kobo Store proxying is disabled, CWA points oauth_host at itself but only returns a dummy token for every /oauth/* path. Modern Kobo firmware performs OpenID Connect discovery (GET oauth_host/.well-known/openid-configuration) before refreshing an expired access token; with no token_endpoint it requests "a new token from ''", which fails and cancels the entire sync queue before /v1/library/sync runs -- the device just reports "Sync failed". Serve a minimal OIDC discovery document advertising the token endpoint CWA already implements (/oauth/token), so the device can refresh and sync. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
With local OAuth, the device authenticates to Kobo's cloud reading-services (annotations, notebooks, UserStorage, checkforchanges) using CWA's dummy token and gets 401s. The notebook 401 becomes a web request error that aborts the sync batch, so even shelves/collections never commit and the device reports "Sync failed". Point reading_services_host at CWA (the device uses only its scheme+host) and add a before_app_request hook returning benign empty responses for those root /api paths, so the sync can complete. Gated to non-Hardcover, non-proxy setups. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On a fully-local setup (Kobo Store proxying off, no real Kobo account), Kobo
sync silently fails on current firmware (reproduced on 4.45.23684). The web
UI works and
curl-ing the sync endpoints directly returns 200, but pressingSync on the device reports "Sync failed" and no books/collections appear.
Two independent causes, both only triggered once the device's 1-hour access
token expires (so it can look like it "just stopped working" without any config
change):
1. OAuth token refresh can't discover the token endpoint
When proxying is off, CWA points
oauth_hostat itself butHandleOauthRequestreturns a dummy token for every
/oauth/*path — including/oauth/.well-known/openid-configuration. Modern firmware does OIDC discoverythere before refreshing an expired token; with no
token_endpointit logs:So
/v1/library/syncis never even called. (This is why directcurlworks —it carries the path token and skips the OAuth gate the device runs first.)
Fix: serve a minimal OIDC discovery document whose
token_endpointpoints atthe
/oauth/tokenroute CWA already implements.2. Cloud reading-services 401 aborts the whole sync
With local OAuth, the device authenticates its direct calls to Kobo's cloud
reading-services with CWA's dummy token and gets 401s:
Kobo sync is transactional, so this aborts the batch and even shelves never
commit. Note the device treats
reading_services_hostas scheme+host only —it strips the path and calls
/api/...at the site root.Fix: point
reading_services_hostat CWA and add abefore_app_requesthookreturning benign empty responses for the reading-services paths
(
/api/v3/content/checkforchanges,/api/v3/content/<uuid>/annotations,/api/UserStorage/*,/api/internal/notebooks). Gated to non-Hardcover setups.Result
Device log after the fixes:
SyncLibraryCommand finished→finished sync clientwith no
WebRequestErr; the device reports "Sync complete" and books +collections sync.
Notes / out of scope
mainhas the same code paths.kobo_synced_books(viaadd_synced_booksduring response generation) even though the device discardsthe aborted batch, so they're permanently excluded from
NewEntitlement. Oncesync succeeds this no longer accumulates; existing stale rows need a one-time
kobo_synced_booksclear (force full re-sync). Could be hardened separately byonly recording synced books on a committed sync.