jwt-rack 0.0.0 → 0.1.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/.gitignore +2 -0
- data/Gemfile +3 -1
- data/README.md +2 -0
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/jwt-rack.gemspec +23 -20
- data/lib/jwt/rack.rb +6 -4
- data/lib/jwt/rack/auth.rb +212 -0
- data/lib/jwt/rack/token.rb +72 -0
- data/lib/jwt/rack/version.rb +4 -2
- metadata +37 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75d32bd64c673a5aac017606f4599fb69dbbff77ff1bd1e2ce24539d1394c4d5
|
4
|
+
data.tar.gz: 602cf6f50f172758e1be322196091e27ccfa1dadb7b50574b2e985e60013edee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5b44a1728ec958adee9246e5e59c37e975683d4bb46c6147c610bd5d0083906c38dc7811182d574ce87b78e747c574c0a4a1582ed1a7e6fd66723168d77bce7
|
7
|
+
data.tar.gz: 65eca4b7d2f3ea28d6e2ad842ed1b71b48c7c8db5834ba675b9c29213da6b258488056e1b403976587f1466160c37411d9c68a41d2e7db9555f3f317d5938743
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'jwt/rack'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +11,5 @@ require "jwt/rack"
|
|
10
11
|
# require "pry"
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start(__FILE__)
|
data/jwt-rack.gemspec
CHANGED
@@ -1,41 +1,44 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
5
|
+
require 'jwt/rack/version'
|
4
6
|
|
5
7
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
7
|
-
spec.version =
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
8
|
+
spec.name = 'jwt-rack'
|
9
|
+
spec.version = JWT::Rack::VERSION
|
10
|
+
spec.authors = ['Yaroslav Savchuk']
|
11
|
+
spec.email = ['savchukyarpolk@gmail.com']
|
10
12
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.summary = 'Rack middleware that provides authentication based on JSON Web Tokens.'
|
14
|
+
spec.description = 'Rack middleware that provides authentication based on JSON Web Tokens.'
|
15
|
+
spec.homepage = 'https://github.com/ysv/jwt-rack'
|
16
|
+
spec.license = 'MIT'
|
15
17
|
|
16
|
-
spec.metadata[
|
17
|
-
spec.metadata[
|
18
|
-
spec.metadata[
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = 'https://github.com/ysv/jwt-rack'
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/ysv/jwt-rack/blob/master/CHANGELOG.md'
|
19
21
|
|
20
22
|
# Specify which files should be added to the gem when it is released.
|
21
23
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
-
spec.files
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
25
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
26
|
end
|
25
|
-
spec.bindir =
|
27
|
+
spec.bindir = 'exe'
|
26
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
-
spec.require_paths = [
|
29
|
+
spec.require_paths = ['lib']
|
28
30
|
|
29
31
|
spec.platform = Gem::Platform::RUBY
|
30
32
|
spec.required_ruby_version = '>= 2.3.8'
|
31
33
|
|
32
|
-
spec.add_development_dependency 'bundler',
|
33
|
-
spec.add_development_dependency '
|
34
|
+
spec.add_development_dependency 'bundler', '>= 1.16.2'
|
35
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.7'
|
34
36
|
spec.add_development_dependency 'rack-test', '>= 1.0.0'
|
37
|
+
spec.add_development_dependency 'rake', '>= 12.0.0'
|
38
|
+
spec.add_development_dependency 'rbnacl', '>= 6.0.1'
|
35
39
|
spec.add_development_dependency 'rspec', '>= 3.8.0'
|
36
40
|
spec.add_development_dependency 'simplecov', '>= 0.16.0'
|
37
|
-
spec.add_development_dependency 'rbnacl', '>= 6.0.1'
|
38
41
|
|
42
|
+
spec.add_runtime_dependency 'jwt', '~> 2.1.0'
|
39
43
|
spec.add_runtime_dependency 'rack'
|
40
|
-
spec.add_runtime_dependency 'jwt', '~> 2.1.0'
|
41
44
|
end
|
data/lib/jwt/rack.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'jwt/rack/version'
|
4
|
+
|
5
|
+
module JWT
|
4
6
|
module Rack
|
5
|
-
|
6
|
-
|
7
|
+
autoload :Auth, 'jwt/rack/auth'
|
8
|
+
autoload :Token, 'jwt/rack/token'
|
7
9
|
end
|
8
10
|
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jwt'
|
4
|
+
|
5
|
+
module JWT
|
6
|
+
module Rack
|
7
|
+
# Authentication middleware
|
8
|
+
class Auth
|
9
|
+
attr_reader :secret
|
10
|
+
attr_reader :verify
|
11
|
+
attr_reader :options
|
12
|
+
attr_reader :exclude
|
13
|
+
|
14
|
+
SUPPORTED_ALGORITHMS = [
|
15
|
+
'none',
|
16
|
+
'HS256',
|
17
|
+
'HS384',
|
18
|
+
'HS512',
|
19
|
+
'RS256',
|
20
|
+
'RS384',
|
21
|
+
'RS512',
|
22
|
+
'ES256',
|
23
|
+
'ES384',
|
24
|
+
'ES512',
|
25
|
+
('ED25519' if defined?(RbNaCl))
|
26
|
+
].compact.freeze
|
27
|
+
|
28
|
+
DEFAULT_ALGORITHM = 'HS256'
|
29
|
+
|
30
|
+
# The last segment gets dropped for 'none' algorithm since there is no
|
31
|
+
# signature so both of these patterns are valid. All character chunks
|
32
|
+
# are base64url format and periods.
|
33
|
+
# Bearer abc123.abc123.abc123
|
34
|
+
# Bearer abc123.abc123.
|
35
|
+
BEARER_TOKEN_REGEX = %r{
|
36
|
+
^Bearer\s{1}( # starts with Bearer and a single space
|
37
|
+
[a-zA-Z0-9\-\_]+\. # 1 or more chars followed by a single period
|
38
|
+
[a-zA-Z0-9\-\_]+\. # 1 or more chars followed by a single period
|
39
|
+
[a-zA-Z0-9\-\_]* # 0 or more chars, no trailing chars
|
40
|
+
)$
|
41
|
+
}x.freeze
|
42
|
+
|
43
|
+
JWT_DECODE_ERRORS = [
|
44
|
+
::JWT::DecodeError,
|
45
|
+
::JWT::VerificationError,
|
46
|
+
::JWT::ExpiredSignature,
|
47
|
+
::JWT::IncorrectAlgorithm,
|
48
|
+
::JWT::ImmatureSignature,
|
49
|
+
::JWT::InvalidIssuerError,
|
50
|
+
::JWT::InvalidIatError,
|
51
|
+
::JWT::InvalidAudError,
|
52
|
+
::JWT::InvalidSubError,
|
53
|
+
::JWT::InvalidJtiError,
|
54
|
+
::JWT::InvalidPayload
|
55
|
+
].freeze
|
56
|
+
|
57
|
+
MissingAuthHeader = Class.new(StandardError)
|
58
|
+
InvalidAuthHeaderFormat = Class.new(StandardError)
|
59
|
+
|
60
|
+
ERRORS_TO_RESCUE = (JWT_DECODE_ERRORS + [MissingAuthHeader, InvalidAuthHeaderFormat]).freeze
|
61
|
+
|
62
|
+
# Initialization should fail fast with an ArgumentError
|
63
|
+
# if any args are invalid.
|
64
|
+
def initialize(app, opts = {})
|
65
|
+
@app = app
|
66
|
+
@secret = opts.fetch(:secret, nil)
|
67
|
+
@verify = opts.fetch(:verify, true)
|
68
|
+
@options = opts.fetch(:options, {})
|
69
|
+
@exclude = opts.fetch(:exclude, [])
|
70
|
+
|
71
|
+
@on_error = opts.fetch(:on_error, method(:default_on_error))
|
72
|
+
|
73
|
+
@secret = @secret.strip if @secret.is_a?(String)
|
74
|
+
@options[:algorithm] = DEFAULT_ALGORITHM if @options[:algorithm].nil?
|
75
|
+
|
76
|
+
check_secret_type!
|
77
|
+
check_secret!
|
78
|
+
check_secret_and_verify_for_none_alg!
|
79
|
+
check_verify_type!
|
80
|
+
check_options_type!
|
81
|
+
check_valid_algorithm!
|
82
|
+
check_exclude_type!
|
83
|
+
check_on_error_callable!
|
84
|
+
end
|
85
|
+
|
86
|
+
def call(env)
|
87
|
+
if path_matches_excluded_path?(env)
|
88
|
+
@app.call(env)
|
89
|
+
else
|
90
|
+
verify_token(env)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def verify_token(env)
|
97
|
+
raise MissingAuthHeader if missing_auth_header?(env)
|
98
|
+
raise InvalidAuthHeaderFormat if invalid_auth_header?(env)
|
99
|
+
|
100
|
+
# extract the token from the Authorization: Bearer header
|
101
|
+
# with a regex capture group.
|
102
|
+
token = BEARER_TOKEN_REGEX.match(env['HTTP_AUTHORIZATION'])[1]
|
103
|
+
|
104
|
+
decoded_token = Token.decode(token, @secret, @verify, @options)
|
105
|
+
env['jwt.payload'] = decoded_token.first
|
106
|
+
env['jwt.header'] = decoded_token.last
|
107
|
+
@app.call(env)
|
108
|
+
rescue *ERRORS_TO_RESCUE => e
|
109
|
+
@on_error.call(e)
|
110
|
+
end
|
111
|
+
|
112
|
+
def check_secret_type!
|
113
|
+
unless Token.secret_of_valid_type?(@secret)
|
114
|
+
raise ArgumentError, 'secret argument must be a valid type'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_secret!
|
119
|
+
if @secret.nil? || (@secret.is_a?(String) && @secret.empty?)
|
120
|
+
unless @options[:algorithm] == 'none'
|
121
|
+
raise ArgumentError, 'secret argument can only be nil/empty for the "none" algorithm'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def check_secret_and_verify_for_none_alg!
|
127
|
+
if @options && @options[:algorithm] && @options[:algorithm] == 'none'
|
128
|
+
unless @secret.nil? && @verify.is_a?(FalseClass)
|
129
|
+
raise ArgumentError, 'when "none" the secret must be "nil" and verify "false"'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def check_verify_type!
|
135
|
+
unless verify.is_a?(TrueClass) || verify.is_a?(FalseClass)
|
136
|
+
raise ArgumentError, 'verify argument must be true or false'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def check_options_type!
|
141
|
+
raise ArgumentError, 'options argument must be a Hash' unless options.is_a?(Hash)
|
142
|
+
end
|
143
|
+
|
144
|
+
def check_valid_algorithm!
|
145
|
+
unless @options &&
|
146
|
+
@options[:algorithm] &&
|
147
|
+
SUPPORTED_ALGORITHMS.include?(@options[:algorithm])
|
148
|
+
raise ArgumentError, 'algorithm argument must be a supported type'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def check_exclude_type!
|
153
|
+
raise ArgumentError, 'exclude argument must be an Array' unless @exclude.is_a?(Array)
|
154
|
+
|
155
|
+
@exclude.each do |x|
|
156
|
+
raise ArgumentError, 'each exclude Array element must be a String' unless x.is_a?(String)
|
157
|
+
|
158
|
+
raise ArgumentError, 'each exclude Array element must not be empty' if x.empty?
|
159
|
+
|
160
|
+
unless x.start_with?('/')
|
161
|
+
raise ArgumentError, 'each exclude Array element must start with a /'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def check_on_error_callable!
|
167
|
+
unless @on_error.respond_to?(:call)
|
168
|
+
raise ArgumentError, 'on_error argument must respond to call'
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def path_matches_excluded_path?(env)
|
173
|
+
@exclude.any? { |ex| env['PATH_INFO'].start_with?(ex) }
|
174
|
+
end
|
175
|
+
|
176
|
+
def valid_auth_header?(env)
|
177
|
+
env['HTTP_AUTHORIZATION'] =~ BEARER_TOKEN_REGEX
|
178
|
+
end
|
179
|
+
|
180
|
+
def invalid_auth_header?(env)
|
181
|
+
!valid_auth_header?(env)
|
182
|
+
end
|
183
|
+
|
184
|
+
def missing_auth_header?(env)
|
185
|
+
env['HTTP_AUTHORIZATION'].nil? || env['HTTP_AUTHORIZATION'].strip.empty?
|
186
|
+
end
|
187
|
+
|
188
|
+
def default_on_error(error)
|
189
|
+
error_message = {
|
190
|
+
::JWT::DecodeError => 'Invalid JWT token : Decode Error',
|
191
|
+
::JWT::VerificationError => 'Invalid JWT token : Signature Verification Error',
|
192
|
+
::JWT::ExpiredSignature => 'Invalid JWT token : Expired Signature (exp)',
|
193
|
+
::JWT::IncorrectAlgorithm => 'Invalid JWT token : Incorrect Key Algorithm',
|
194
|
+
::JWT::ImmatureSignature => 'Invalid JWT token : Immature Signature (nbf)',
|
195
|
+
::JWT::InvalidIssuerError => 'Invalid JWT token : Invalid Issuer (iss)',
|
196
|
+
::JWT::InvalidIatError => 'Invalid JWT token : Invalid Issued At (iat)',
|
197
|
+
::JWT::InvalidAudError => 'Invalid JWT token : Invalid Audience (aud)',
|
198
|
+
::JWT::InvalidSubError => 'Invalid JWT token : Invalid Subject (sub)',
|
199
|
+
::JWT::InvalidJtiError => 'Invalid JWT token : Invalid JWT ID (jti)',
|
200
|
+
::JWT::InvalidPayload => 'Invalid JWT token : Invalid Payload',
|
201
|
+
MissingAuthHeader => 'Missing Authorization header',
|
202
|
+
InvalidAuthHeaderFormat => 'Invalid Authorization header format'
|
203
|
+
}
|
204
|
+
message = error_message.fetch(error.class)
|
205
|
+
body = { error: message }.to_json
|
206
|
+
headers = { 'Content-Type' => 'application/json', 'Content-Length' => body.bytesize.to_s }
|
207
|
+
|
208
|
+
[401, headers, [body]]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JWT
|
4
|
+
module Rack
|
5
|
+
# Token encoding and decoding
|
6
|
+
class Token
|
7
|
+
# abc123.abc123.abc123 (w/ signature)
|
8
|
+
# abc123.abc123. ('none')
|
9
|
+
TOKEN_REGEX = /\A([a-zA-Z0-9\-\_\~\+\\]+\.[a-zA-Z0-9\-\_\~\+\\]+\.[a-zA-Z0-9\-\_\~\+\\]*)\z/.freeze
|
10
|
+
DEFAULT_HEADERS = { typ: 'JWT' }.freeze
|
11
|
+
|
12
|
+
def self.encode(payload, secret, alg = 'HS256')
|
13
|
+
raise 'Invalid payload. Must be a Hash.' unless payload.is_a?(Hash)
|
14
|
+
raise 'Invalid secret type.' unless secret_of_valid_type?(secret)
|
15
|
+
raise 'Unsupported algorithm' unless algorithm_supported?(alg)
|
16
|
+
|
17
|
+
# if using an unsigned token ('none' alg) you *must* set the `secret`
|
18
|
+
# to `nil` in which case any user provided `secret` will be ignored.
|
19
|
+
if alg == 'none'
|
20
|
+
::JWT.encode(payload, nil, alg, DEFAULT_HEADERS)
|
21
|
+
else
|
22
|
+
::JWT.encode(payload, secret, alg, DEFAULT_HEADERS)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.decode(token, secret, verify, options = {})
|
27
|
+
raise 'Invalid token format.' unless valid_token_format?(token)
|
28
|
+
raise 'Invalid secret type.' unless secret_of_valid_type?(secret)
|
29
|
+
raise 'Unsupported verify value.' unless verify_of_valid_type?(verify)
|
30
|
+
|
31
|
+
options[:algorithm] = 'HS256' if options[:algorithm].nil?
|
32
|
+
raise 'Unsupported algorithm' unless algorithm_supported?(options[:algorithm])
|
33
|
+
|
34
|
+
# If using an unsigned 'none' algorithm token you *must* set the
|
35
|
+
# `secret` to `nil` and `verify` to `false` or it won't work per
|
36
|
+
# the ruby-jwt docs. Using 'none' is probably not recommended.
|
37
|
+
if options[:algorithm] == 'none'
|
38
|
+
::JWT.decode(token, nil, false, options)
|
39
|
+
else
|
40
|
+
::JWT.decode(token, secret, verify, options)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.secret_of_valid_type?(secret)
|
45
|
+
secret.nil? ||
|
46
|
+
secret.is_a?(String) ||
|
47
|
+
secret.is_a?(OpenSSL::PKey::RSA) ||
|
48
|
+
secret.is_a?(OpenSSL::PKey::EC) ||
|
49
|
+
(defined?(RbNaCl) && secret.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)) ||
|
50
|
+
(defined?(RbNaCl) && secret.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Private Utility Class Methods
|
54
|
+
# See : https://gist.github.com/Integralist/bb8760d11a03c88da151
|
55
|
+
|
56
|
+
def self.valid_token_format?(token)
|
57
|
+
token =~ TOKEN_REGEX
|
58
|
+
end
|
59
|
+
private_class_method :valid_token_format?
|
60
|
+
|
61
|
+
def self.algorithm_supported?(alg)
|
62
|
+
JWT::Rack::Auth::SUPPORTED_ALGORITHMS.include?(alg)
|
63
|
+
end
|
64
|
+
private_class_method :algorithm_supported?
|
65
|
+
|
66
|
+
def self.verify_of_valid_type?(verify)
|
67
|
+
verify.nil? || verify.is_a?(FalseClass) || verify.is_a?(TrueClass)
|
68
|
+
end
|
69
|
+
private_class_method :verify_of_valid_type?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/jwt/rack/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt-rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yaroslav Savchuk
|
@@ -25,19 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.16.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: pry-byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '3.7'
|
34
34
|
type: :development
|
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:
|
40
|
+
version: '3.7'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rack-test
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,61 +53,61 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.0.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 12.0.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 12.0.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rbnacl
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 6.0.1
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 6.0.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 3.8.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 3.8.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: simplecov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
104
|
-
type: :
|
103
|
+
version: 0.16.0
|
104
|
+
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 0.16.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: jwt
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 2.1.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rack
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
description: Rack middleware that provides authentication based on JSON Web Tokens.
|
126
140
|
email:
|
127
141
|
- savchukyarpolk@gmail.com
|
@@ -141,6 +155,8 @@ files:
|
|
141
155
|
- bin/setup
|
142
156
|
- jwt-rack.gemspec
|
143
157
|
- lib/jwt/rack.rb
|
158
|
+
- lib/jwt/rack/auth.rb
|
159
|
+
- lib/jwt/rack/token.rb
|
144
160
|
- lib/jwt/rack/version.rb
|
145
161
|
homepage: https://github.com/ysv/jwt-rack
|
146
162
|
licenses:
|
@@ -164,7 +180,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
180
|
- !ruby/object:Gem::Version
|
165
181
|
version: '0'
|
166
182
|
requirements: []
|
167
|
-
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 2.7.8
|
168
185
|
signing_key:
|
169
186
|
specification_version: 4
|
170
187
|
summary: Rack middleware that provides authentication based on JSON Web Tokens.
|