Open decentral1se opened 3 months ago
Another alternative: Logged-in users can visit a route to generate their own private RSS feed.
The randomly generated feed url is stored in the database and related to the user who generated it, acting as an access token for the private rss feed. When a request comes in for the route responsible for handling private rss feeds, the database checks "do i have it in my database?" if yes, then the result is returned as an rss feed with all posts included. If no, then pursue the same behaviour as with requests that have been throttled for being too eager.
What this enables: when a user is removed, their read access to the private feed can also be removed by removing the row containing their generated route.
This begs the question of where to present the route though, and I'm starting to think there are enough of these little pieces now to introduce a /profile
route that gathers functionality for:
xx
most recent threads you have participated in, linking to your latest post in each threadSounds legit! Actually this was also a thing discussed in the PMC chat with a tale about how some Wordpress (plugin?) which implements private feeds with cryptic URLs.
If you have spoons to lay out a little game plan I can follow again, I'm all for taking a stab at this. At least the feed part, if that can go first? Or I tag in after you lay some groundwork? I'm easy.
Or even simpler: same idea but you only have to visit the regular rss route while logged in & it will redirect you to yr private route? Not yet sure which is soundest :)
edit: demangled my email response lmao
Mullin' it over π€
Also, interesting: https://daringfireball.net/2005/02/feed_authentication
If you have spoons to lay out a little game plan I can follow again, I'm all for taking a stab at this. At least the feed part, if that can go first? Or I tag in after you lay some groundwork? I'm easy.
definitely! i'll have it done before the weekend has come and gone again π agree that the feed part can go first! i can try to sort out the profile bits & bobs afterwards :]
Also, interesting: https://daringfireball.net/2005/02/feed_authentication
ty! good note about the basic auth scheme, as the author of a very simple rss reader i was biased against it due to my program not having any modals to prompt users for auth details X)
This is very exciting! (greetings from pmc chat)
Regarding http basic auth vs no auth. I've been trying to think about what could be the pros and cons and there is not a clear winner. Ultimately it boils down to trusting (or not) the software where the URL will be landing (from casually sharing a private feed URL without auth, to using a URL with username:password on local or remote RSS client).
Even if it feels a bit less elegant, I am tempted to lean towards adding http basic auth as the better way, simply because, ultimately, if this concerns private parts of a forum, I suppose there must be valid reasons for these parts of the forum to remain as private as possible?
@320x200 heyo! good points. ideally i'd want the basic auth to be self-contained within cerca so that the cerca binary is all you need. luckily i've already played around with basic auth for another project!
https://github.com/cblgh/mould/blob/main/server.go#L53-L81
d1: dump still to come, but i think we could do what i was thinking originally but in a basic auth fashion?
instead of passing the randomly generated token as part of the url path, we could instead interpret the token as the password portion of the basic auth. to make things easy for people to copy, we can output the link to the generated private rss feed as
http[s]://rss:<generated-token>@<forum-domain>/rss`
i.e. rss
is the username, and the generated token is the password, and we keep the rss route unchanged and amend its routine to check for basic auth information Γ la the linked-in snippet above. that way, if the auth checks out, we flip the switch on which threads to list in the feed i.e. listing all threads, and not only public threads. and if it doesn't check out then we just return the public-only rss?
note for pmc: basic auth details are sent unencrypted (base64 lol), so if you don't force https (which i understand some permacomputing projects shy away from) you'll run into the same concern as before
note for pmc: basic auth details are sent unencrypted (base64 lol), so if you don't force https (which i understand some permacomputing projects shy away from) you'll run into the same concern as before
Thanks for thinking ahead! True, we have some concerns regarding defaulting everything to https. With that said, internet is scary place, so we will probably do the same as for the wiki, namely leave the choice to the visitor whether they want to browse as http or https, and only enforce https (via a simple Nginx redirect) for things that require authentication.
@decentral1se the promised dump, with a late sunday evening twist! tbf i think the easiest thing to do would be to just use basic auth for the actual username and password of the user? i don't know how sound it is though. if we don't go that route, below is an outline for how to generate a private rss feed that can be accessed by username and an access token using basic auth. it is functionally similar to username & passwords except only grants access to the private rss feed
but to be honest, i really haven't landed on whether the below approach is better than just letting users send their full creds to the server via basic auth. full creds could leak depending on what the rss software looks like, whereas the access token only gives partial access (a list of all thread names). yet there's a lot of code duplication below and a slight hacky vibe i can't quite shake. open to iterating & ideating if you concur on the slightly off-vibe!
crypto/crypto.go
: you will want to use this function to generate the access token crypto.GeneratePassword()
database/database.go
:db.createTables()
: create a new database table by adding the following element to createTable()
's internal slice:
/* this is currently only used for generating a personal rss feed that also includes private threads */
`CREATE TABLE IF NOT EXISTS access_token (
id INTEGER PRIMARY KEY AUTOINCREMENT,
accessid INTEGER NOT NULL,
tokenhash TEXT NOT NULL,
FOREIGN KEY (accessid) REFERENCES users(id)
);`
create a new function to retrieve the hash of the access token for a given username func (d DB) GetTokenHash(username string) (string, error)
db.GetPasswordHash
) except with the following sql statementβwhich i haven't tried! you might need to tweak / confirm the inner join: stmt := `SELECT a.tokenhash FROM
access_token a
INNER JOIN users u
ON a.accessid = u.id
where u.name = ?`
ResetPassword()
and inline the call to db.UpdateUserPasswordHash()
, changing the relevant places to operate on table access_token
insteadserver/server.go
:GeneratePrivateRSSFeedRoute()
only accessible by logged in users which generates an access token for the logged in user and returns the string https://<username>:<accessToken>@<forum-domain>
as the data for an instance of GenericMessageData
(search for GenericMessageData to see how it's used)GenerateRSS()
includePrivateThreads
to instead be one of the function's parameterstype RequestHandler struct
privateRSSFeed
, setting it in both places and in the same way as h.rssFeed
is set except using the new bool parameter for GenerateRSS()
(i.e. includePrivateThreads = true
)RSSRoute()
h.rssFeed
as normalGetTokenHash(credentialUsername)
which gets the related accessToken for that username if it exists
server.LoginRoute()
and the use of crypto.ValidatePasswordHash
for how to compare the received credential against the retrieved hash of the access tokenh.privateRSSFeed
@cblgh nice, tysm! I think this looks fine personally. Given that we don't really know how good RSS clients will take care of creds, it seems good to separate this from the default user password? I have a pretty large stack of TODOs atm but hoping to get to this from next week. Lemme know if you settle on this design or decide to re-work it π
@decentral1se great! i'll take the extra moments to really mull it over :]
Will be AFK for until end of September so more time to mull over π Can dive into this in October unless anyone gets there before me βοΈ The current proposal still reads well imho.
cheers! the mulling did prove useful and, in the end, i found myself willing to accept the approach i suggested above. fewer unexpected issues that will be run into, feels like
fwiw bit of a busy period right now too so let me know if things should be prioritized or not (for example). otherwise i see myself looping back to things in october when you have a bit more time as well π
See https://github.com/cblgh/cerca/issues/70#issuecomment-2477374636
To complicate matters, we are now using Nginx HTTP basic auth for privacy π
So, the https://USERNAME:PASSWORD@<CERCA-URL>
trick is already being used to bypass the Nginx auth and not a possible private thread token auth π
I know we're still in the formation stages of this but do we see any way to "toggle" this functionality? I am still prepared to carry out the implementation, if so.
So, people can make use of this "token" feed auth (built-in) OR private feed posts are included in the main feed and "external" auth is used.
It seems like a config option could be used.
[rss]
# default is token
# 'external' means you bring your own auth
private = "token" # OR "external"
To complicate matters, we are now using Nginx HTTP basic auth for privacy π
super curious to hear the rationale of this / how this came about!
So, the https://USERNAME:PASSWORD@
trick is already being used to bypass the Nginx auth and not a possible private thread token auth π
yeh, in my last post i came to terms with moving away from that anway. it would have unanticipated consequences for users that forget their password and have it changed; they would discover later on that their rss feed wasn't loading anymore and not really know why.
So, people can make use of this "token" feed auth (built-in) OR private feed posts are included in the main feed and "external" auth is used.
ah interesting, so let me phrase how i read your suggestion (based on PMC's developing needs):
add a configurable toggle to include private posts in the forum's single rss feed. is that right?
Yes, you got it!
But now actually reflecting on this, I think maybe we should put my latest request to the side. Things are moving a lot and we're experimenting... I think I should try to open less "fresh" requests π My apologies.
In one sense, this is "solved" for us because we're just blocking entry completely via HTTP basic auth and only using public threads for RSS updates. That is also "RSS updates for private threads" π
no worries! in my case i'm always happy to jam and think things through with ya π€
Following https://github.com/cblgh/cerca/pull/66.
We now know that private threads are just excluded from the RSS feed. However, this potentially most juicy and interesting aspect of the forum deserves some RSS love! How can we do this while maintaining privacy?
One idea: separate rss feed with private updates which is only enabled via some config knob. This feed must then be protected by additional http basic auth. This could be implemented by
cerca
itself but probably most are proxying and$web_server
can handle it?The motivation is to keep forum users up to date on both public and private discussions via RSS.