sandstorm-io / sandstorm

Sandstorm is a self-hostable web productivity suite. It's implemented as a security-hardened web app package manager.
https://sandstorm.io
Other
6.72k stars 705 forks source link

cannot tweet from grains #2925

Open dwrensha opened 7 years ago

dwrensha commented 7 years ago

I had been hoping that the recent powerbox improvements would allow me to write an app that posts tweets through https://api.twitter.com. My working assumption was that Twitter would let me generate a token from its UI and that I would be able to directly use that token in aBasic or Bearer authorization header on a request to the /statuses/update endpoint.

The situation turns out to not be quite so simple. Twitter's "application only" authorization works more or less as I was hoping, but it only allows access to a restricted subset of Twitter's API, and in particular does not allow tweets to be posted.

Twitter's main authorization scheme is more complicated. (See https://dev.twitter.com/oauth/overview/authorizing-requests and https://dev.twitter.com/oauth/overview/single-user.) Based on my current understanding of it, I can roughly imagine two ways that it might work with Sandstorm.

  1. The user generates their own Twitter "application" through https://apps.twitter.com/ and then generates an "access token" through the UI there. When the Sandstorm grain makes a powerbox request for https://api.twitter.com, there is a configuration step where the user enters the "Consumer Key", the "Consumer Secret", the "Access Token", and the "Access Token Secret" from their "application". Sandstorm stores these values (encrypted) and uses them to fill out the Authorization header for each request.

  2. The Sandstorm server itself is a Twitter "application", similar to how it is a Github application when Github Oauth is configured. In fact, we could make Twitter an identity provider. However, this Twitter "application" will need to be allowed to do more than just read profile information -- we want it to be able to post tweets. Once this is configured, the powerbox request flow should consist of a few easy clicks, rather than the cumbersome copy-pasting in approach (1). Moreover, the user does not need to be instructed about how to configure their own Twitter "application". A downside is that this approach will probably require a lot more work on our end, to get all of the Oauth integration working smoothly.

If I end up pushing forward on my Twitterbot Sandstorm app, I think I'll start with trying approach (1).

kentonv commented 7 years ago

The docs you link appear to be OAuth1, which required that the Authorization header contain a signature generated by a convoluted mechanism. Under OAuth2, the Authorization header is just Authorization: Bearer <token>. In the latter case -- assuming Twitter supports OAuth2 -- you should be able to get access to the API through the Powerbox today by punching in https://api.twitter.com#<token> as the custom URL in the powerbox UI. You will need to obtain an access token manually, which usually involves POSTing to some endpoint and providing your client key, client secret, etc.

Of course, we don't really want users to copy/paste, much less manually obtain access tokens; we'd rather provide a nice UI. I think the right answer here is to add Twitter as another authentication provider. The Sandstorm server admin would need to obtain a client key and secret, but individual users would not. We may want to implement the identities/credentials/personas refactor before we add any more identity providers, though...

ocdtrekkie commented 4 years ago

I was reading a bit how the OAuth Powerbox stuff works while reading around #3180 (cc: @zenhack) and it caused me to think a bit about the login providers limitations and how it impacts this. (#3074 also represents a common request for this, going all the way back to #525.)

In my case, I choose not to let Google know much about my Sandstorm server, so I didn't configure Google login. I didn't realize this adds the secondary limitation that apps that want to talk to Google's API also can't. Can I choose to configure an OAuth service and still disallow Sandstorm users for using it for login?

I do not know if anyone in their right mind would want to let people use Facebook login to Sandstorm (same thoughts about Google as far as I'm concerned, but whatever), but people might want a Facebook OAuth configuration so that they can pull data from it. I was thinking about exporting data from Fitbit (before it also becomes Google), but adding a Fitbit login provider to Sandstorm would be kinda silly, in my opinion.

Right now, login providers (and hence OAuth providers) are very much hardcoded into Sandstorm and unable to be added by the server admin, much less the Sandstorm user. And if we want to enable Sandstorm to manage our OAuth flow to various services, we probably need a better story around doing this?

zenhack commented 4 years ago

It does seem reasonable to uncouple login providers from stuff the server can talk to via oauth, and there's no reason we couldn't do that I think. It would somewhat sidestep the issue of just having too many and being overwhelming.

Right now, login providers (and hence OAuth providers) are very much hardcoded into Sandstorm and unable to be added by the server admin, much less the Sandstorm user. And if we want to enable Sandstorm to manage our OAuth flow to various services, we probably need a better story around doing this?

I'm not sure what that story would be; OAuth is obnoxiously not quite standard enough to just be able to plug in an arbitrary provider to an app without any dev work. It's not hard to add one, but I don't know how you'd automate it. Though I agree with the goal...

ocdtrekkie commented 4 years ago

Another concern or two I was thinking about:

ocdtrekkie commented 4 years ago

As for implementation:

zenhack commented 4 years ago

The question about admins possibly being on the hook for ToS violations from users is a good one, we should think about how to deal with that.

I haven't dug into meteor-accounts much at all, so can't comment on that yet.

There is an idea mentioned in the contributing doc about apps being able to provide auth backends:

https://github.com/sandstorm-io/sandstorm/blob/master/CONTRIBUTING.md#new-authentication-mechanisms

...but for that matter, the oauth powerbox requests are just regular powerbox requests that sandstorm itself can also respond do. It is in principle possible to add apps do to extend functionality, though that being a good experience is going to probably depend on other improvements.

kentonv commented 4 years ago

I think it would make sense for admins to be able to enable Google (or whatever) credentials, but refuse to let them be used for login. (Users would only be able to add them as non-login credentials.)

Unfortunately OAuth 2.0 is not quite specific enough that administrators could configure arbitrary login providers. E.g. the URLs of the various endpoints differ from provider to provider, with no real pattern. :( You can look at the various per-provider Meteor packages to see how much customization is needed for each... it's not a ton but it's still painful.

The policy stuff around client keys and ToS violations has always been a shitshow for decentralized applications. E.g. when you ship a client app that embeds its own keys, anyone can pull out those keys and use them for any purpose. The whole system was designed for a world where everything is SaaS. :( But I think in practice the kinds of abuse that providers try to manage by blocking client keys are not likely to come from a Sandstorm app...