Skip to content
Seamless JWT authentication for Rails API
Ruby HTML CSS JavaScript
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
app Rescue specific exceptions in Authenticable (#133) Mar 15, 2017
bin replace remaining references to deprecated gem name (simsim) Jul 14, 2015
config rename gem from simsim (already used) to knock Jul 14, 2015
gemfiles Update tests & CI configuration Sep 21, 2016
lib Change loading (#243) Dec 9, 2019
test Bump JWT dependency to 2.2.1 (#242) Sep 15, 2019
.travis.yml Version 2 (#111) Oct 23, 2016 Check token presense before trying to look up entity (#143) Feb 11, 2017 [v1.5] Multiple entities authentication (#72) May 29, 2016
Gemfile Remove test reporter Nov 15, 2016
MIT-LICENSE - rails plugin new simsim --mountable Jul 13, 2015 Update (fix Wiki link) (#180) Dec 11, 2019 Add Dec 5, 2019
Rakefile Update tests & CI configuration Sep 21, 2016
knock.gemspec Bump JWT dependency to 2.2.1 (#242) Sep 15, 2019


Gem Version Build Status Code Climate

Seamless JWT authentication for Rails API


Knock is an authentication solution for Rails API-only application based on JSON Web Tokens.

Why should I use this?

  • It's lightweight.
  • It's tailored for Rails API-only application.
  • It's stateless.
  • It works out of the box with Auth0.

Is this being maintained?

Yes No Yes!

Currently being maintained with the help of @andrerpbts ❤️

Slowly moving through the backlog of issues & PRs and starting to build a roadmap for the next version.

Getting Started


Add this line to your application's Gemfile:

gem 'knock'

Then execute:

$ bundle install

Finally, run the install generator:

$ rails generate knock:install

It will create the following initializer config/initializers/knock.rb. This file contains all of the existing configuration options.

If you don't use an external authentication solution like Auth0, you also need to provide a way for users to sign in:

$ rails generate knock:token_controller user

This will generate the controller user_token_controller.rb and add the required route to your config/routes.rb file. You can also provide another entity instead of user. E.g. admin


Knock makes one assumption about your user model:

It must have an authenticate method, similar to the one added by has_secure_password.

class User < ActiveRecord::Base

Using has_secure_password is recommended, but you don't have to as long as your user model implements an authenticate instance method with the same behavior.


Include the Knock::Authenticable module in your ApplicationController

class ApplicationController < ActionController::API
  include Knock::Authenticable

You can now protect your resources by calling authenticate_user as a before_action inside your controllers:

class SecuredController < ApplicationController
  before_action :authenticate_user

  def index
    # etc...

  # etc...

You can access the current user in your controller with current_user.

If no valid token is passed with the request, Knock will respond with:

head :unauthorized

You can modify this behaviour by overriding unauthorized_entity in your controller.

You also have access directly to current_user which will try to authenticate or return nil:

def index
  if current_user
    # do something
    # do something else

Note: the authenticate_user method uses the current_user method. Overwriting current_user may cause unexpected behaviour.

You can do the exact same thing for any entity. E.g. for Admin, use authenticate_admin and current_admin instead.

If you're using a namespaced model, Knock won't be able to infer it automatically from the method name. Instead you can use authenticate_for directly like this:

class ApplicationController < ActionController::Base
  include Knock::Authenticable


  def authenticate_v1_user
    authenticate_for V1::User
class SecuredController < ApplicationController
  before_action :authenticate_v1_user

Then you get the current user by calling current_v1_user instead of current_user.


Via the entity model

The entity model (e.g. User) can implement specific methods to provide customization over different parts of the authentication process.

  • Find the entity when creating the token (when signing in)

By default, Knock tries to find the entity by email. If you want to modify this behaviour, implement within your entity model a class method from_token_request that takes the request in argument.


class User < ActiveRecord::Base
  def self.from_token_request request
    # Returns a valid user, `nil` or raise `Knock.not_found_exception_class_name`
    # e.g.
    #   email = request.params["auth"] && request.params["auth"]["email"]
    #   self.find_by email: email
  • Find the authenticated entity from the token payload (when authenticating a request)

By default, Knock assumes the payload as a subject (sub) claim containing the entity's id and calls find on the model. If you want to modify this behaviour, implement within your entity model a class method from_token_payload that takes the payload in argument.


class User < ActiveRecord::Base
  def self.from_token_payload payload
    # Returns a valid user, `nil` or raise
    # e.g.
    #   self.find payload["sub"]
  • Modify the token payload

By default the token payload contains the entity's id inside the subject (sub) claim. If you want to modify this behaviour, implement within your entity model an instance method to_token_payload that returns a hash representing the payload.


class User < ActiveRecord::Base
  def to_token_payload
    # Returns the payload as a hash

Via the initializer

The initializer config/initializers/knock.rb is generated when rails g knock:install is executed. Each configuration variable is documented with comments in the initializer itself.

Authenticating from a web or mobile application

Example request to get a token from your API:

POST /user_token
{"auth": {"email": "", "password": "secret"}}

Example response from the API:

201 Created
{"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"}

To make an authenticated request to your API, you need to pass the token via the request header:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
GET /my_resources

Knock responds with a 404 Not Found when the user cannot be found or the password is invalid. This is a security best practice to avoid giving away information about the existence or not of a particular user.

NB: HTTPS should always be enabled when sending a password or token in your request.

Authenticated tests

To authenticate within your tests:

  1. Create a valid token
  2. Pass it in your request


class SecuredResourcesControllerTest < ActionDispatch::IntegrationTest
  def authenticated_header
    token = { sub: users(:one).id }).token

      'Authorization': "Bearer #{token}"

  it 'responds successfully' do
    get secured_resources_url, headers: authenticated_header

    assert_response :success

Without ActiveRecord

If no ActiveRecord is used, then you will need to specify what Exception will be used when the user is not found with the given credentials.

Knock.setup do |config|

  # Exception Class
  # ---------------
  # Configure the Exception to be used (raised and rescued) for User Not Found.
  # note: change this if ActiveRecord is not being used.
  # Default:
  config.not_found_exception_class_name = 'MyCustomException'


The JWT spec supports different kind of cryptographic signing algorithms. You can set token_signature_algorithm to use the one you want in the initializer or do nothing and use the default one (HS256).

You can specify any of the algorithms supported by the jwt gem.

If the algorithm you use requires a public key, you also need to set token_public_key in the initializer.


To enable cross-origin resource sharing, check out the rack-cors gem.

Related links


  1. Fork it ( )
  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



You can’t perform that action at this time.