Skip to content

Commit e02d39a

Browse files
author
Rodion
committed
Merge pull request #7 from Blaze34/cookies
work with cookies
2 parents 202f6d5 + 0713c72 commit e02d39a

File tree

10 files changed

+81
-17
lines changed

10 files changed

+81
-17
lines changed

app/controllers/jwt_authentication/confirmations_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ def show
1111
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
1212
yield resource if block_given?
1313
if resource.errors.empty?
14-
render json: { auth_token: resource.jwt_token }
14+
token, expires = resource.jwt_token_and_expires
15+
send(:"set_jwt_cookie_for_#{resource_name}", token, expires)
16+
render json: { auth_token: token }
1517
else
1618
render_errors resource.errors
1719
end

app/controllers/jwt_authentication/passwords_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ def update
1717
if resource.errors.empty?
1818
resource.unlock_access! if unlockable?(resource)
1919
sign_in(resource_name, resource)
20-
render json: { auth_token: resource.jwt_token }
20+
token, expires = resource.jwt_token_and_expires
21+
send(:"set_jwt_cookie_for_#{resource_name}", token, expires)
22+
render json: { auth_token: token }
2123
else
2224
render_errors resource.errors
2325
end

app/controllers/jwt_authentication/registrations_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ def create
88
if resource_saved
99
if resource.active_for_authentication?
1010
sign_in(resource_name, resource, store: false)
11+
token, expires = resource.jwt_token_and_expires
12+
send(:"set_jwt_cookie_for_#{resource_name}", token, expires)
1113
render json: {
12-
auth_token: resource.jwt_token,
14+
auth_token: token,
1315
resource_name => resource
1416
}
1517
return

app/controllers/jwt_authentication/sessions_controller.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ def create
55
self.resource = warden.authenticate!({ scope: resource_name, recall: "#{controller_path}#new", store: false })
66
sign_in(resource_name, resource)
77
yield resource if block_given?
8-
render json: { auth_token: resource.jwt_token(sign_in_params[:remember_me]) }
8+
9+
token, expires = resource.jwt_token_and_expires(sign_in_params[:remember_me])
10+
send(:"set_jwt_cookie_for_#{resource_name}", token, expires)
11+
render json: { auth_token: token }
912
end
1013

1114
def destroy

lib/generators/templates/jwt_authentication.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
# # Note: specified model should have `authentication_token` attribute (Model should "act as jwt authenticatable")
55
# # header_name - name of header to search auth_token in request
66
# # param_name - name of parameters to search auth_token in request
7+
# # cookie_name - name of cookie to search auth_token in request
78
# # sign_in - method to be executed if authentication success, possible values: :devise, :simplified
89
# # if :devise selected, devises method sign_in() will be called at success authentication,
910
# # if :simplified selected, instance variable with name of resource will be set (@user or @terminal)
1011
# config.models = {user: {header_name: 'X-User-Token',
1112
# param_name: 'user_token',
13+
# # cookie_name: 'user_token',
1214
# sign_in: :devise}}
1315
#
1416
# # Configure mark of jwt timeout verification

lib/jwt_authentication.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
require 'jwt_authentication/acts_as_jwt_authenticatable'
22
require 'jwt_authentication/acts_as_jwt_authentication_handler'
33
require 'jwt_authentication/configuration'
4+
require 'jwt_authentication/engine'
45
require 'jwt'
56

67
module JwtAuthentication
78
extend Configuration
89

9-
class Engine < ::Rails::Engine
10-
end
11-
1210
NoAdapterAvailableError = Class.new(LoadError)
1311

1412
private

lib/jwt_authentication/acts_as_jwt_authenticatable.rb

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module ActsAsJwtAuthenticatable
99
private :generate_authentication_token
1010
private :token_suitable?
1111
private :token_generator
12+
private :token_expires_and_data
1213
end
1314

1415
def ensure_authentication_token
@@ -36,13 +37,21 @@ def token_generator
3637
@token_generator ||= TokenGenerator.new
3738
end
3839

39-
def jwt_token(remember = false)
40+
def token_expires_and_data(remember = false)
4041
data = self.class.jwt_key_fields.inject({}) { |hash, field| hash[field] = self.send field; hash }
41-
payload = {
42-
exp: (Time.now + jwt_session_duration(remember)).to_i,
43-
self.class.name.underscore => data
44-
}
45-
JWT.encode(payload, self.authentication_token)
42+
43+
[Time.now + jwt_session_duration(remember), data]
44+
end
45+
46+
def jwt_token_and_expires(remember = false)
47+
expires, data = token_expires_and_data(remember)
48+
payload = {exp: expires.to_i, self.class.name.underscore => data}
49+
50+
[JWT.encode(payload, self.authentication_token), expires]
51+
end
52+
53+
def jwt_token(remember = false)
54+
jwt_token_and_expires(remember).first
4655
end
4756

4857
def jwt_session_duration(remember = false)

lib/jwt_authentication/engine.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module JwtAuthentication
2+
class Engine < ::Rails::Engine
3+
initializer 'jwt-autentication' do |app|
4+
cookies_required = JwtAuthentication.models.any? { |key, value| value.is_a?(Hash) && value.has_key?(:cookie_name) }
5+
6+
if cookies_required
7+
app.middleware.use ::ActionDispatch::Cookies
8+
9+
JwtAuthentication::JwtAuthenticationHandler.module_exec do
10+
include ::ActionController::Cookies
11+
end
12+
end
13+
end
14+
end
15+
end

lib/jwt_authentication/entity.rb

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,26 @@ def token_param_name(controller)
2525
controller.jwt_models[name_underscore.to_sym][:param_name] || "#{name_underscore}_token"
2626
end
2727

28-
def get_token_from_params_or_headers(controller)
29-
(controller.request.headers[token_header_name(controller)] || controller.params[token_param_name(controller)]).to_s
28+
def token_cookie_name(controller)
29+
controller.jwt_models[name_underscore.to_sym][:cookie_name]
30+
end
31+
32+
def cookie_enabled?(controller)
33+
token_cookie_name(controller).present?
34+
end
35+
36+
def get_token_from_cookie(controller)
37+
cookie_enabled?(controller) ? controller.send(:cookies).signed[token_cookie_name(controller)] : nil
38+
end
39+
40+
def get_token(controller)
41+
(get_token_from_cookie(controller) || controller.request.headers[token_header_name(controller)] || controller.params[token_param_name(controller)]).to_s
3042
end
3143

3244
def get_entity(controller)
3345
begin
34-
token = get_token_from_params_or_headers controller
35-
payload = JWT.decode(token, nil, false)[0] # get payload; decode can riase: JWT::DecodeError
46+
token = get_token controller
47+
payload = JWT.decode(token, nil, false)[0] # get payload; decode can raise: JWT::DecodeError
3648
keys = model.jwt_key_fields.inject({}) do |hash, field|
3749
hash[field] = payload[name_underscore][field.to_s]
3850
hash

lib/jwt_authentication/jwt_authentication_handler.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ module JwtAuthenticationHandler
1515
private :authenticate_entity_by_jwt!
1616
private :sign_in_handler
1717
private :raise_error!
18+
private :set_jwt_to_cookie
19+
1820
end
1921

2022
def authenticate_entity_by_jwt!(entity)
@@ -33,6 +35,17 @@ def raise_error!
3335
raise JwtAuthentication::NotAuthenticated.new('Not authenticated')
3436
end
3537

38+
def set_jwt_to_cookie(entity, token, expires)
39+
return unless entity.cookie_enabled? self
40+
41+
cookie_name = entity.token_cookie_name(self)
42+
if JwtAuthentication.jwt_timeout_verify
43+
cookies.signed[cookie_name] = {value: token, expires: expires}
44+
else
45+
cookies.permanent.signed[cookie_name] = token
46+
end
47+
end
48+
3649
def valid_entity_name?(entity)
3750
jwt_models.has_key? entity.name_underscore.to_sym
3851
end
@@ -96,6 +109,12 @@ def define_jwt_authentication_helpers_for(entity)
96109
raise_error! unless authenticate_entity_by_jwt!(_entity)
97110
end.call(entity)
98111
end
112+
113+
define_method "set_jwt_cookie_for_#{entity.name_underscore}".to_sym do |token, expires|
114+
lambda do |_entity|
115+
set_jwt_to_cookie(_entity, token, expires)
116+
end.call(entity)
117+
end
99118
end
100119
end
101120
end

0 commit comments

Comments
 (0)