Google Reader API: Add feed icon URL endpoint#3195
Conversation
What's the point of this? |
|
@jvoisin I went with this direction given a comment from the initial "Share article" PR #475 (comment)
So in the same way, this avoids exposing the internal Icon or Feed IDs for these endpoints. |
d3b1264 to
b0304de
Compare
internal/googlereader/handler.go
Outdated
| builder := response.New(w, r) | ||
| builder.WithHeader("Content-Type", icon.MimeType) | ||
| builder.WithBody(icon.Content) | ||
| builder.Write() |
There was a problem hiding this comment.
It would be nice to use HTTP caching similar to the web ui in feed_icon.go.
There was a problem hiding this comment.
Good call. I copied over that code but happy to work out an abstraction if desired.
Testing in my browser, the second call correctly returns 304 Not Modified.
e52949d to
d8a1df1
Compare
Then you might want to use something like an HMAC instead, as an attacker could simply download a bunch of favicon from popular feeds, and check if they exist on the navidrome instance. |
|
HMAC could work. I'll take another pass at this. |
|
HMAC requires a secret key. How would that be implemented? |
|
There's a few options, really open to any: Option 1: Integration level Add a secret to the ALTER TABLE integrations ADD COLUMN googlereader_salt text ...;On result, check The upside is that this would only add a single row to the database, and only populate it if the Google Reader integration is enabled. The downside is that it's relatively resource intensive: several SQL queries, and re-computation of HMACs on each request. Option 2: Icon level With this option, the secret isn't added as an HMAC, it's generated alongside each icon either as a random string or something like a UUIDv4. The generated URL will use the unique, random alphanumeric value in the same way that the "share article": ALTER TABLE icons ADD COLUMN share_code text ...;The subscription list will use The upside with this approach is that it's much lighter. No extra hashing involved. The downside is that it shifts the complexity from computation to database storage. All things equal, option 2 would be my approach to avoid hashing and heavy SQL queries. |
a8f0460 to
4f6b43b
Compare
|
Updated to use a generated On fetch, the requested HMAC is compared with all generated icon HMACs. |
4f6b43b to
7518185
Compare
|
The I think we should keep it simple. The media proxy feature also uses HMAC, and users can specify the secret value using the MEDIA_PROXY_PRIVATE_KEY config option. If no value is specified, a random secret is generated at startup. The same mechanism could be used for feed icons. This approach could be generic enough to support both the Miniflux REST API and the Google Reader API in the future.
Option 2 that you mentioned in the previous comment also looks fine to me. Using |
|
Hey @fguillot thanks for reviewing this again. If you're ok with option 2 - |
7518185 to
bae08be
Compare
| _, err = tx.Exec(sql) | ||
| return err | ||
| }, | ||
| func(tx *sql.Tx, _ string) (err error) { |
There was a problem hiding this comment.
similar to a previous users migration (link) this migration
- Finds empty
external_id's - Updates each
external_idto a random hex value - Commits
This could be done purely in SQL, but the alternatives are way more involved:
- Pull in pgcrypto which would require pulling in OpenSSL as a dep and enabling the extension
- Hand write a random function for a one-off (example from brandur.org)
515f966 to
16d27ea
Compare
|
Code and description are updated with to reflect |
16d27ea to
a67fadb
Compare
Adds an endpoint to the Google Reader integration to serve feed icon URLs.
a67fadb to
a3148db
Compare
Adds an endpoint to the Google Reader integration to serve feed icon URLs.
The
/icons/{externalIconID}route is an unauthorized endpoint. This is consistent with other feed readers like FreshRSS (icon source code) which uses crc32 to generate icon endpoints.The icon endpoint is made public for consistency with the Google Reader API, and the icon is obfuscated using a randomly generated hex string value
The subscription output looks something like this:
{ "subscriptions": [ { "id": "feed/2", "title": "Miniflux", "categories": [ { "id": "user/1/label/All", "label": "All", "type": "folder" } ], "url": "https://miniflux.app/feed.xml", "htmlUrl": "https://miniflux.app/", // New! "iconUrl": "http://localhost/reader/api/0/icons/e3481406d20b3982b48f3aa857c518bac7dc58da" } ]Have you followed these guidelines?