Permalink
Browse files

JWT authentication from scratch

1 parent 645408a commit dc74a648f6e788117037bc4443bdbb928dd7d899 @excid3 excid3 committed Jan 6, 2017
View
@@ -46,3 +46,6 @@ end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+
+gem 'devise'
+gem 'jwt'
View
@@ -39,6 +39,7 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (7.1.4)
+ bcrypt (3.1.11)
builder (3.2.2)
byebug (9.0.6)
coffee-rails (4.2.1)
@@ -50,6 +51,12 @@ GEM
coffee-script-source (1.12.1)
concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
+ devise (4.2.0)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0, < 5.1)
+ responders
+ warden (~> 1.2.3)
erubis (2.7.0)
execjs (2.7.0)
ffi (1.9.14)
@@ -63,6 +70,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
+ jwt (1.5.6)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
@@ -80,6 +88,7 @@ GEM
nio4r (1.2.1)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
+ orm_adapter (0.5.0)
puma (3.6.2)
rack (2.0.1)
rack-test (0.6.3)
@@ -111,6 +120,8 @@ GEM
rb-fsevent (0.9.8)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
+ responders (2.3.0)
+ railties (>= 4.2.0, < 5.1)
sass (3.4.22)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
@@ -141,6 +152,8 @@ GEM
thread_safe (~> 0.1)
uglifier (3.0.4)
execjs (>= 0.3.0, < 3)
+ warden (1.2.6)
+ rack (>= 1.0)
web-console (3.4.0)
actionview (>= 5.0)
activemodel (>= 5.0)
@@ -156,8 +169,10 @@ PLATFORMS
DEPENDENCIES
byebug
coffee-rails (~> 4.2)
+ devise
jbuilder (~> 2.5)
jquery-rails
+ jwt
listen (~> 3.0.5)
puma (~> 3.0)
rails (~> 5.0.0, >= 5.0.0.1)
@@ -0,0 +1,12 @@
+class Api::V1::AuthenticationController < ApiController
+ skip_before_action :authenticate_token!
+
+ def create
+ user = User.find_by(email: params[:user][:email])
+ if user.valid_password? params[:user][:password]
+ render json: { token: JsonWebToken.encode(sub: user.id) }
+ else
+ render json: { errors: ["Invalid email or password"] }
+ end
+ end
+end
@@ -1,9 +1,25 @@
class ApiController < ApplicationController
+ skip_before_action :verify_authenticity_token
+
before_action :set_default_format
+ before_action :authenticate_token!
private
def set_default_format
request.format = :json
end
+
+ def authenticate_token!
+ payload = JsonWebToken.decode(auth_token)
+ @current_user = User.find(payload["sub"])
+ rescue JWT::ExpiredSignature
+ render json: {errors: ["Auth token has expired"]}, status: :unauthorized
+ rescue JWT::DecodeError
+ render json: {errors: ["Invalid auth token"]}, status: :unauthorized
+ end
+
+ def auth_token
+ @auth_token ||= request.headers.fetch("Authorization", "").split(" ").last
+ end
end
@@ -0,0 +1,10 @@
+class JsonWebToken
+ def self.encode(payload)
+ expiration = 30.minutes.from_now.to_i
+ JWT.encode payload.merge(exp: expiration), Rails.application.secrets.secret_key_base
+ end
+
+ def self.decode(token)
+ JWT.decode(token, Rails.application.secrets.secret_key_base).first
+ end
+end
View
@@ -0,0 +1,6 @@
+class User < ApplicationRecord
+ # Include default devise modules. Others available are:
+ # :confirmable, :lockable, :timeoutable and :omniauthable
+ devise :database_authenticatable, :registerable,
+ :recoverable, :rememberable, :trackable, :validatable
+end
Oops, something went wrong.

0 comments on commit dc74a64

Please sign in to comment.