8 ms·
Ask HN: How can self hosted apps(browser) converse with no central medium?
I'm currently working on some open net tools. One last piece of the puzzle for me to bring my proof of concepts to life is to get social network apps hosted across multiple domains, to talk to each other.
The scenario is this:
Person A and Person B host their own versions of an open source version of twitter on persona.com and personb.com respectively. Each person is currently logged into their own app and are happily "tweeting". Person A discovers person B's site and sees a tweet they'd like to reshare. Upon clicking reshare, Person A's app should make a request to Person B's app saying "I'm resharing". Person B's app would respond saying "ok. here's the tweet you are resharing along with other meta info. I just increased my reshare count to 1". Obviously this would happen over an open standard API.
The kicker here though is, when person A clicks reshare on person B's site, how does the browser know that persona.com should initiate a request? How does it get the token from person A (so that no one can manually craft their own requests to get person A to reshare) and say "fine, it's person A who wants to do this reshare"?
Right now I'm stuck at the point where it feels like some central medium has to be watching over both sites so the intermediate request would go to central server saying "hey, this token (no idea who it is) just said it wants to reshare person B's tweet". The central server would match token to person A, and say "hey persona.com, you need to do a reshare on this tweet" from which point all would function as normal.
I desperately want to remove the central server but current protocols just don't seem to allow for it. Funnily enough, this would be simple on a mobile/desktop app. But on a browser app I'm completely stuck. Once person A leaves persona.com, the browser has no way of knowing that it should contact persona.com with a token when reshare is clicked.
Is a central server really the only way to go about this?
- nstart 11y agoDue to the 2000 character limit I couldn't add the following: I'm sorry if this comes across as a question that belongs on Stack Exchange. It's a genuine problem that I've been putting off for the last two years, and I finally need to address it. IRC's and other resources have all eventually pointed me in the direction of central servers. I even tried using custom url prefixes like "reshare://" but the experience is terrible since any site can attempt to set the protocol handler for reshare://. Imagine browsing to a random site (like a torrent seeder) that tries to hijack the reshare:// protocol. So currently stuck. Would appreciate any feedback and thoughts on this. Thanks :)
- logn 11y agoI don't think you should be so quick to dismiss custom protocol handlers. To me that's the correct way to do this. Browsers are responsible for not letting handlers be hijacked. It's already used widely for mailto links. Firefox: https://developer.mozilla.org/en-US/docs/Web-based_protocol_handlers https://developer.mozilla.org/en-US/docs/Web-based_protocol_... ; Chrome (needs web+ prefix): https://developers.google.com/web/updates/2011/06/Registering-a-custom-protocol-handler?hl=en https://developers.google.com/web/updates/2011/06/Registerin... There is cross-domain local storage but it involves a central server and iframes, https://github.com/zendesk/cross-storage https://github.com/zendesk/cross-storage
- nstart 11y agothank you! This definitely seems to open up a path that I can look into. As for custom protocol handlers, their experience is pretty messy. But well, try and use what you've got eh.
- sarahj 11y agoA few ideas from a quick brainstorm, none of them are perfect, but neither is the centralized server solution: 1. Bookmarklet - In a similar vein to the way some password managers work you could construct a bookmarklet that the user can click on to make a site do the right thing - there are some security configurations depending on your threat model - however this does require user interaction. 2. Browser plugin - like #1 but obviously with the pain of writing and maintaining a browser plugin. 3. Bake the site determination into the flow - so instead of a 1-click retweet it becomes a 2-click retweet with the second step requiring the user to provide the site where they want to retweet - again some security implications and breaks the regular flow (although you could get around this by doing it once and storing the value in a cookie) 4. Have a local app listening on a specified port (so retweets get POSTed to 127.0.0.1:7000 for example) and then from there onwards - requires extra setup, makes the system less portable (can't just throw it on a hosted server). Like #2 but more annoying.
- nstart 11y agoNumber 3 is pretty good honestly. It might be the best option in fact.
- cairo140 11y agoCan you just have person A supply to personb.com the path to person A's sharing service (in this case persona.com) and craft share links to person A's sharing service pointing to the content from personb.com you want to share? Let's say: Share endpoint /share?content=URL Content endpoint /content/ID If personb.com knows that the client shares from persona.com/share, it can craft its share links as (excuse the escaping) <a href="https://persona.com/share?content=http://personb.com/content/5</a> When person A follows the link, they get sent to persona.com, authenticated using their cookie, and then the persona.com web service follows the content URL to fetch the content to share. This seems to address your core use case as well as your stated kicker (you can't craft a request to get person A to reshare something they don't want to since persona.com/share can auth person A and confirm the share). This is all essential how Facebook, G+, Twitter sharing all work, except you don't pass to your content site the share endpoint because it uses canonical endpoints built in.
- nstart 11y agoThis would be the ideal workflow because it's non platform dependent (works on desktop and mobile browsers with no additional steps). The question is, how does the browser tell personb.com that the reshare point for the current visitor (person A) is persona.com. Struggled with this since there doesn't seem to be a way for the browser to set a value that's writable by one site but readable by any site
- lucaspiller 11y agoI don't think you can make something like this fully distributed with current web technologies, but one solution would be to use a centralised domain for identification. When Person A signs up / logs in their instance includes an iframe at personident.com which sets a cookie saying their instance is persona.com. When they visit Person B's site the include an iframe for the share endpoint at personident.com. That knows about persona.com, so displays a button to share to their instance. Iframes may sound nasty but this is how all the social sharing buttons work at the moment. I think the code on personident.com could just be JavaScript, so hosting would be easy.
- bgdam 11y agoMake persona.com an oAuth provider. Force person a to authenticate with persona.com when they click the reshare button. Once authentication is done, personb.com knows that it has to talk to persona.com. Then call the reshare API on persona.com. This will be a multistep process for the first reshare, but once person a is logged into persona.com and has granted access to personb.com then should be a seamless single click experience. This provides the added benefit that only person a can reshar on persona.com.
- nstart 11y agoI was thinking of this. It's not a great experience, but it might be the only pure browser based options that will work. Along those lines I thought: Person A clicks reshare. Gets asked for url. Person A types in persona.com. Immediately a window pops up which is persona.com/reshare?s=personb&id=4 or something along those lines. This is similar to what happens if you click retweet or fav on an embedded tweet right now. I'm actually ok with this workflow even if it's clunky (you have to click reshare twice to do a reshare). I just wish there was a better way to tell personb.com to automatically recognise that persona.com is associated with resharing.
- warcode 11y agoMake the usernames "username@domain.tld". If the user is already logged in the button will act normally. If its not you simply ask them to log in. If they use username@persona.com on personb.com, handle that in the login code and start the regular OpenID flow with persona.com to authenticate. personb.com is now allowed, on behalf of the user, to reshare this content on persona.com, and sends the data directly to an endpoint there.
- peterpink0 11y agoI prefer a Human at the other end
- javajosh 11y agoWell, in a distributed twitter everyone is primarily writing to their own server. "Retweets" are just a different kind of content. Notification of the originating server that you've found something interesting should be an optional nicety, not a critical feature. Chances are most sites won't support that feature anyway (to easy to abuse for spam).
- skstronghold 11y agoYou need to maintain state related to which is user's own version of website and which is not. This state needs to be accessible to all versions of your apps. As far as my knowledge goes, it is not possible without a central medium. You can either maintain it in a remote server or in a master_domain cookie, to which all apps can redirect, to read current state(similar to SSO). The second approach is not that clean and you would still need a central server, I would prefer first approach only. Sharing states/cookies across domains is not supported by browsers due to security concerns. So doing it completely in browser is not possible at moment.
- zizee 11y agoIt sounds like you are implementing a distributed social network. https://en.wikipedia.org/wiki/Distributed_social_network https://en.wikipedia.org/wiki/Distributed_social_network There are quite a number of open source projects trying to solve similar sounding problems. Perhaps you could look at these projects for inspiration? https://en.wikipedia.org/wiki/Comparison_of_software_and_protocols_for_distributed_social_networking https://en.wikipedia.org/wiki/Comparison_of_software_and_pro... Many of the projects are purely "protocol" projects, which you may be able to leverage to achieve what you want without having to implement it yourself.
- TerryADavis 11y agohttp://hackaday.com/2014/12/19/nist-randomness-beacon/ http://hackaday.com/2014/12/19/nist-randomness-beacon/ Towards the Perfect Coin Flip: The NIST Randomness Beacon 72 Comments by: Elliot Williams December 19, 2014 Since early evening on September 5th, 2013 the US National Institute of Standards and Technology (NIST) has been publishing a 512-bit, full-entropy random number every minute of every day. What’s more, each number is cryptographically signed so that you can easily verify that it was generated by the NIST. A date stamp is included in the process, so that you can tell when the random values were created. And finally, all of the values are linked to the previous value in a chain so that you can detect if any of the past numbers in the series have been altered after the next number is published. This is quite an extensive list of features for a list of random values, and we’ll get into the rationale, methods, and uses behind this scheme in the next section, so stick around. But first, before those of you who’ve got crypto on the brain start thinking crazy thoughts, note that the NIST has a banner stating the obvious in all caps: “WARNING: DO NOT USE BEACON GENERATED VALUES AS SECRET CRYPTOGRAPHIC KEYS.” Why not? Cryptographically speaking, they’re phenomenal random numbers; they’re just not secret at all! In contrast, they’re publicly available to everyone and archived for all time. The aim of the Randomness Beacon is to provide a random number standard, not to generate secrets. This distinction between secrecy and randomness is important in order to realize what the NIST is up to, so put your secrecy on the shelf for now. We’re talking randomness here. The Perfect Coin Flip A random variable, says the statistician, is a function that produces a value that is unknown before a given point in time, but is constant thereafter. This instant when the value is realized is crucial to understanding randomness. It’s the instant that separates the past, a period of time when the outcome has a probability distribution around its possible values, from the present in which the outcome is a simple constant number. Before you roll that twenty-sided die, any number from one to twenty could come up. After the die comes to a stop, it’s absolutely certain that you just rolled a seventeen, and that fact is never going to change. You just rolled a seventeen, and only a seventeen, with certainty and forevermore. The probability distribution has collapsed to a point, which is exactly why we roll dice or flip coins if you think about it. Keep these concepts of uncertainty and timing in your mind as I tell you a brief, entirely fictional, story. My wife and I are going out to a restaurant, but we can’t decide whether to get Italian or Thai. For the past year, we’ve been deciding restaurants with a coin flip, but that hasn’t worked since she got suspicious and discovered that the “random” coin flip isn’t random at all, and that I’d been using a two-headed coin. She’s not going to accept a dice roll either, for the same reason that we don’t play craps together anymore. What we need is a perfect coin flip: some future random event with an outcome that’s currently totally unpredictable, impossible for either of us to influence, but then easily verifiable after the event so there’s no room for argument. Note what’s going on here. If either of us knew what the future random value would be, it wouldn’t be random. But we require something even stronger, that we can’t even make useful predictions about the outcome — that the coin is a fair coin. And since she doesn’t trust me anymore, the only way we’re going to go out to dinner is if neither of us can possibly influence the future value. Burned by a year of eating Thai food, she’s not going to trust me to read the result out to her either, she’ll need to see the results herself. nist-randomness-beacon-screenshotThis is exactly what is provided by the NIST Randomness Beacon. To pick a restaurant, we agree to look at the NIST’s webpage at 7:00 pm and if the first digit is even, we go Thai. If it’s odd, we go Italian. We both agree that this is fair because the 7:00 pm result isn’t published until 7:00 pm. As late as 6:59 pm, the outcome is entirely unknowable, and after 7:00 pm it’s publicly available to anyone and hashed and signed with the NIST Beacon’s secret key, so it’s easily verifiable. Because the Beacon’s Output Value is the product of a few hashing steps, it’s also almost impossible that I could influence the value ahead of time even if I had an insider at the NIST. Even if I’ve hacked into the NIST’s servers and tried to change that one value, the way that the values are chained will eventually make this tampering obvious. While it’s overkill for picking restaurants, there are a lot of similar agreements that a publicly available source of randomness will facilitate. One similar example from the NIST’s website is that of random inspections. If a saboteur knew ahead of time which box of mangoes was going to be “randomly” inspected, he could fill it with contraband, and the whole shipment would get impounded. Or if a pharmaceutical company knew ahead of time which patients were going to receive the real drug and which the placebo, they could assign healthier patients to the test group. By using a neutral source of randomness, the saboteur is left guessing and the pharma firm can demonstrate that it didn’t cheat on its science. Or the Beacon could be used in an election in a scheme to randomly sample precincts and re-count votes, immune to influence from any political parties. More esoterically, one could use the Randomness Beacon to prove that something is newer than a certain date by including a recent Beacon entry. As of this writing, the values for December 31, 2014 are all still up in the air, so I can’t possibly write one of them down yet. But from Jan 1, 2015 and on, it’s trivial to do so. So if I get a bunch of t-shirts made with the midnight value from December 31, it’s absolutely verifiable that I got them made in the new year. In short, you could use the Beacon as a not-older-than dating scheme. How Does It Work? So to see how the NIST pulls this off, let’s take a quick look behind the curtains at how the Randomness Beacon achieves its goals of providing a random string of bits that’s completely unpredictable, stupendously difficult to influence, and publicly verifiable. See Figure 1 for the overview. It all begins, naturally, with the random number generators. Two independent hardware random number generators provide 512 bits of randomness, and these two values are XOR’ed together to yield the Seed Value. Taken on its own, this is an extremely good 512-bit random number. The Seed Value is then collected together with the rest of the relevant descriptive data: version number, frequency of output, the time stamp, a code for the chaining status, and the value of the previous output. This collection ties the random outcome together with the time that it was created and links this value with the previous one. The collection of data is then hashed with SHA-512 and signed with the Beacon’s private key, yielding the Signature. Given the Beacon’s public key, one can easily verify that the signature corresponds to the relevant data and is signed by the Beacon. You can use the UNIX shell script at the bottom of this article to run a verification for you. Finally, the signature is hashed with SHA-512 again to create the final Output Value. This is the value that you’ll want to use as your random number. It incorporates all the relevant information about this minute’s value because it’s a hash of the signature, which is in turn a hash of the data. All of this hashing preserves the original entropy from the Seed Value but additionally makes the Output Value depend on the Beacon’s secret key and all the relevant background data in a verifiable way. Devil’s Advocacy Now let’s say that you don’t trust the NIST. That’s OK, because by design you don’t need to. What you would care about, for the purpose of deciding on dinner, is that the value isn’t manipulable in a way that could affect whether we go out for Thai or Italian. If someone inside the NIST wants to change the Output Value by picking a particular Seed Value, there are two rounds of SHA-512 hashing standing between the Seed Value and the Output Value even if they know the Beacon’s secret key. SHA-512 is not known to be broken at present, and so even working backwards through one of the SHA-512 stages is essentially impossible; two rounds is impossible squared. Combining NIST with your own hashes (like our One TIme Pad) creates an even more secure system than using a single one. Combining NIST with your own hashes (like our One TIme Pad) creates an even more secure system than using just one source. If you want to make the outcome even more difficult to manipulate, you could use two values from the Beacon and XOR or hash them together to create the final random value. Because the outputs are chained, changing any value in the past introduces a changed Previous Output value which would have to be propagated forward to the current observation. So if you’d like to make your adversary’s work super-duper difficult, combine the Output Values from today at 7:00 pm and yesterday at 7:00 pm. Your adversary will have to work backwards through 2 * 24 * 60 = 2,880 SHA-512 stages to make the chain verify, still assuming that he knows the NIST’s secret key. But suppose SHA-512 were broken and working it backwards were easy instead of being ridiculously difficult. Nothing prevents you from writing your contract to take the Output Value, add one to it, and run this value through a better hash of your choosing. Now the bad actor inside the NIST has to reverse your chosen hash function as well.
- comex 11y agoAFAIK this is the kind of thing Web Intents was meant to facilitate: https://en.wikipedia.org/wiki/Web_Intents https://en.wikipedia.org/wiki/Web_Intents Too bad it seems to be dead.
- nstart 11y agoyep. when I stumbled on this I was all yeyy. Then I saw the status and was all "sigh". That led me to custom URL protocols which turned out to be a deadend
- yoz-y 11y agoIf your network is to be used by technically more savvy people you could use this approach: On personA site there would be a field which accepts a 'reshare' code when the user is logged in. Clicking on the reshare button on personB site would (by default) display a reshare code. This code would contain information such as personB URL, id of the post etc. Pasting the reshare code into personA site would result in a (backend) communication between personA and personB sites to sort stuff out. When using reshare function for the first time on personB site, the site would propose to enter the URL of 'your own' server in order to transform the reshare button functionality. Once personB site knows the url of personA, it would transform the reshare button so it actually constructs an URL in the means of personA/reshare/from/personB/reshare-code. Since the user is presumably logged in (with cookie/local-storage token) to personA, this would redirect him to personA, the backend of personA would eat the reshare-code and could offer a dialog asking for confirmation of a reshare. Once validated it could ping personB site that the resharing was complete.
- Vendan 11y agoIt seems like you are working towards a "everyone put their social stuff on their own site" model, which really lines up with the indiewebcamp ideal. I would recommend looking at https://indiewebcamp.com/webactions https://indiewebcamp.com/webactions, as it's almost exactly what you are looking for, and requires little to no browser support at all, just the ability to register a url as a handler for a protocol. Biggest issue is just getting all the different sites to have support for webactions. The other bit you need is https://indiewebcamp.com/indie-config https://indiewebcamp.com/indie-config