knocknock
Seamless multi-model, multi-client JWT authentication for Rails API
Description
Knocknock is an authentication solution for Rails API applications based on JSON Web Tokens.
What are JSON Web Tokens?
Why should I use this?
- It's lightweight.
- It's tailored for Rails API-only application.
- It's stateless.
Is this gem going to be maintained?
Yes. And we will keep improving it.
Getting Started
Requirements
knocknock 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
has_secure_password
end
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.
knocknock can handle multiple user models (eg: User, Admin, etc). For the sake of simplicity, all examples in this README will use the User
model.
Installation
Add this line to your application's Gemfile:
gem 'knocknock'
And then execute:
$ bundle install
Finally, run the install generator:
$ rails generate knocknock:install
This creates three files:
- The knocknock initializer
config/initializers/knocknock.rb
. This file contains all the informations about the existing configuration options. - The AccessToken model.
- The related migration for the AccessToken model.
You also need to provide a way for users to authenticate:
$ rails generate knocknock:token_controller user
This will generate the controller user_token_controller.rb
and add the required
route to your config/routes.rb
file.
Usage
For each model you want to use with knocknock, add the
has_many :access_tokens, as: :authenticatee
association
class User < ApplicationRecord
has_many :access_tokens, as: :authenticatee
...
end
Include the Knocknock::Authenticatable
module in your ApplicationController
class ApplicationController < ActionController::API
include Knocknock::Authenticatable
end
You can now restrict access to your controllers like this:
class SecuredController < ApplicationController
before_action :authenticate_user
def index
# etc...
end
# etc...
end
If your user model is something other than User, replace "user" with "yourmodel". The same logic applies everywhere.
You can access the current authenticated user in your controller with this method:
current_user
If no valid token is passed with the request, Knock will respond with:
head :unauthorized
Authenticating from a web or mobile application:
Example request to get a token from your API:
POST /user_tokens
{"auth": {"email": "foo@bar.com", "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 in the request header:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
GET /my_resources
NB: HTTPS should always be enabled when sending a password or token in your request.
Authenticated tests
To authenticate within your tests:
- Create a valid token
- Pass it in your request
e.g.
class SecuredControllerTest < ActionController::TestCase
def authenticate
token = Knock::AuthToken.new(payload: { sub: users(:one).id }).token
request.env['HTTP_AUTHORIZATION'] = "Bearer #{token}"
end
setup do
authenticate
end
it 'responds successfully' do
get :index
assert_response :success
end
end
Algorithms
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.
CORS
To enable cross-origin resource sharing, check out the rack-cors gem.
Related links
Contributing
- Fork it ( https://github.com/nsarno/knock/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
License
MIT