Coder Social home page Coder Social logo

faye-authentication's Introduction

Faye::Authentication Build Status Code Climate

Authentification implementation for faye

Principle

This project implements (channel,client_id) authentication on channel subscription and publication and delegate it to an external HTTP endpoint through JWT tupple signature based on a shared secret key between Faye server and the endpoint.

On channel subscription the JS client performs an Ajax Call to an HTTP endpoint to be granted a signature that will be provided to Faye Server to connect and publish to channel. The authentication of the endpoint itself is up to you but in the general case this will be a session authenticated resource of your app and you will decide to provide the signature or not depending on your own business logic.

This signature is required for each channel and client id tupple and relies on JWT for security. The Faye server will verify the (channel,client_id) tupple signature and reject the message if the signature is incorrect or not present.

If the browser needs multiple signatures (for multiple channels), they'll automatically be batched together into one signature HTTP request to your server.

Current support

Currently Implemented :

  • Javascript Client Extention (JQuery needed)
  • Ruby Faye Server Extension
  • Ruby Faye Client Extension
  • Ruby utils to signing messages in your webapp
  • Want another one ? Pull requests are welcome.

Installation

Add this line to your application's Gemfile:

gem 'faye-authentication'

And then execute:

$ bundle

Or install it yourself as:

$ gem install faye-authentication

Usage

Channels requiring authentication

All channels require authentication by default, however, it is possible to provide a lambda to the faye extensions to let them know which channels are public.

Authentication endpoint requirements

The endpoint will receive a POST request with one or more channels, and shall return a JSON document with the signatures.

The parameters sent to the endpoint are the following :

{
    "messages": {
      "0": {
        "channel": "/foo",
        "clientId": "123abc"
      },
      "1": {
        "channel": "/bar",
        "clientId": "123abc"
      }
    }
}

If the endpoint returns an error, the messages won't be signed and the server will reject them.

You can use Faye::Authentication.sign to generate the signature from the message and a private key.

Example (For a Rails application)

def auth
  response = params[:messages].values.map do |message|
    if current_user.can?(:read, message[:channel])
      message.merge(signature: Faye::Authentication.sign(message, FAYE_CONFIG['secret']))
    else
      message.merge(error: 'Forbidden')
    end
  end
  render json: {signatures: response}
end

A Ruby HTTP Client is also available for publishing messages to your faye server without the hassle of using EventMachine :

Faye::Authentication::HTTPClient.publish('http://localhost:9290/faye', '/channel', 'data', 'your private key')

Javascript client extension

Add the extension to your faye client :

var client = new Faye.Client('http://my.server/faye');
client.addExtension(new FayeAuthentication(client));

By default, when sending a subscribe request or publishing a message, the extension will issue an AJAX request to /faye/auth

If you wish to change the endpoint, you can supply it as the second argument of the extension constructor, the first one being the client :

client.addExtension(new FayeAuthentication(client, '/my_custom_auth_endpoint'));

If you want to specify some channels for which you don't want the extension to call your endpoint, you can pass an options object with a whitelist key mapping to a function :

function channelWhitelist(channel) {
  // Allow channels beginning with /public but disallow globbing
  return (channel.lastIndexOf('/public/', 0) === 0 && channel.indexOf('*') == -1);
}

client.addExtension(new FayeAuthentication(client, '/faye/auth', {whitelist: channelWhitelist}));

Faye-authentication will retry each signatures request once if the first attempt failed or returned an invalid signature. The default retry delay is 1000 ms, so 1 second. It can be configured :

client.addExtension(new FayeAuthentication(client, '/faye/auth', {retry_delay: 200})); // 200 ms retry delay

Ruby Faye server extension

Instanciate the extension with your secret key and add it to the server :

server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 15)
server.add_extension Faye::Authentication::ServerExtension.new('your shared secret key')

Faye::Authentication::ServerExtension expect that :

  • a signature is present in the message for publish/subscribe request
  • this signature is a valid JWT token
  • the JWT payload contains "channel", "clientId" and a expiration timestamp "exp" that is not in the past.

Otherwise Faye Server will refuse the message.

If you want to specify some channels for which you don't want the extension require authentication, you can pass an options hash with a whitelist key mapping to a lambda :

channel_whitelist = lambda do |channel|
  # Allow channels beginning with /public but disallow globbing
  channel.start_with?('/public/') and not channel.include?('*')
end

server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 15)
server.add_extension Faye::Authentication::ServerExtension.new('your shared secret key', {whitelist: channel_whitelist})

Ruby Faye client extension

This extension allows the ruby Faye::Client to auto-sign its messages before sending them to the server.

client = Faye::Client.new('http://localhost:9292/faye')
client.add_extension Faye::Authentication::ClientExtension.new('your shared secret key')

Contributing

  1. Fork it ( https://github.com/dimelo/faye-authentication/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

faye-authentication's People

Contributors

alexistoulotte avatar branch14 avatar intrepidd avatar jarthod avatar nel avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.