firehoseio / firehose

Build realtime Ruby web applications. Created by the fine folks at Poll Everywhere.
http://firehose.io/
MIT License
727 stars 72 forks source link

Private channels #41

Open nanego opened 10 years ago

nanego commented 10 years ago

Does Firehose currently support private channels? What is the best way to restrict access so that anonymous users cannot read private messages? Thank you!

thoughtless commented 10 years ago

Firehose itself does not include any form of authentication or authorization.

One approach is to use a Rack middleware that handles it. You create your own project, put firehose in your Gemfile. Then in your config.ru you set up your auth middleware.

Another approach is to put Nginx in front of Firehose as a proxy, and use the auth available through Nginx. I know Nginx supports basic auth.

bizmurr commented 9 years ago

@thoughtless when using Nginx basic auth, will the Ruby client allow us to pass in the nginx auth params, or would you have to write your own client? I'm interested in only securing the PUT side so only the application servers can send updates.

thoughtless commented 9 years ago

Based on https://github.com/polleverywhere/firehose/blob/master/lib/firehose/client/producer.rb#L104 I think the existing client will work with basic auth. I haven't tested myself.

bradgessler commented 8 years ago

I'd like to implement a Middleware into Firehose that can deal with these issues. For example, if you wanted to authenticate or authorize a client to access the stream of a resource, Firehose would be able to fire off a HEAD request with a token of some sort on behalf of your client to see if it should authorize access to the channel.

The only thing I don't like about this approach is that we do everything inside of EventMachine. I fear people would develop Middleware that would block the reactor. In this case https://github.com/igrigorik/em-http-request would have to be used to fire off HTTP requests (not the dreaded Net::HTTP).

thoughtless commented 8 years ago

I think I'd rather explore using JSON Web Tokens (JWT). This avoids having Firehose making HTTP requests.

The simplest solution is a shared key. The publisher keeps the private key and Firehose keeps the public key.

When a Firehose connection is established, the initial request for data includes the JWT. If Firehose can verify the signature and that the JWT is valid for the requested resource, things continue as normal. If not, then it returns 401 Unauthorized.

This implementation could have serious performance implications for Long Polling. However, we could potentially use Cookies to skip the JWT verification on each request. WebSockets would only verify the JWT when it first connects.

Since JWTs expire, the client will need a way to ask the publisher for a new JWT so it can retry. Again, we could use cookies that last longer than the JWT to avoid the frequency of this being required.

Finally, if not every resources needs to be protected (and you can't guess ahead of time based on the URL), then a publish request could include a header (or possibly a new field in a structured body) that determines whether or not authentication is required.

bradgessler commented 8 years ago

You'd be able to implement that in Firehose as a Middleware. The idea is to keep Firehose agnostic on authorization/authentication schemes (or whatever) on this front.

thoughtless commented 8 years ago

Yes. Everything I described would be a middleware and operate independently of firehose itself.

bradgessler commented 8 years ago

There's a fork of Firehose with an authentication implementation at https://github.com/shoreside/firehose/commit/8dc43ed985ba20933951eacbc10a00abc18db45e. While its probably too specific to implement in Firehose, it is a good example of how a user has implemented authentication.

thoughtless commented 6 years ago

Private channels can be implemented with a Custom MessageFilter