https://github.com/brocoders/jwt_authentication
Rails JWT token Authentication for Devise
https://github.com/brocoders/jwt_authentication
Last synced: about 1 year ago
JSON representation
Rails JWT token Authentication for Devise
- Host: GitHub
- URL: https://github.com/brocoders/jwt_authentication
- Owner: brocoders
- License: gpl-3.0
- Created: 2015-03-03T12:18:33.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2017-01-23T20:07:42.000Z (over 9 years ago)
- Last Synced: 2025-04-03T22:01:39.665Z (about 1 year ago)
- Language: Ruby
- Homepage:
- Size: 43 KB
- Stars: 34
- Watchers: 3
- Forks: 11
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
JWT Authentication
===========================
[devise]: https://github.com/plataformatec/devise
[jwt-gem]: https://github.com/progrium/ruby-jwt
[sta-gem]: https://github.com/gonzalo-bulnes/simple_token_authentication
This is a mix of [Simple Token Authentication][sta-gem] and [JWT][jwt-gem], based on [Devise][devise].
* [Installation](#installation)
* [Using](#using)
* [Configuring](#configuring)
* [Authentication](#authentication)
* [Devise](#devise)
Installation
-----
Add the gem to your `Gemfile`:
```ruby
# Gemfile
gem 'jwt_authentication', github: 'Rezonans/jwt_authentication'
```
Using
-----
### Models
Make the models token authenticatable
#### ActiveRecord
First define which model or models will be token authenticatable (typ. `User`):
```ruby
# app/models/user.rb
class User < ActiveRecord::Base
acts_as_jwt_authenticatable
# Note: you can include any module you want. If available,
# token authentication will be performed before any other
# Devise authentication method.
#
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable,
:lockable
# ...
end
```
Method `acts_as_jwt_authenticatable` extends Model with several methods: `:jwt_token`, `:generate_authentication_token!`
and some others. Obviously, `:jwt_token` returns token for current record and `:generate_authentication_token!` updates record with new authentication_token.
If the model or models that you have chosen does not contain `:authentication_token` column, then add the new column onto it (with index):
```bash
rails g jwt_authentication MODEL
```
This will add 'acts_as_jwt_authenticatable' to specified MODEL. Also, this will generate migration for adding 'authentication_token' to MODEL.
To skip generating migration add '-m' parameter: rails g jwt_authentication User -m.
Migration looks like:
```ruby
def change
add_column :users, :authentication_token, :string
add_index :users, :authentication_token
end
```
### Allow controllers to handle jwt authentication
Define controllers, which will handle jwt authentication (typ. `HomeController`) for which _jwt authenticatable_ models:
```ruby
# app/controllers/home_controller.rb
class HomeController < ActionController::Base # or ActionController::API
# ...
acts_as_jwt_authentication_handler
# Note: you can specify several parameters for handling authentication for this controller:
# :models (which "acts as jwt authenticatable") for authenticating, hash, that specifies models
# and those authentication parameters :header_name, :param_name, :sign_in
#
# example:
# acts_as_jwt_authentication_handler models: {terminal: {header_name: 'terminal_auth_token',
# param_name: 'X-Auth-Terminal-Token',
# sign_in: :simplified}
#
# ...
end
```
Method `acts_as_jwt_authentication_handler` extends controller with methods: `:jwt_authenticate_user`, `:jwt_authenticate_user!` and with another ones.
Instead of _user_ there will be specified model names, pair of methods for each model.
See detailed parameters and methods description in [Authentication](#authentication)
Atfer controller was extended with jwt_authentication helpers, you may authenticate entity in _actions_ or in _before filter_:
```ruby
class TerminalsController < ActionController
acts_as_jwt_authentication_handler models: {terminal: {sign_in: :simlified}}
before_filter :jwt_authenticate_terminal!
def show
@terminal
end
end
```
### Routing
Define devise routes for creating devise mapping.
```ruby
# config/routes.rb
...
devise_for :users, module: :jwt_authentication
...
```
Devise routing is necessary, because it creates devise mappings.
Configuring
------
Some aspects of the behavior of _Jwt Authentication_ can be customized with an initializer.
Below is an example with reasonable defaults:
```ruby
# config/initializers/jwt_authentication.rb
JwtAuthentication.configure do |config|
#
# # Configure models, that will be default for `acts_as_jwt_authentication_handler` calling.
# # Note: specified model should have `authentication_token` attribute (Model should "act as jwt authenticatable")
# # header_name - name of header to search auth_token within request
# # param_name - name of parameters to search auth_token within request
# # sign_in - method to be executed if authentication success, possible values: :devise, :simplified
# # if :devise selected, devises method sign_in() will be called at success authentication,
# # if :simplified selected, instance variable with name of resource will be set (@user or @terminal)
# config.models = {user: {header_name: 'X-User-Token',
# param_name: 'user_token',
# sign_in: :devise}}
#
# # Configure mark of jwt timeout verification
# config.jwt_timeout_verify = true
#
# # Configure jwt timeout leeway (value in seconds)
# config.jwt_timeout_leeway = 60
#
# # Configure jwt timeout for simple login (without "remember me")
# # Devise SessionsController generates jwt according to this parameter
# # * This parameter may be overridden in each model:
# # acts_as_jwt_authenticatable jwt_timeout: 10.minutes
# config.jwt_timeout = 20.minutes
#
# # Configure jwt timeout for session login (with "remember me")
# # Devise SessionsController generates jwt according to this parameter
# # * This parameter may be overridden in each model:
# # acts_as_jwt_authenticatable jwt_timeout_remember_me: 1.week
# config.jwt_timeout_remember_me = 1.month
#
# # Configure list of model keys to be stored in jwt payload.
# # Also, record will be searched by this fields at authentication.
# # * This parameter may be overridden in each model:
# # acts_as_jwt_authenticatable key_fields: [:email, :id]
# config.key_fields = [:email]
#
end
```
Authentication
-----
As there was mentioned in [Using](#using), method `acts_as_jwt_authentication_handler` adds to controller two methods:
`:jwt_authenticate_user` and `:jwt_authenticate_user!`. Method with bang raises error, if authentication falls,
method without bang do nothing if authentication falls.
Authentication process is pretty simple:
* Analize request - try to find token either in params or header. If token is not found, authentication falls.
* Read payload from jwt
* Search for entity by field, that payload contains. If entity is not found, authentication falls.
* Decode jwt with entities `authentication_token` (private key, that is stored as entities field).
If `jwt_timeout_verify` specified, timeout verification will take place also.
* If token successfully verified - _sign_in handler_ will be called, otherwise authentication falls.
`sign_in_handler`. You may specify, what to do at success authentication in `sign_in` parameter in model:
```ruby
# config/initializers/jwt_authentication.rb
...
config.models = {user: {sign_in: :devise}}
...
```
There are 2 variants:
* `:devise` (default) - `:sign_in` (devise controller method) will be called
* `:simplified` - create instance variable with resource name (@user, @terminal, etc).
Devise
-----
JwtAuthentication inherits devise controllers: Registrations, Confirmations, Sessions, Passwords.
So, you can extend this functionality with inheritance or override of some of them.
Note, that you need to specify routes to this inherited controllers, like here:
```ruby
# config/routes.rb
...
devise_for :users, module: :jwt_authentication
...
```
_Note: request format will be set to `:json` by before filter `:set_request_format!`, that is plugged to each inherited devise controller.
It is necessary for process action if `warder.authenticate!` falls. It will render view for sessions creating by default,
but in our case we need json response :unauthorized_