Open nanego opened 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.
@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.
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.
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).
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.
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.
Yes. Everything I described would be a middleware and operate independently of firehose itself.
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.
Private channels can be implemented with a Custom MessageFilter
Does Firehose currently support private channels? What is the best way to restrict access so that anonymous users cannot read private messages? Thank you!