Token auth for grape apps
Ruby HTML Shell
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.md

GrapeTokenAuth

Gem Version Code Climate GPA Test Coverage Circle CI

GrapeTokenAuth is a token authentication solution for grape. It is compatible with ng-token-auth (for angular) and j-toker (for jQuery), and is meant as a grape (rather than rails) version of devise_token_auth. As such, this project is built entirely upon grape and warden and avoids the need for rails. However, it has built in compatibility for devise if you are looking to mount a grape app within your rails app. Finally, If you are placing a grape app within an existing rails + devise_token_auth app you might be interested in grape_devise_token_auth.

This gem is a port of devise_token-auth written by Lyann Dylan Hurley and the team of contributors. That team does great work and the conceptual section on that gem is highly recommended reading.

Philosophy

This gem aims to maintain a small direct dependency footprint. As such, it currently depends only on grape, warden, mail, and bcrypt. In the future, the hope is to break this gem up into modules so that you can be even more selective on the code and dependencies that are included.

Installation

Add this line to your application's Gemfile:

gem 'grape_token_auth'

And then execute:

$ bundle

Or install it yourself as:

$ gem install grape_token_auth

Quick-Start Setup

This is the minimum setup to get GrapeTokenAuth running. For a more detailed walkthrough, you can refer to this blog post, the demo repo, and the wiki. Setup has 4 parts:

  1. Middleware Setup
  2. Model/ORM setup
  3. Grape Token Auth configuration
  4. Mounting Authentication APIs

###Middleware setup

GrapeTokenAuth requires setting up warden middleware in order to function properly. In a simple rack environment this is usually as easy as adding the following to the config.ru:

# config.ru

require 'warden'
require 'grape_token_auth'

## Setup session middleware (E.g. Rack::Session::Cookie)

GrapeTokenAuth.setup_warden!(self)

run YourGrapeAPI

In rails, you will need to setup warden as so:

# application.rb

config.middleware.insert_after ActionDispatch::Flash, Warden::Manager do |manager|
  manager.failure_app = GrapeTokenAuth::UnauthorizedMiddleware
  manager.default_scope = :user
end

Model/ORM setup

Include the module for your ORM within the model classes. At the moment, only ActiveRecord is supported but other ORMs are planned. Your model must contain a text-type field called tokens.

####ActiveRecord

class User < ActiveRecord::Base
  include GrapeTokenAuth::ActiveRecord::TokenAuth
end

Grape Token Auth Configuration

GTA does not make guesses about what scopes and user classes you are using, you must define them before the Grape API is loaded. In rails this could be in an initializer, for a rack app run the setup before the API class definitions.

To define mappings, the scope is the key of the mapping hash, and the value is the model to which the scope is mapped. For the above user class this would be:

GrapeTokenAuth.setup! do |config|
	config.mappings = { user: User }
	config.secret   = 'THIS MUST BE A LONG HEX STRING'
end

Note on Secret: generate a unique secret using rake secret in a rails app or via these directions.

In addition, if you are using the mail features in grape_token_auth you will want to set the appropriate configuration options. See the mail wiki page for more information.

Mounting authentication APIs

In order to use a given feature of GrapeTokenAuth, the corresponding API must be mounted. This can be accomplished in your grape app by first including the mount helpers:

class TestApp < Grape::API
  format :json

  include GrapeTokenAuth::MountHelpers

  #...
end

Then you can use the individual helpers to mount a given GTA API:

class TestApp < Grape::API
  # ...

  mount_registration(to: '/auth', for: :user)
  mount_sessions(to: '/auth', for: :user)
  mount_token_validation(to: '/auth', for: :user)
  mount_confirmation(to: '/auth', for: :user)

  # ...
end

The first line indicates the GrapeTokenAuth registration API will be mounted to '/auth' relative to the location where the TestApp is mounted. Presuming that TestApp is being run at root, registration endpoints will be at /auth. Also, we are defining the scope that these endpoints pertain to (user). Important the scope must be defined in the configuration step.

A table of the various APIs and their associated helpers follows:

API helper description
Registration mount_registration used to register new 'email' type users
Session mount_sessions used to login 'email' type users
Confirmation mount_confirmation used to confirm 'email' users new emails
TokenValidation mount_token_validation used to tokens for all type users
OmniAuth mount_omniauth used to register/login omniauth users, requires the OmniAuthCallback API
OmniAuthCallback mount_omniauth_callbacks used to register/login omniauth users, requires the OmniAuth API
PasswordReset mount_password_reset used to issue password resets for forgotten passwords

Usage

First, include the TokenAuthentication module in the grape API you want to enforce authentication on.

class TestApp < Grape::API
  # ...

  include GrapeTokenAuth::TokenAuthentication

  # ...
end

Enforcing authentication on an endpoint

In any grape endpoint you can call authenticate_{SCOPE}! to enforce authentication on that endpoint. For instance, the following:

get '/' do
  authenticate_user!
  present Post.all
end

will authenticate against the :user scope when trying to GET the / route.

Enforcing authentication on all endpoints

Alternatively, if you want to protect all of the endpoints in an API, place the authentication call in a before_filter, like so:

class TestApp < Grape::API
  before do
    :authenticate_user!
  end
end

Development

After checking out the repo, run bin/setup to install dependencies. Then, run bin/console for an interactive prompt that will allow you to experiment.

To run tests, you will need postgres to be setup and configured correctly. Run rake db:setup to create the test db and rake db:reset to reset the db.

Contributing

See CONTRIBUTING.md