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 +4 -4
- data/.ruby-version +1 -1
- data/Gemfile.lock +14 -14
- data/jwt-authenticator.gemspec +3 -3
- data/lib/jwt-authenticator.rb +39 -31
- data/lib/jwt-authenticator/version.rb +1 -1
- data/test/helper.rb +8 -0
- data/test/{jwt-authenticator-test.rb → test-jwt-authenticator.rb} +18 -18
- metadata +17 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 707fad532a2bd87b7ab6a9e7839cd61789d53024a18f7b4849d5fbb6e44eb16c
|
4
|
+
data.tar.gz: 8e020e5ca4feac5e69dd276d93d8bce8b17928a75e0e20f2d4743656e33072cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4868783d0751eeeda6c5e4c7ecab2f5b9c36f4b61881d82332b3bdd20e10a683265a4f9e8c05bc671ab4951e2dd7f25a91441e4f6ce6f438f6209c1ce548b9c
|
7
|
+
data.tar.gz: c90110f5b22510a4ce50630dea91a6f2ebb7cf711098f5e6500c27255b31aa8bcb55f734f07fffce52348aeb038eebe43ef0c4358870fcca0c890848343c8e21
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7.3
|
data/Gemfile.lock
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
jwt-authenticator (
|
4
|
+
jwt-authenticator (2.0.0)
|
5
5
|
activesupport (>= 4.0, < 6.0)
|
6
|
-
jwt (~> 2.1
|
7
|
-
method-not-implemented (~> 1.0
|
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.
|
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.
|
18
|
-
i18n (1.
|
17
|
+
concurrent-ruby (1.1.9)
|
18
|
+
i18n (1.8.10)
|
19
19
|
concurrent-ruby (~> 1.0)
|
20
|
-
jwt (2.
|
20
|
+
jwt (2.2.3)
|
21
21
|
method-not-implemented (1.0.1)
|
22
|
-
minitest (5.
|
23
|
-
power_assert (
|
24
|
-
rake (12.3.
|
25
|
-
test-unit (3.
|
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.
|
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 (
|
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.
|
41
|
+
2.1.4
|
data/jwt-authenticator.gemspec
CHANGED
@@ -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
|
21
|
-
s.add_dependency "method-not-implemented", "~> 1.0
|
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", "
|
23
|
+
s.add_development_dependency "bundler", ">= 1.7", "< 3.0"
|
24
24
|
end
|
data/lib/jwt-authenticator.rb
CHANGED
@@ -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("::").
|
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!
|
22
|
-
|
23
|
-
|
24
|
-
|
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!
|
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(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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!(
|
58
|
-
raise Error.new(
|
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 :
|
76
|
+
attr_reader :type
|
69
77
|
|
70
|
-
def initialize(message,
|
71
|
-
super
|
72
|
-
@
|
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
|
data/test/helper.rb
CHANGED
@@ -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:
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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:
|
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:
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
124
|
+
- test/test-jwt-authenticator.rb
|