jwt-authenticator 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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