rails_jwt_auth 0.23.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +77 -219
  3. data/app/controllers/concerns/rails_jwt_auth/authenticable_helper.rb +31 -0
  4. data/app/controllers/rails_jwt_auth/confirmations_controller.rb +3 -6
  5. data/app/controllers/rails_jwt_auth/invitations_controller.rb +5 -8
  6. data/app/controllers/rails_jwt_auth/passwords_controller.rb +3 -7
  7. data/app/controllers/rails_jwt_auth/sessions_controller.rb +13 -9
  8. data/app/mailers/rails_jwt_auth/mailer.rb +32 -47
  9. data/app/models/concerns/rails_jwt_auth/authenticatable.rb +31 -25
  10. data/app/models/concerns/rails_jwt_auth/confirmable.rb +54 -47
  11. data/app/models/concerns/rails_jwt_auth/invitable.rb +10 -11
  12. data/app/models/concerns/rails_jwt_auth/recoverable.rb +29 -28
  13. data/app/models/concerns/rails_jwt_auth/trackable.rb +1 -1
  14. data/app/views/rails_jwt_auth/mailer/confirmation_instructions.html.erb +2 -2
  15. data/app/views/rails_jwt_auth/mailer/reset_password_instructions.html.erb +2 -2
  16. data/app/views/rails_jwt_auth/mailer/send_invitation.html.erb +2 -2
  17. data/app/views/rails_jwt_auth/mailer/set_password_instructions.html.erb +2 -2
  18. data/lib/generators/rails_jwt_auth/install_generator.rb +4 -5
  19. data/lib/generators/rails_jwt_auth/migrate_generator.rb +17 -0
  20. data/lib/generators/templates/initializer.rb +15 -18
  21. data/lib/generators/templates/migration.rb +29 -0
  22. data/lib/rails_jwt_auth.rb +54 -20
  23. data/lib/rails_jwt_auth/engine.rb +0 -21
  24. data/lib/rails_jwt_auth/jwt_manager.rb +33 -0
  25. data/lib/rails_jwt_auth/spec_helpers.rb +15 -0
  26. data/lib/rails_jwt_auth/version.rb +1 -1
  27. metadata +8 -10
  28. data/app/controllers/concerns/rails_jwt_auth/warden_helper.rb +0 -29
  29. data/lib/rails_jwt_auth/jwt/manager.rb +0 -41
  30. data/lib/rails_jwt_auth/jwt/request.rb +0 -34
  31. data/lib/rails_jwt_auth/spec/helpers.rb +0 -17
  32. data/lib/rails_jwt_auth/spec/not_authorized.rb +0 -6
  33. data/lib/rails_jwt_auth/strategies/jwt.rb +0 -17
  34. data/lib/tasks/rails_token_jwt_tasks.rake +0 -4
@@ -1,20 +1,42 @@
1
1
  module RailsJwtAuth
2
2
  module Recoverable
3
+ def self.included(base)
4
+ base.class_eval do
5
+ if defined?(Mongoid) && base.ancestors.include?(Mongoid::Document)
6
+ # include GlobalID::Identification to use deliver_later method
7
+ # http://edgeguides.rubyonrails.org/active_job_basics.html#globalid
8
+ include GlobalID::Identification if RailsJwtAuth.deliver_later
9
+
10
+ field :reset_password_token, type: String
11
+ field :reset_password_sent_at, type: Time
12
+ end
13
+
14
+ validate :validate_reset_password_token, if: :password_digest_changed?
15
+
16
+ before_update do
17
+ self.reset_password_token = nil if password_digest_changed? && reset_password_token
18
+ end
19
+ end
20
+ end
21
+
3
22
  def send_reset_password_instructions
23
+ email_field = RailsJwtAuth.email_field_name! # ensure email field es valid
24
+
4
25
  if self.class.ancestors.include?(RailsJwtAuth::Confirmable) && !confirmed?
5
- errors.add(:email, :unconfirmed)
26
+ errors.add(email_field, :unconfirmed)
6
27
  return false
7
28
  end
8
29
 
9
30
  self.reset_password_token = SecureRandom.base58(24)
10
- self.reset_password_sent_at = Time.now
31
+ self.reset_password_sent_at = Time.current
11
32
  return false unless save
12
33
 
13
- mailer = Mailer.reset_password_instructions(id.to_s)
34
+ mailer = Mailer.reset_password_instructions(self)
14
35
  RailsJwtAuth.deliver_later ? mailer.deliver_later : mailer.deliver
15
36
  end
16
37
 
17
38
  def set_and_send_password_instructions
39
+ RailsJwtAuth.email_field_name! # ensure email field es valid
18
40
  return if password.present?
19
41
 
20
42
  self.password = SecureRandom.base58(48)
@@ -22,40 +44,19 @@ module RailsJwtAuth
22
44
  self.skip_confirmation! if self.class.ancestors.include?(RailsJwtAuth::Confirmable)
23
45
 
24
46
  self.reset_password_token = SecureRandom.base58(24)
25
- self.reset_password_sent_at = Time.now
47
+ self.reset_password_sent_at = Time.current
26
48
  return false unless save
27
49
 
28
- mailer = Mailer.set_password_instructions(id.to_s)
50
+ mailer = Mailer.set_password_instructions(self)
29
51
  RailsJwtAuth.deliver_later ? mailer.deliver_later : mailer.deliver
30
52
  true
31
53
  end
32
54
 
33
- def self.included(base)
34
- base.class_eval do
35
- if defined?(Mongoid) && base.ancestors.include?(Mongoid::Document)
36
- # include GlobalID::Identification to use deliver_later method
37
- # http://edgeguides.rubyonrails.org/active_job_basics.html#globalid
38
- include GlobalID::Identification if RailsJwtAuth.deliver_later
39
-
40
- field :reset_password_token, type: String
41
- field :reset_password_sent_at, type: Time
42
- end
43
-
44
- validate :validate_reset_password_token, if: :password_digest_changed?
45
-
46
- before_update do
47
- if password_digest_changed? && reset_password_token
48
- self.reset_password_token = nil
49
- end
50
- end
51
- end
52
- end
53
-
54
- private
55
+ protected
55
56
 
56
57
  def validate_reset_password_token
57
58
  if reset_password_sent_at &&
58
- (reset_password_sent_at < (Time.now - RailsJwtAuth.reset_password_expiration_time))
59
+ (reset_password_sent_at < (Time.current - RailsJwtAuth.reset_password_expiration_time))
59
60
  errors.add(:reset_password_token, :expired)
60
61
  end
61
62
  end
@@ -1,7 +1,7 @@
1
1
  module RailsJwtAuth
2
2
  module Trackable
3
3
  def update_tracked_fields!(request)
4
- self.last_sign_in_at = Time.now.utc
4
+ self.last_sign_in_at = Time.current
5
5
  self.last_sign_in_ip = request.respond_to?(:remote_ip) ? request.remote_ip : request.ip
6
6
  save(validate: false)
7
7
  end
@@ -1,5 +1,5 @@
1
- <p>Welcome <%= @user.email %>!</p>
1
+ <p>Welcome <%= @user[RailsJwtAuth.email_field_name] %>!</p>
2
2
 
3
3
  <p>You can confirm your account email through the link below:</p>
4
4
 
5
- <p><%= link_to 'Confirm my account', @confirmation_url.html_safe %></p>
5
+ <p><%= link_to 'Confirm my account', @confirmations_url.html_safe %></p>
@@ -1,8 +1,8 @@
1
- <p>Hello <%= @user.email %>!</p>
1
+ <p>Hello <%= @user[RailsJwtAuth.email_field_name] %>!</p>
2
2
 
3
3
  <p>Someone has requested a link to change your password. You can do this through the link below.</p>
4
4
 
5
- <p><%= link_to 'Change my password', @reset_password_url.html_safe %></p>
5
+ <p><%= link_to 'Change my password', @reset_passwords_url.html_safe %></p>
6
6
 
7
7
  <p>If you didn't request this, please ignore this email.</p>
8
8
  <p>Your password won't change until you access the link above and create a new one.</p>
@@ -1,6 +1,6 @@
1
- <p>Hello <%= @user.email %>!</p>
1
+ <p>Hello <%= @user[RailsJwtAuth.email_field_name] %>!</p>
2
2
 
3
3
  <p>Someone has sent you an invitation to App.</p>
4
4
  <p>To complete registration setting a password, please click the following link.</p>
5
5
 
6
- <p><%= link_to "Accept invitation", @accept_invitation_url.html_safe %></p>
6
+ <p><%= link_to "Accept invitation", @invitations_url.html_safe %></p>
@@ -1,5 +1,5 @@
1
- <p>Hello <%= @user.email %>!</p>
1
+ <p>Hello <%= @user[RailsJwtAuth.email_field_name] %>!</p>
2
2
 
3
3
  <p>You need to define your password to complete registration. You can do this through the link below.</p>
4
4
 
5
- <p><%= link_to 'Set my password', @reset_password_url.html_safe %></p>
5
+ <p><%= link_to 'Set my password', @reset_passwords_url.html_safe %></p>
@@ -6,12 +6,11 @@ class RailsJwtAuth::InstallGenerator < Rails::Generators::Base
6
6
  end
7
7
 
8
8
  def create_routes
9
- route "resource :session, controller: 'rails_jwt_auth/sessions', only: [:create, :destroy]"
10
- route "resource :registration, controller: 'rails_jwt_auth/registrations', only: [:create, :update, :destroy]"
11
-
12
- route "resource :confirmation, controller: 'rails_jwt_auth/confirmations', only: [:create, :update]"
13
- route "resource :password, controller: 'rails_jwt_auth/passwords', only: [:create, :update]"
9
+ route "resources :session, controller: 'rails_jwt_auth/sessions', only: [:create, :destroy]"
10
+ route "resources :registration, controller: 'rails_jwt_auth/registrations', only: [:create, :update, :destroy]"
14
11
 
12
+ route "resources :confirmations, controller: 'rails_jwt_auth/confirmations', only: [:create, :update]"
13
+ route "resources :passwords, controller: 'rails_jwt_auth/passwords', only: [:create, :update]"
15
14
  route "resources :invitations, controller: 'rails_jwt_auth/invitations', only: [:create, :update]"
16
15
  end
17
16
  end
@@ -0,0 +1,17 @@
1
+ class RailsJwtAuth::MigrateGenerator < Rails::Generators::Base
2
+ include Rails::Generators::Migration
3
+
4
+ source_root File.expand_path('../templates', __dir__)
5
+
6
+ def self.next_migration_number(_dir)
7
+ Time.current.strftime('%Y%m%d%H%M%S')
8
+ end
9
+
10
+ def create_initializer_file
11
+ migration_template 'migration.rb', "db/migrate/create_#{RailsJwtAuth.table_name}.rb"
12
+ end
13
+
14
+ def migration_version
15
+ "[#{Rails.version.split('.')[0..1].join('.')}]"
16
+ end
17
+ end
@@ -5,11 +5,8 @@ RailsJwtAuth.setup do |config|
5
5
  # field name used to authentication with password
6
6
  #config.auth_field_name = 'email'
7
7
 
8
- # set to true to validate auth_field email format
9
- #config.auth_field_email = true
10
-
11
- # regex used to Validate email format
12
- #config.email_regex = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
8
+ # define email field name used to send emails
9
+ #config.email_field_name = 'email'
13
10
 
14
11
  # expiration time for generated tokens
15
12
  #config.jwt_expiration_time = 7.days
@@ -23,28 +20,28 @@ RailsJwtAuth.setup do |config|
23
20
  # mailer sender
24
21
  #config.mailer_sender = 'initialize-mailer_sender@example.com'
25
22
 
26
- # url used to create email link with confirmation token
27
- #config.confirmation_url = 'http://frontend.com/confirmation'
28
-
29
23
  # expiration time for confirmation tokens
30
24
  #config.confirmation_expiration_time = 1.day
31
25
 
26
+ # expiration time for reset password tokens
27
+ #config.reset_password_expiration_time = 1.day
28
+
29
+ # time an invitation is valid after sent
30
+ # config.invitation_expiration_time = 2.days
31
+
32
+ # url used to create email link with confirmation token
33
+ #config.confirmations_url = 'http://frontend.com/confirmation'
34
+
32
35
  # url used to create email link with reset password token
33
- #config.reset_password_url = 'http://frontend.com/reset_password'
36
+ #config.reset_passwords_url = 'http://frontend.com/reset_password'
34
37
 
35
38
  # url used to create email link with set password token
36
39
  # by set_and_send_password_instructions method
37
- #config.set_password_url = 'http://frontend.com/set_password'
40
+ #config.set_passwords_url = 'http://frontend.com/set_password'
38
41
 
39
- # expiration time for reset password tokens
40
- #config.reset_password_expiration_time = 1.day
42
+ # url used to create email link with activation token parameter to accept invitation
43
+ #config.invitations_url = 'http://frontend.com/accept_invitation'
41
44
 
42
45
  # uses deliver_later to send emails instead of deliver method
43
46
  #config.deliver_later = false
44
-
45
- # time an invitation is valid after sent
46
- # config.invitation_expiration_time = 2.days
47
-
48
- # url used to create email link with activation token parameter to accept invitation
49
- # config.accept_invitation_url = 'http://frontend.com/accept_invitation'
50
47
  end
@@ -0,0 +1,29 @@
1
+ class Create<%= RailsJwtAuth.model_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ create_table :<%= RailsJwtAuth.table_name %> do |t|
4
+ t.string :email
5
+ t.string :password_digest
6
+ t.string :auth_tokens
7
+
8
+ ## Confirmable
9
+ # t.string :unconfirmed_email
10
+ # t.string :confirmation_token
11
+ # t.datetime :confirmation_sent_at
12
+ # t.datetime :confirmed_at
13
+
14
+ ## Recoverable
15
+ # t.string :reset_password_token
16
+ # t.datetime :reset_password_sent_at
17
+
18
+ ## Trackable
19
+ # t.string :last_sign_in_ip
20
+ # t.datetime :last_sign_in_at
21
+
22
+ ## Invitable
23
+ # t.string :invitation_token
24
+ # t.datetime :invitation_sent_at
25
+ # t.datetime :invitation_accepted_at
26
+ # t.datetime :invitation_created_at
27
+ end
28
+ end
29
+ end
@@ -1,20 +1,24 @@
1
- require 'warden'
2
1
  require 'bcrypt'
3
2
 
4
3
  require 'rails_jwt_auth/engine'
4
+ require 'rails_jwt_auth/jwt_manager'
5
5
 
6
6
  module RailsJwtAuth
7
+ InvalidEmailField = Class.new(StandardError)
8
+ InvalidAuthField = Class.new(StandardError)
9
+ NotConfirmationsUrl = Class.new(StandardError)
10
+ NotInvitationsUrl = Class.new(StandardError)
11
+ NotResetPasswordsUrl = Class.new(StandardError)
12
+ NotSetPasswordsUrl = Class.new(StandardError)
13
+
7
14
  mattr_accessor :model_name
8
15
  self.model_name = 'User'
9
16
 
10
17
  mattr_accessor :auth_field_name
11
18
  self.auth_field_name = 'email'
12
19
 
13
- mattr_accessor :auth_field_email
14
- self.auth_field_email = true
15
-
16
- mattr_accessor :email_regex
17
- self.email_regex = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
20
+ mattr_accessor :email_field_name
21
+ self.email_field_name = 'email'
18
22
 
19
23
  mattr_accessor :jwt_expiration_time
20
24
  self.jwt_expiration_time = 7.days
@@ -28,35 +32,65 @@ module RailsJwtAuth
28
32
  mattr_accessor :mailer_sender
29
33
  self.mailer_sender = 'initialize-mailer_sender@example.com'
30
34
 
31
- mattr_accessor :confirmation_url
32
- self.confirmation_url = nil
33
-
34
35
  mattr_accessor :confirmation_expiration_time
35
36
  self.confirmation_expiration_time = 1.day
36
37
 
37
- mattr_accessor :reset_password_url
38
- self.reset_password_url = nil
39
-
40
- mattr_accessor :set_password_url
41
- self.set_password_url = nil
42
-
43
38
  mattr_accessor :reset_password_expiration_time
44
39
  self.reset_password_expiration_time = 1.day
45
40
 
46
- mattr_accessor :deliver_later
47
- self.deliver_later = false
48
-
49
41
  mattr_accessor :invitation_expiration_time
50
42
  self.invitation_expiration_time = 2.days
51
43
 
52
- mattr_accessor :accept_invitation_url
53
- self.accept_invitation_url = nil
44
+ mattr_accessor :confirmations_url
45
+ self.confirmations_url = nil
46
+
47
+ mattr_accessor :reset_passwords_url
48
+ self.reset_passwords_url = nil
49
+
50
+ mattr_accessor :set_passwords_url
51
+ self.set_passwords_url = nil
52
+
53
+ mattr_accessor :invitations_url
54
+ self.invitations_url = nil
55
+
56
+ mattr_accessor :deliver_later
57
+ self.deliver_later = false
54
58
 
55
59
  def self.model
56
60
  model_name.constantize
57
61
  end
58
62
 
63
+ def self.table_name
64
+ model_name.underscore.pluralize
65
+ end
66
+
59
67
  def self.setup
60
68
  yield self
61
69
  end
70
+
71
+ def self.auth_field_name!
72
+ field_name = RailsJwtAuth.auth_field_name
73
+ klass = RailsJwtAuth.model
74
+
75
+ unless field_name.present? &&
76
+ (klass.respond_to?(:column_names) && klass.column_names.include?(field_name) ||
77
+ klass.respond_to?(:fields) && klass.fields[field_name])
78
+ raise RailsJwtAuth::InvalidAuthField
79
+ end
80
+
81
+ field_name
82
+ end
83
+
84
+ def self.email_field_name!
85
+ field_name = RailsJwtAuth.email_field_name
86
+ klass = RailsJwtAuth.model
87
+
88
+ unless field_name.present? &&
89
+ (klass.respond_to?(:column_names) && klass.column_names.include?(field_name) ||
90
+ klass.respond_to?(:fields) && klass.fields[field_name])
91
+ raise RailsJwtAuth::InvalidEmailField
92
+ end
93
+
94
+ field_name
95
+ end
62
96
  end
@@ -1,25 +1,4 @@
1
1
  module RailsJwtAuth
2
2
  class Engine < ::Rails::Engine
3
- require 'rails_jwt_auth/strategies/jwt'
4
-
5
- config.generators do |g|
6
- g.test_framework :rspec
7
- g.fixture_replacement :factory_girl, dir: 'spec/factories'
8
- end
9
-
10
- initializer 'rails_jwt_auth.warden' do |app|
11
- app.middleware.insert_after ActionDispatch::Callbacks, Warden::Manager do |manager|
12
- manager.default_strategies :authentication_token
13
- manager.failure_app = UnauthorizedController
14
- end
15
-
16
- Warden::Strategies.add(:authentication_token, Strategies::Jwt)
17
-
18
- Warden::Manager.after_set_user except: :fetch do |record, warden, options|
19
- if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(options[:scope])
20
- record.update_tracked_fields!(warden.request)
21
- end
22
- end
23
- end
24
3
  end
25
4
  end
@@ -0,0 +1,33 @@
1
+ require 'jwt'
2
+
3
+ module RailsJwtAuth
4
+ module JwtManager
5
+ def self.secret_key_base
6
+ Rails.application.secrets.secret_key_base || Rails.application.credentials.secret_key_base
7
+ end
8
+
9
+ # Encodes and signs JWT Payload with expiration
10
+ def self.encode(payload)
11
+ payload.reverse_merge!(meta)
12
+ JWT.encode(payload, secret_key_base)
13
+ end
14
+
15
+ # Decodes the JWT with the signed secret
16
+ # [{"auth_token"=>"xxx", "exp"=>148..., "iss"=>"RJA"}, {"typ"=>"JWT", "alg"=>"HS256"}]
17
+ def self.decode(token)
18
+ JWT.decode(token, secret_key_base)
19
+ end
20
+
21
+ # Default options to be encoded in the token
22
+ def self.meta
23
+ {
24
+ exp: RailsJwtAuth.jwt_expiration_time.from_now.to_i,
25
+ iss: RailsJwtAuth.jwt_issuer
26
+ }
27
+ end
28
+
29
+ def self.decode_from_request(request)
30
+ decode(request.env['HTTP_AUTHORIZATION']&.split&.last)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ module RailsJwtAuth
2
+ module SpecHelpers
3
+ def sign_out
4
+ warn '[DEPRECATION] `sign_out` is deprecated and not needed. Please remove it.'
5
+ end
6
+
7
+ def sign_in(user)
8
+ allow_any_instance_of(RailsJwtAuth::AuthenticableHelper)
9
+ .to receive(:authenticate!).and_return(true)
10
+
11
+ allow_any_instance_of(RailsJwtAuth::AuthenticableHelper)
12
+ .to receive(:current_user).and_return(user)
13
+ end
14
+ end
15
+ end