jwt-authenticator 1.0.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a0f3e5579beda1099857bfb7731cf03f9a531f5178289ac89721561f51b9394
4
- data.tar.gz: b4d779f5919c2bcce341e484b720fe995eea90eb4d1dd1f7faa7fde9fa669293
3
+ metadata.gz: 707fad532a2bd87b7ab6a9e7839cd61789d53024a18f7b4849d5fbb6e44eb16c
4
+ data.tar.gz: 8e020e5ca4feac5e69dd276d93d8bce8b17928a75e0e20f2d4743656e33072cd
5
5
  SHA512:
6
- metadata.gz: fc10f802cea4187f46f4c8ef876e8caf11010f8477fa2461d210d75a63cdfda109f711e320b8a4b2e06b7e22f0c86845a2cd4b1ce4f08189648f3e292488eda9
7
- data.tar.gz: 77512700bcc753b7505b82682595baeabc46b50cbff09cf1199ff4fb559e19143d106958f485051b77ed393c2eca1516cec85e84fd6cc734d66c175129e960fd
6
+ metadata.gz: c4868783d0751eeeda6c5e4c7ecab2f5b9c36f4b61881d82332b3bdd20e10a683265a4f9e8c05bc671ab4951e2dd7f25a91441e4f6ce6f438f6209c1ce548b9c
7
+ data.tar.gz: c90110f5b22510a4ce50630dea91a6f2ebb7cf711098f5e6500c27255b31aa8bcb55f734f07fffce52348aeb038eebe43ef0c4358870fcca0c890848343c8e21
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 2.7.3
data/Gemfile.lock CHANGED
@@ -1,41 +1,41 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jwt-authenticator (1.0.0)
4
+ jwt-authenticator (2.0.0)
5
5
  activesupport (>= 4.0, < 6.0)
6
- jwt (~> 2.1.0)
7
- method-not-implemented (~> 1.0.1)
6
+ jwt (~> 2.1)
7
+ method-not-implemented (~> 1.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (5.2.1)
12
+ activesupport (5.2.6)
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
14
  i18n (>= 0.7, < 2)
15
15
  minitest (~> 5.1)
16
16
  tzinfo (~> 1.1)
17
- concurrent-ruby (1.0.5)
18
- i18n (1.1.0)
17
+ concurrent-ruby (1.1.9)
18
+ i18n (1.8.10)
19
19
  concurrent-ruby (~> 1.0)
20
- jwt (2.1.0)
20
+ jwt (2.2.3)
21
21
  method-not-implemented (1.0.1)
22
- minitest (5.11.3)
23
- power_assert (1.1.3)
24
- rake (12.3.1)
25
- test-unit (3.2.8)
22
+ minitest (5.14.4)
23
+ power_assert (2.0.0)
24
+ rake (12.3.3)
25
+ test-unit (3.4.4)
26
26
  power_assert
27
27
  thread_safe (0.3.6)
28
- tzinfo (1.2.5)
28
+ tzinfo (1.2.9)
29
29
  thread_safe (~> 0.1)
30
30
 
31
31
  PLATFORMS
32
32
  ruby
33
33
 
34
34
  DEPENDENCIES
35
- bundler (~> 1.7)
35
+ bundler (>= 1.7, < 3.0)
36
36
  jwt-authenticator!
37
37
  rake (~> 12.3)
38
38
  test-unit (~> 3.2)
39
39
 
40
40
  BUNDLED WITH
41
- 1.16.4
41
+ 2.1.4
@@ -17,8 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
  s.required_ruby_version = "~> 2.5"
19
19
 
20
- s.add_dependency "jwt", "~> 2.1.0"
21
- s.add_dependency "method-not-implemented", "~> 1.0.1"
20
+ s.add_dependency "jwt", "~> 2.1"
21
+ s.add_dependency "method-not-implemented", "~> 1.0"
22
22
  s.add_dependency "activesupport", ">= 4.0", "< 6.0"
23
- s.add_development_dependency "bundler", "~> 1.7"
23
+ s.add_development_dependency "bundler", ">= 1.7", "< 3.0"
24
24
  end
@@ -14,17 +14,23 @@ class JWT::Authenticator
14
14
 
15
15
  def initialize
16
16
  @verification_options = token_verification_options_from_environment \
17
- self.class.name.split("::").first.underscore.upcase.gsub(/_?JWT\z/, "") + "_JWT"
17
+ self.class.name.split("::")[0...-1].join("_").underscore.upcase.gsub(/_?JWT\z/, "") + "_JWT"
18
18
  end
19
19
 
20
20
  def call(token)
21
- error! "Token is missing.", 101 if token.blank?
22
- token_type, token_value = token.to_s.squish.split(" ")
23
- error! "Token type is not provided or invalid.", 102 unless token_type == "Bearer"
24
- returned = JWT.decode(token_value, nil, true, @verification_options) { |header| public_key(header.deep_symbolize_keys) }
21
+ error! type: :token_missing unless token.present?
22
+
23
+ returned = JWT.decode token, nil, true, @verification_options do |header|
24
+ public_key(header.deep_symbolize_keys)
25
+ end
26
+
25
27
  returned.map(&:deep_symbolize_keys)
28
+
29
+ rescue JWT::ExpiredSignature => e
30
+ error! message: e.inspect, type: :token_expired
31
+
26
32
  rescue JWT::DecodeError => e
27
- error!(e.inspect, 103)
33
+ error! message: e.inspect, type: :token_invalid
28
34
  end
29
35
 
30
36
  protected
@@ -33,29 +39,31 @@ protected
33
39
  method_not_implemented
34
40
  end
35
41
 
36
- def token_verification_options_from_environment(prefix)
37
- { verify_expiration: ENV["#{prefix}_VERIFY_EXP"] != "false",
38
- verify_not_before: ENV["#{prefix}_VERIFY_NBF"] != "false",
39
- iss: ENV["#{prefix}_ISS"].to_s.squish.presence,
40
- verify_iat: ENV["#{prefix}_VERIFY_IAT"] != "false",
41
- verify_jti: ENV["#{prefix}_VERIFY_JTI"] != "false",
42
- aud: ENV["#{prefix}_AUD"].to_s.split(",").map(&:squish).reject(&:blank?).presence, # Comma-separated values.
43
- sub: ENV["#{prefix}_SUB"].to_s.squish.presence,
44
- algorithms: ENV["#{prefix}_ALG"].to_s.split(",").map(&:squish).reject(&:blank?).presence, # Comma-separated values.
45
- leeway: ENV["#{prefix}_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? },
46
- iat_leeway: ENV["#{prefix}_IAT_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? },
47
- exp_leeway: ENV["#{prefix}_EXP_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? },
48
- nbf_leeway: ENV["#{prefix}_NBF_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? }
49
- }.tap { |options|
50
- options.merge! \
51
- verify_sub: options[:sub].present?,
52
- verify_iss: options[:iss].present?,
53
- verify_aud: options[:aud].present?
54
- }.compact
42
+ def token_verification_options_from_environment(namespace)
43
+ namespace = namespace.gsub(/_+\z/, "")
44
+ options = {
45
+ verify_expiration: ENV["#{namespace}_VERIFY_EXP"] != "false",
46
+ verify_not_before: ENV["#{namespace}_VERIFY_NBF"] != "false",
47
+ iss: ENV["#{namespace}_ISS"].to_s.split(",").map(&:squish).reject(&:blank?).presence, # Comma-separated values.
48
+ verify_iat: ENV["#{namespace}_VERIFY_IAT"] != "false",
49
+ verify_jti: ENV["#{namespace}_VERIFY_JTI"] != "false",
50
+ aud: ENV["#{namespace}_AUD"].to_s.split(",").map(&:squish).reject(&:blank?).presence, # Comma-separated values.
51
+ sub: ENV["#{namespace}_SUB"].to_s.squish.presence,
52
+ algorithms: ENV["#{namespace}_ALG"].to_s.split(",").map(&:squish).reject(&:blank?).presence, # Comma-separated values.
53
+ leeway: ENV["#{namespace}_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? },
54
+ iat_leeway: ENV["#{namespace}_IAT_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? },
55
+ exp_leeway: ENV["#{namespace}_EXP_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? },
56
+ nbf_leeway: ENV["#{namespace}_NBF_LEEWAY"].to_s.squish.yield_self { |n| n.to_i if n.present? }
57
+ }
58
+ options.merge! \
59
+ verify_sub: options[:sub].present?,
60
+ verify_iss: options[:iss].present?,
61
+ verify_aud: options[:aud].present?
62
+ options.compact
55
63
  end
56
64
 
57
- def error!(message, code = nil)
58
- raise Error.new(message, code)
65
+ def error!(**options)
66
+ raise Error.new(**options)
59
67
  end
60
68
 
61
69
  class << self
@@ -65,11 +73,11 @@ protected
65
73
  end
66
74
 
67
75
  class Error < StandardError
68
- attr_reader :code
76
+ attr_reader :type
69
77
 
70
- def initialize(message, code = nil)
71
- super(message)
72
- @code = code
78
+ def initialize(message: nil, type:)
79
+ super message.presence || type.to_s.humanize
80
+ @type = type
73
81
  end
74
82
  end
75
83
  end
@@ -3,6 +3,6 @@
3
3
 
4
4
  module JWT
5
5
  class Authenticator
6
- VERSION = "1.0.0"
6
+ VERSION = "2.0.0"
7
7
  end
8
8
  end
data/test/helper.rb CHANGED
@@ -40,3 +40,11 @@ module MyAPIv2
40
40
  end
41
41
  end
42
42
  end
43
+
44
+ module MyAPI
45
+ module V3
46
+ class JWTAuthenticator < JWT::Authenticator
47
+
48
+ end
49
+ end
50
+ end
@@ -33,7 +33,7 @@ class JWTAuthenticatorTest < Test::Unit::TestCase
33
33
  end
34
34
 
35
35
  modify_environment "MY_API_V1_JWT_ISS", " foo " do
36
- assert_equal(default.merge(iss: "foo", verify_iss: true), my_api_v1_token_verification_options)
36
+ assert_equal(default.merge(iss: %w[foo], verify_iss: true), my_api_v1_token_verification_options)
37
37
  end
38
38
 
39
39
  modify_environment "MY_API_V1_JWT_VERIFY_IAT", "false" do
@@ -76,13 +76,7 @@ class JWTAuthenticatorTest < Test::Unit::TestCase
76
76
  test "blank token" do
77
77
  error = assert_raises(JWT::Authenticator::Error) { JWT::Authenticator.instance.call(" ") }
78
78
  assert_match(/\bmissing\b/i, error.message)
79
- assert_equal(101, error.code)
80
- end
81
-
82
- test "token with invalid type" do
83
- error = assert_raises(JWT::Authenticator::Error) { JWT::Authenticator.instance.call("Beer XXX.YYY.ZZZ") }
84
- assert_match(/\binvalid\b/i, error.message)
85
- assert_equal(102, error.code)
79
+ assert_equal(:token_missing, error.type)
86
80
  end
87
81
 
88
82
  test "token decoding and verification" do
@@ -96,63 +90,69 @@ class JWTAuthenticatorTest < Test::Unit::TestCase
96
90
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.merge(iss: "qux"))
97
91
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
98
92
  assert_match(/\binvalid issuer\b/i, error.message)
99
- assert_equal(103, error.code)
93
+ assert_equal(:token_invalid, error.type)
100
94
  end
101
95
 
102
96
  test "missing iss" do
103
97
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.tap { |p| p.delete(:iss) })
104
98
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
105
99
  assert_match(/\binvalid issuer\b/i, error.message)
106
- assert_equal(103, error.code)
100
+ assert_equal(:token_invalid, error.type)
107
101
  end
108
102
 
109
103
  test "missing aud" do
110
104
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.tap { |p| p.delete(:aud) })
111
105
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
112
106
  assert_match(/\binvalid audience\b/i, error.message)
113
- assert_equal(103, error.code)
107
+ assert_equal(:token_invalid, error.type)
114
108
  end
115
109
 
116
110
  test "wrong aud" do
117
111
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.merge(aud: "qux"))
118
112
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
119
113
  assert_match(/\binvalid audience\b/i, error.message)
120
- assert_equal(103, error.code)
114
+ assert_equal(:token_invalid, error.type)
121
115
  end
122
116
 
123
117
  test "missing sub" do
124
118
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.tap { |p| p.delete(:sub) })
125
119
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
126
120
  assert_match(/\binvalid subject\b/i, error.message)
127
- assert_equal(103, error.code)
121
+ assert_equal(:token_invalid, error.type)
128
122
  end
129
123
 
130
124
  test "wrong sub" do
131
125
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.merge(sub: "qux"))
132
126
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
133
127
  assert_match(/\binvalid subject\b/i, error.message)
134
- assert_equal(103, error.code)
128
+ assert_equal(:token_invalid, error.type)
135
129
  end
136
130
 
137
131
  test "token is expired" do
138
132
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.merge(exp: Time.now.to_i - 5))
139
133
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
140
134
  assert_match(/\bexpired\b/i, error.message)
141
- assert_equal(103, error.code)
135
+ assert_equal(:token_expired, error.type)
142
136
  end
143
137
 
144
138
  test "missing jti" do
145
139
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.tap { |p| p.delete(:jti) })
146
140
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
147
141
  assert_match(/\bmissing jti\b/i, error.message)
148
- assert_equal(103, error.code)
142
+ assert_equal(:token_invalid, error.type)
149
143
  end
150
144
 
151
145
  test "issued at in future" do
152
146
  jwt = my_api_v2_jwt_encode(my_api_v2_jwt_payload.merge(iat: Time.now.to_i + 30))
153
147
  error = assert_raises(JWT::Authenticator::Error) { my_api_v2_jwt_decode(jwt) }
154
148
  assert_match(/\binvalid iat\b/i, error.message)
155
- assert_equal(103, error.code)
149
+ assert_equal(:token_invalid, error.type)
150
+ end
151
+
152
+ test "loading token verification options from environment (authenticator nested under multiple modules)" do
153
+ ENV["MY_API_V3_JWT_ISS"] = "bar"
154
+ authenticator = MyAPI::V3::JWTAuthenticator.instance
155
+ assert_equal([ENV["MY_API_V3_JWT_ISS"]], authenticator.instance_variable_get(:@verification_options)[:iss])
156
156
  end
157
157
 
158
158
  private
@@ -179,6 +179,6 @@ private
179
179
  end
180
180
 
181
181
  def my_api_v2_jwt_decode(jwt)
182
- MyAPIv2::JWTAuthenticator.call("Bearer " + jwt)
182
+ MyAPIv2::JWTAuthenticator.call(jwt)
183
183
  end
184
184
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt-authenticator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yaroslav Konoplov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-02 00:00:00.000000000 Z
11
+ date: 2021-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.0
19
+ version: '2.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.0
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: method-not-implemented
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.1
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.0.1
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -62,16 +62,22 @@ dependencies:
62
62
  name: bundler
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '1.7'
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '3.0'
68
71
  type: :development
69
72
  prerelease: false
70
73
  version_requirements: !ruby/object:Gem::Requirement
71
74
  requirements:
72
- - - "~>"
75
+ - - ">="
73
76
  - !ruby/object:Gem::Version
74
77
  version: '1.7'
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '3.0'
75
81
  description: The gem provides easy & extendable way to perform JSON Web Token authentication.
76
82
  email: eahome00@gmail.com
77
83
  executables: []
@@ -89,7 +95,7 @@ files:
89
95
  - lib/jwt-authenticator.rb
90
96
  - lib/jwt-authenticator/version.rb
91
97
  - test/helper.rb
92
- - test/jwt-authenticator-test.rb
98
+ - test/test-jwt-authenticator.rb
93
99
  homepage: https://github.com/ruby-jwt/jwt-authenticator
94
100
  licenses:
95
101
  - Apache-2.0
@@ -109,11 +115,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
115
  - !ruby/object:Gem::Version
110
116
  version: '0'
111
117
  requirements: []
112
- rubyforge_project:
113
- rubygems_version: 2.7.6
118
+ rubygems_version: 3.1.6
114
119
  signing_key:
115
120
  specification_version: 4
116
121
  summary: JSON Web Token authentication Ruby service.
117
122
  test_files:
118
123
  - test/helper.rb
119
- - test/jwt-authenticator-test.rb
124
+ - test/test-jwt-authenticator.rb