jwt-auth 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +48 -19
  3. data/.travis.yml +11 -0
  4. data/README.md +1 -1
  5. data/jwt-auth.gemspec +24 -21
  6. data/lib/jwt/auth/authentication.rb +3 -3
  7. data/lib/jwt/auth/token.rb +14 -3
  8. data/lib/jwt/auth/version.rb +1 -1
  9. data/spec/authentication_spec.rb +95 -0
  10. data/spec/configuration_spec.rb +1 -1
  11. data/spec/dummy/.gitignore +41 -0
  12. data/spec/dummy/Rakefile +6 -0
  13. data/spec/dummy/app/assets/config/manifest.js +4 -0
  14. data/spec/dummy/app/assets/images/.keep +0 -0
  15. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  16. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  17. data/spec/dummy/app/assets/javascripts/channels/.keep +0 -0
  18. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  19. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  20. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  21. data/spec/dummy/app/controllers/application_controller.rb +13 -0
  22. data/spec/dummy/app/controllers/authentication_controller.rb +15 -0
  23. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  24. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  25. data/spec/dummy/app/helpers/authentication_helper.rb +2 -0
  26. data/spec/dummy/app/jobs/application_job.rb +2 -0
  27. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  28. data/spec/dummy/app/models/application_record.rb +3 -0
  29. data/spec/dummy/app/models/concerns/.keep +0 -0
  30. data/spec/dummy/app/models/user.rb +14 -0
  31. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  32. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  33. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  34. data/spec/dummy/bin/bundle +3 -0
  35. data/spec/dummy/bin/rails +4 -0
  36. data/spec/dummy/bin/rake +4 -0
  37. data/spec/dummy/bin/setup +38 -0
  38. data/spec/dummy/bin/update +29 -0
  39. data/spec/dummy/bin/yarn +11 -0
  40. data/spec/dummy/config.ru +5 -0
  41. data/spec/dummy/config/application.rb +18 -0
  42. data/spec/dummy/config/boot.rb +5 -0
  43. data/spec/dummy/config/cable.yml +10 -0
  44. data/spec/dummy/config/database.yml +25 -0
  45. data/spec/dummy/config/environment.rb +5 -0
  46. data/spec/dummy/config/environments/development.rb +54 -0
  47. data/spec/dummy/config/environments/production.rb +91 -0
  48. data/spec/dummy/config/environments/test.rb +42 -0
  49. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  50. data/spec/dummy/config/initializers/assets.rb +14 -0
  51. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  52. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  53. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  54. data/spec/dummy/config/initializers/inflections.rb +16 -0
  55. data/spec/dummy/config/initializers/jwt_auth.rb +11 -0
  56. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  57. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  58. data/spec/dummy/config/locales/en.yml +33 -0
  59. data/spec/dummy/config/puma.rb +56 -0
  60. data/spec/dummy/config/routes.rb +6 -0
  61. data/spec/dummy/config/secrets.yml +32 -0
  62. data/spec/dummy/config/spring.rb +6 -0
  63. data/spec/dummy/db/migrate/20170726110751_create_users.rb +9 -0
  64. data/spec/dummy/db/migrate/20170726110825_add_token_version_to_user.rb +5 -0
  65. data/spec/dummy/db/migrate/20170726112117_add_activated_to_user.rb +5 -0
  66. data/spec/dummy/db/schema.rb +23 -0
  67. data/spec/dummy/lib/assets/.keep +0 -0
  68. data/spec/dummy/log/.keep +0 -0
  69. data/spec/dummy/package.json +5 -0
  70. data/spec/dummy/public/404.html +67 -0
  71. data/spec/dummy/public/422.html +67 -0
  72. data/spec/dummy/public/500.html +66 -0
  73. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  74. data/spec/dummy/public/apple-touch-icon.png +0 -0
  75. data/spec/dummy/public/favicon.ico +0 -0
  76. data/spec/dummy/tmp/.keep +0 -0
  77. data/spec/rails_helper.rb +50 -0
  78. data/spec/spec_helper.rb +4 -1
  79. data/spec/support/.keep +0 -0
  80. data/spec/token_spec.rb +76 -4
  81. metadata +196 -18
  82. data/spec/support/dummy_user.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4fc903bec961f43790b39851ed465e98ee4db262
4
- data.tar.gz: 2c54dc88944789086ec0ef2cfb11f33b3ec63520
3
+ metadata.gz: 7cd012fc046f4777af5d9ee5f6265f5ca2d62af9
4
+ data.tar.gz: 9170ff259b31aa1867b40da3572db62b4b1af852
5
5
  SHA512:
6
- metadata.gz: 6caaeac87553b3fb5fc3ab08e7c0806cb01ba40cac74e8b11bf739517383687289dd9f157a22b81b9571029c58ff04cc8f499abb6e0059a2f32016d5c05aa13d
7
- data.tar.gz: 89da2604d876f84c21836acfb6cf11e47c3d542a01514ee2d2d6d4b653c5f081f60ce670e1dfb67a3f532f8d3f9ae803af65e9bd3f65b1a19105cee23b62f8e4
6
+ metadata.gz: cee44e1a66ed06d4ecb6298542b45b13c72a2806c271805c2e8772dcab5b755ad4f9cf9c862c8f507a511744fa52c28e600c458b48ef50b555ca6ae1e946afb1
7
+ data.tar.gz: b34a80b8d6bb0f0cf068b4505101edbc9030f96bcccf3bd5b5bcb5ffe55b7e7fd77726177dbb2ac68b3fe1981edf2c68ecdd5a04a54d7b2ff2d2ab9dbb4c8eda
data/.gitignore CHANGED
@@ -1,25 +1,54 @@
1
1
  *.gem
2
2
  *.rbc
3
- .bundle
4
- .config
5
- .yardoc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+ .byebug_history
13
+
14
+ # Used by dotenv library to load environment variables.
15
+ # .env
16
+
17
+ ## Specific to RubyMotion:
18
+ .dat*
19
+ .repl_history
20
+ build/
21
+ *.bridgesupport
22
+ build-iPhoneOS/
23
+ build-iPhoneSimulator/
24
+
25
+ ## Specific to RubyMotion (use of CocoaPods):
26
+ #
27
+ # We recommend against adding the Pods directory to your .gitignore. However
28
+ # you should judge for yourself, the pros and cons are mentioned at:
29
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
30
+ #
31
+ # vendor/Pods/
32
+
33
+ ## Documentation cache and generated files:
34
+ /.yardoc/
35
+ /_yardoc/
36
+ /doc/
37
+ /rdoc/
38
+
39
+ ## Environment normalization:
40
+ /.bundle/
41
+ /vendor/bundle
42
+ /lib/bundler/man/
43
+
44
+ # for a library or gem, you might want to ignore these files since the code is
45
+ # intended to run in multiple environments; otherwise, check them in:
6
46
  Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- *.bundle
19
- *.so
20
- *.o
21
- *.a
22
- mkmf.log
23
47
  .ruby-version
24
48
  .ruby-gemset
49
+
50
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
51
+ .rvmrc
52
+
53
+ # IDE files
25
54
  .idea
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.4.0
4
+ cache:
5
+ bundler: true
6
+ env:
7
+ - RAILS_ENV=test CI=true TRAVIS=true
8
+ install:
9
+ - bundle install
10
+ script:
11
+ - bundle exec rspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # JWT::Auth
1
+ # JWT::Auth [![Travis](https://travis-ci.org/floriandejonckheere/jwt-auth.svg?branch=master)](https://travis-ci.org/floriandejonckheere/jwt-auth) [![Coverage Status](https://coveralls.io/repos/github/floriandejonckheere/jwt-auth/badge.svg)](https://coveralls.io/github/floriandejonckheere/jwt-auth)
2
2
 
3
3
  JWT-based authentication middleware for Rails API without Devise
4
4
 
@@ -6,28 +6,31 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
6
 
7
7
  require 'jwt/auth/version'
8
8
 
9
- Gem::Specification.new do |spec|
10
- spec.name = 'jwt-auth'
11
- spec.version = JWT::Auth::VERSION
12
- spec.authors = ['Florian Dejonckheere']
13
- spec.email = ['florian@floriandejonckheere.be']
14
- spec.summary = 'JWT-based authentication for Rails API without Devise'
15
- spec.description = 'Authentication middleware for Rails API that uses JWTs, without depending on Devise'
16
- spec.homepage = 'https://github.com/floriandejonckheere/jwt-auth'
17
- spec.license = 'MIT'
9
+ Gem::Specification.new do |gem|
10
+ gem.name = 'jwt-auth'
11
+ gem.version = JWT::Auth::VERSION
12
+ gem.authors = ['Florian Dejonckheere']
13
+ gem.email = ['florian@floriandejonckheere.be']
14
+ gem.summary = 'JWT-based authentication for Rails API'
15
+ gem.description = 'Authentication middleware for Rails API that uses JWTs'
16
+ gem.homepage = 'https://github.com/floriandejonckheere/jwt-auth'
17
+ gem.license = 'MIT'
18
18
 
19
- spec.files = `git ls-files -z`.split("\x0")
20
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
- spec.require_paths = ['lib']
19
+ gem.files = `git ls-files -z`.split("\x0")
20
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
+ gem.require_paths = ['lib']
23
23
 
24
- spec.add_dependency 'jwt', '~> 1.5'
25
- spec.add_dependency 'rails', '~> 5.0'
24
+ gem.add_runtime_dependency 'jwt', '~> 1.5'
25
+ gem.add_runtime_dependency 'rails', '~> 5.1'
26
26
 
27
- spec.add_development_dependency 'bundler', '~> 1.14'
28
- spec.add_development_dependency 'rubocop', '~> 0.48'
29
- spec.add_development_dependency 'rake', '~> 12.0'
30
- spec.add_development_dependency 'rspec', '~> 3.5'
31
- spec.add_development_dependency 'rspec-rails', '~> 3.5'
32
- spec.add_development_dependency 'byebug'
27
+ gem.add_development_dependency 'bundler', '~> 1.15'
28
+ gem.add_development_dependency 'rubocop', '~> 0.49'
29
+ gem.add_development_dependency 'rake', '~> 12.0'
30
+ gem.add_development_dependency 'rspec', '~> 3.6'
31
+ gem.add_development_dependency 'rspec-rails', '~> 3.6'
32
+ gem.add_development_dependency 'rdoc', '~> 5.1'
33
+ gem.add_development_dependency 'coveralls', '~> 0.8'
34
+ gem.add_development_dependency 'byebug'
35
+ gem.add_development_dependency 'sqlite3'
33
36
  end
@@ -12,21 +12,21 @@ module JWT
12
12
  # Current user helper
13
13
  #
14
14
  def current_user
15
- jwt&.subject
15
+ jwt && jwt.subject
16
16
  end
17
17
 
18
18
  ##
19
19
  # Authenticate a request
20
20
  #
21
21
  def authenticate_user
22
- raise JWT::Auth::UnauthorizedError unless jwt&.valid?
22
+ raise JWT::Auth::UnauthorizedError unless jwt && jwt.valid?
23
23
  end
24
24
 
25
25
  ##
26
26
  # Add JWT header to response
27
27
  #
28
28
  def renew_token
29
- return unless jwt&.valid?
29
+ return unless jwt && jwt.valid?
30
30
  jwt.renew!
31
31
  response.headers['Authorization'] = "Bearer #{jwt.to_jwt}"
32
32
  end
@@ -13,11 +13,16 @@ module JWT
13
13
  attr_accessor :expiration, :subject, :token_version
14
14
 
15
15
  def valid?
16
+ # Reload subject to prevent caching the old token_version
17
+ subject && subject.reload
18
+
16
19
  return false if subject.nil? || expiration.nil? || token_version.nil?
17
20
  return false if Time.at(expiration).past?
18
21
  return false if token_version != subject.token_version
19
22
 
20
23
  true
24
+ rescue ActiveRecord::RecordNotFound
25
+ false
21
26
  end
22
27
 
23
28
  def renew!
@@ -42,14 +47,20 @@ module JWT
42
47
  end
43
48
 
44
49
  def self.from_token(token)
45
- payload = JWT.decode(token, JWT::Auth.secret).first
50
+ begin
51
+ payload = JWT.decode(token, JWT::Auth.secret).first
52
+ rescue JWT::ExpiredSignature
53
+ payload = {}
54
+ end
46
55
 
47
56
  token = JWT::Auth::Token.new
48
57
  token.expiration = payload['exp']
49
58
  token.token_version = payload['ver']
50
59
 
51
- find_method = JWT::Auth.model.respond_to?(:find_by_token) ? :find_by_token : :find_by
52
- token.subject = JWT::Auth.model.send find_method, :id => payload['sub'], :token_version => payload['ver']
60
+ if payload['sub']
61
+ find_method = JWT::Auth.model.respond_to?(:find_by_token) ? :find_by_token : :find_by
62
+ token.subject = JWT::Auth.model.send find_method, :id => payload['sub'], :token_version => payload['ver']
63
+ end
53
64
 
54
65
  token
55
66
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module JWT
4
4
  module Auth
5
- VERSION = '3.0.0'
5
+ VERSION = '3.0.1'
6
6
  end
7
7
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_listeral: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe AuthenticationController, :type => :request do
6
+ let(:user) { User.create :activated => true }
7
+
8
+ let(:headers) do
9
+ {
10
+ 'Authorization' => "Bearer #{JWT::Auth::Token.from_user(user).to_jwt}"
11
+ }
12
+ end
13
+
14
+ describe 'GET /public' do
15
+ context 'activated user' do
16
+ it 'is accessible without token' do
17
+ get '/public'
18
+
19
+ expect(response.status).to eq 204
20
+ end
21
+
22
+ it 'is accessible with token' do
23
+ get '/public', :headers => headers
24
+
25
+ expect(response.status).to eq 204
26
+ end
27
+
28
+ it 'renews the token' do
29
+ get '/public', :headers => headers
30
+
31
+ jwt = response.headers['Authorization'].scan(/Bearer (.*)$/).flatten.last
32
+ token = JWT::Auth::Token.from_token jwt
33
+
34
+ expect(token).to be_valid
35
+ end
36
+ end
37
+
38
+ context 'disabled user' do
39
+ let(:user) { User.new }
40
+
41
+ it 'is accessible without token' do
42
+ get '/public'
43
+
44
+ expect(response.status).to eq 204
45
+ end
46
+
47
+ it 'is accessible with token' do
48
+ get '/public', :headers => headers
49
+
50
+ expect(response.status).to eq 204
51
+ end
52
+ end
53
+ end
54
+
55
+ describe 'GET /private' do
56
+ context 'activated user' do
57
+ it 'is not accessible without token' do
58
+ get '/private'
59
+
60
+ expect(response.status).to eq 401
61
+ end
62
+
63
+ it 'is accessible with token' do
64
+ get '/private', :headers => headers
65
+
66
+ expect(response.status).to eq 204
67
+ end
68
+
69
+ it 'renews the token' do
70
+ get '/private', :headers => headers
71
+
72
+ jwt = response.headers['Authorization'].scan(/Bearer (.*)$/).flatten.last
73
+ token = JWT::Auth::Token.from_token jwt
74
+
75
+ expect(token).to be_valid
76
+ end
77
+ end
78
+
79
+ context 'disabled user' do
80
+ let(:user) { User.new }
81
+
82
+ it 'is not accessible without token' do
83
+ get '/private'
84
+
85
+ expect(response.status).to eq 401
86
+ end
87
+
88
+ it 'is not accessible with token' do
89
+ get '/private', :headers => headers
90
+
91
+ expect(response.status).to eq 401
92
+ end
93
+ end
94
+ end
95
+ end
@@ -13,6 +13,6 @@ RSpec.describe JWT::Auth do
13
13
 
14
14
  expect(subject.token_lifetime).to eq 24.hours
15
15
  expect(subject.secret).to eq 'mysecret'
16
- expect(subject.model).to eq DummyUser
16
+ expect(subject.model).to eq User
17
17
  end
18
18
  end
@@ -0,0 +1,41 @@
1
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+ /.gem
10
+
11
+ # Ignore the default SQLite database.
12
+ /db/*.sqlite3
13
+ /db/*.sqlite3-journal
14
+
15
+ # Ignore all logfiles and tempfiles.
16
+ /log/*
17
+ /tmp/*
18
+ !/log/.keep
19
+ !/tmp/.keep
20
+
21
+ # Ignore Byebug command history file.
22
+ .byebug_history
23
+
24
+ # IDE files
25
+ .idea
26
+
27
+ # Webpack files
28
+ node_modules
29
+ /client/public
30
+
31
+ # Private files
32
+ *.env
33
+ config/*.pem
34
+ config/*.pub
35
+
36
+ # Coverage report
37
+ coverage/
38
+
39
+ /.gem
40
+ /.vscode
41
+ .DS_Store
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require_relative 'config/application'
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,4 @@
1
+
2
+ //= link_tree ../images
3
+ //= link_directory ../javascripts .js
4
+ //= link_directory ../stylesheets .css
File without changes
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ // Action Cable provides the framework to deal with WebSockets in Rails.
2
+ // You can generate new channels where WebSocket features live using the `rails generate channel` command.
3
+ //
4
+ //= require action_cable
5
+ //= require_self
6
+ //= require_tree ./channels
7
+
8
+ (function() {
9
+ this.App || (this.App = {});
10
+
11
+ App.cable = ActionCable.createConsumer();
12
+
13
+ }).call(this);
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Channel < ActionCable::Channel::Base
3
+ end
4
+ end