OriginProtocol / origin-js

We've moved to a monorepo: https://github.com/OriginProtocol/origin
MIT License
81 stars 33 forks source link

Implement user identity for Twitter publicly-auditable proof #5

Closed matthewliu closed 6 years ago

tyleryasaka commented 6 years ago

As can be seen in the activity timeline here, I have created a PR that implements some methods for signing and verifying messages.

However, I've run into a roadblock on the Twitter implementation. Twitter's API requires authentication for all requests (even read-only requests for publicly available data). All of their supported authentication methods require some sort of API key (in addition to any client-side keys that are required for permissioned actions such as posting a new tweet), which means a server has to be involved. Currently our origin.js library is purely client-side.

What is our strategy for implementing publicly auditable proofs for Twitter? Should we add a separate open source server library? Or just set up our own server and provide it as a service? Or some other approach maybe?

I'll need some feedback on this before I can continue.

joshfraser commented 6 years ago

Thought we might run into this problem. 3 options. None of them are great.

1) we set up a twitter-proxy that the dapp connects to that uses our keys. it's important that we are merely forward the contents of the tweet versus verifying it server-side to keep things as trustless as possible.

2) we just set up an account and publish our keys to the world. high risk that Twitter won't like it and will deactivate our keys especially if someone else runs across them and starts abusing them. quick and dirty hack to get it working, but probably not a viable long term solution. https://stackoverflow.com/questions/17049821/setting-up-twitter-api-getting-the-last-few-tweets

3) we do a proper oauth handshake to connect each user and then use their personal oauth keys to do the fetching. one challenge would be that you would need to connect your own twitter account before you can fetch and verify other people's accounts.

I think our best option is probably #1. I hate adding centralized servers into the mix, so it's important that we keep it open-source & make it possible for people to swap our the verification server that they want to use. We should generalize this of course, as twitter won't be the only place where we run into this problem.

Anyone else want to weigh in?

joshfraser commented 6 years ago

There's a few places where a centralized server is necessary:

Maybe we combine this all in one place and then you have 1 single setting to choosing your preferred centralized provider. Origin Protocol can be the default of course, but you should be able to swap it out for any other provider you want, including hosting it yourself.

Need a good name for this thing. Ideas?

tyleryasaka commented 6 years ago

Agreed on all points. Hmm, maybe we could call it something like supporting server? (Just throwing an idea out there.)

matthewliu commented 6 years ago

One piece of weirdness.

What happens when a user uses one centralized server and then switches to another centralized server?

Indexing seems fine. The identity stuff should be fine (after it's written to the smart contracts). The notification stuff is potentially weird. Unless the plan is to store some sort of message log on chain. Otherwise how do we show history in the client? Or are notifications ephemeral (seems bad)?

matthewliu commented 6 years ago

Also changing the scope of this to just Twitter to be more specific since we aren't doing other accounts yet.

tyleryasaka commented 6 years ago

@matthewliu I see what you're saying. Off the top of my head, I think the solution would be to either (1) let notifications be ephemeral, or (2) store notifications in IPFS somehow, and then just store the IPFS hash on-chain.

I do think though that we can probably just assume the user will remain on one centralized server for now, as a first iteration, and then worry about edge cases like switching servers later.

joshfraser commented 6 years ago

We don't have a good solution for messaging yet.

Messages can be encrypted and then stored on IPFS with the content-hashes published to a smart contract, but even doing that is expensive as each message could cost ~$1 at todays prices.

We'd like at least the signature of each message to be published to the blockchain so that in case of a conflict, either the buyer or seller can reveal the message thread to an arbitrator and the arbitrator can use the signatures to confirm the legitimacy of the communications.

Either Ethereum solves their scalability challenges or we're going to have to figure out an alternative solution here.

wanderingstan commented 6 years ago

I've been meaning to check out IPFS pubsub: https://github.com/ipfs-shipyard/ipfs-pubsub-room

Could we create a room for the transaction, and encrypt the messages? (Each side encrypts messages with public key of the other side, and perhaps also signs each message.)

Either party can keep a copy of the chat log. And hash of the chat can be included when dispute is opened or transaction is finished.

joshfraser commented 6 years ago

IPFS pubsub could certainly be part of the solution.

What happens when a arbitrator is sent two conflicting chat logs? The benefit of publishing signatures in realtime is that the arbitrator has a way to tell which one is true and which one is fake.

wanderingstan commented 6 years ago

If the messages are signed, there is no way to create a conflicting chat log.

To be thorough: Each new message, along with the entire chat log up to that point (or even just the previous message), is cryptographically signed.

joshfraser commented 6 years ago

You're right. Creating a chain of signed messages would do the trick.

tyleryasaka commented 6 years ago

Update: I now have a PR that implements methods for publicly-auditable twitter proofs. https://github.com/OriginProtocol/platform/pull/44

It allows a centralized server to be specified. I have working code for an example server written in node/express. https://github.com/tyleryasaka/origin-server. I set it up to be modular, so we could easily expand it to perform the other tasks that Josh mentioned.

tyleryasaka commented 6 years ago

Edit: I've looked at keybase now and I see that they have a great example of publicly-auditable proofs. I understand the approach we're going for now and no longer have these concerns.

So, in the call yesterday it was mentioned that we probably prefer to use Twitter's "Tweet Button" to do the thing where a new window is opened with a pre-populated tweet, which the user can then choose to post. As opposed to getting permission to post a tweet, using the rest api and oauth, on the user's behalf.

However, there's an issue with this method. Actually it's something I thought of before and was one reason I opted to implement using the rest api instead of the tweet button. The problem is that we have no way of getting a callback or promise of the tweet after it is sent out. We get an event when the user clicks to open the new window, but after that we lose all ability to know what the user chooses to do. For example the user could send the tweet, or just choose to close the window. Or they could edit the tweet, then send it. Or they could wait a long time before sending the tweet.

We could of course implement some sort of polling and just watch the user's twitter feed and wait for the tweet to come through. But because we won't know what the user chose to do with the Tweet window, it could be tricky to have the UI reflect the current state once the Tweet window is opened. We won't know whether or not the user chose to send the tweet.

Any thoughts? Do we want to hack something together using the tweet button, or do we want to just settle for allowing the bridge server to request read/write access to the user's account? (Here are the docs for application permissions, if anyone is interested. Basically there are 3 levels: (1) read, (2) read/write, (3) read/write/direct-message.)

wanderingstan commented 6 years ago

We've moved on to ERC725 (and @tyleryasaka was able to re-use a lot of his code), so I'm going to call this one closed.