Ruby SDK for Userbin

Build Status Gem Version Dependency Status

Userbin provides an additional security layer to your application by adding user activity monitoring, real-time threat protection and two-factor authentication in a white-label package. Your users do not need to be signed up or registered for Userbin before using the service and there's no need for them to download any proprietary apps. Also, Userbin requires no modification of your current database schema as it uses your local user IDs.

Using Devise?

If you're using Devise for authentication, check out the Userbin extension for Devise for an even easier integration.

Getting started

Add the userbin gem to your Gemfile

gem "userbin"

Install the gem

bundle install

Load and configure the library with your Userbin API secret in an initializer or similar.

require 'userbin'
Userbin.api_secret = "YOUR_API_SECRET"

The basics

First you'll need to initialize a Userbin client for every incoming HTTP request and preferrably add it to the environment so that it's accessible during the request lifetime.

env['userbin'] = Userbin::Client.new(request)

At any time, a call to Userbin might result in an exception, maybe because the user has been logged out. You should catch these errors in one place and take action. Just catch and display all Userbin errors for now.

class ApplicationController < ActionController::Base
  rescue_from Userbin::Error do |e|
    redirect_to root_url, alert: e.message
  end
end

Tracking user sessions

You should call login as soon as the user has logged in to your application. Pass a unique user identifier, and an optional hash of user properties. This starts the Userbin session.

def 
  env['userbin'].(current_user.id, email: current_user.email)
end

And call logout just after the user has logged out from your application. This ends the Userbin session.

def after_logout_hook
  env['userbin'].logout
end

The session created by login expires typically every 5 minutes and needs to be refreshed with new metadata. This is done by calling authorize. Makes sure that the session hasn't been revoked or locked.

before_filter do
  env['userbin'].authorize
end

Verify that it works: Log in to your Ruby application and watch a user appear in the Userbin dashboard.

Configuring two-factor authentication

Pairing

Google Authenticator

Create a new Authenticator pairing to get hold of the QR code image to show to the user.

authenticator = env['userbin'].pairings.create(type: 'authenticator')

puts authenticator.qr_url # => "http://..."

Catch the code from the user to pair the Authenticator app.

authenticator = env['userbin'].pairings.build(id: params[:pairing_id])

begin
  authenticator.verify(response: params[:code])
rescue
  flash.notice = 'Wrong code, try again'
end

YubiKey

YubiKeys are immediately verified for two-factor authentication.

begin
  env['userbin'].pairings.create(type: 'yubikey', otp: code)
rescue
  flash.notice = 'Wrong code, try again'
end

SMS

Create a new phone number pairing which will send out a verification SMS.

phone_number = env['userbin'].pairings.create(
  type: 'phone_number', number: '+1739855455')

Catch the code from the user to pair the phone number.

phone_number = env['userbin'].pairings.build(id: params[:pairing_id])

begin
  phone_number.verify(response: params[:code])
rescue
  flash.notice = 'Wrong code, try again'
end

Usage

1. Protect routes

If the user has enabled two-factor authentication, two_factor_authenticate! will return the second factor that is used to authenticate. If SMS is used, this call will also send out an SMS to the user's registered phone number.

class UsersController < ApplicationController
  before_filter :authenticate_with_userbin!

  # Your controller code here

  private
  def authenticate_with_userbin!
    begin
      # Checks if two-factor authentication is needed. Returns nil if not.
      factor = env['userbin'].two_factor_authenticate!

      # Show form and message specific to the current factor
      case factor
      when :authenticator
        redirect_to '/verify/authenticator'
      when :sms
        redirect_to '/verify/sms'
      end
    rescue Userbin::Error
      # logged out from Userbin; clear your current_user and logout
    end
  end
end

2. Show the two-factor authentication form to the user

<p>
  Open the two-factor authentication app on your device to view your
  authentication code and verify your identity.
</p>
<form action="/users/handle_two_factor_response" method="post">
  <label for="code">Authentication code</label>
  <input id="code" name="code" type="text" />
  <input type="submit" value="Verify code" />
</form>

3. Verify the code from the user

The user enters the authentication code in the form and posts it to your handler.

def handle_two_factor_response
  # Get the authentication code from the form
  authentication_code = params[:code]

  begin
    env['userbin'].two_factor_verify(authentication_code)
  rescue Userbin::UserUnauthorizedError
    # invalid code, show the form again
  rescue Userbin::ForbiddenError
    # no tries remaining, log out
  rescue Userbin::Error
    # logged out from Userbin; clear your current_user and logout
  end

  # We made it through two-factor authentication!
end