rack-json_web_token_auth 0.1.1 → 0.2.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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +43 -4
- data/lib/rack/json_web_token_auth.rb +75 -71
- data/lib/rack/json_web_token_auth/contracts.rb +17 -41
- data/lib/rack/json_web_token_auth/exceptions.rb +6 -0
- data/lib/rack/json_web_token_auth/resource.rb +43 -25
- data/lib/rack/json_web_token_auth/resources.rb +5 -5
- data/lib/rack/json_web_token_auth/version.rb +1 -1
- metadata +3 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ae3fd49effa85dae53d4098b01beabf1245a418
|
4
|
+
data.tar.gz: cf8334ffaef3a34d486e32de2716ceadec47c010
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6a071a87d21bc42583a465759c8568242a8af10f45eb1bd77c0a75e4e9f11c5570349a2a5bc4376d3dd8c807a3d38bcf4506df67a66ea69cdd15493cb797029
|
7
|
+
data.tar.gz: a8c0137beaa370ec6fe38969ef1a5919a13a87be8adec836ca6e3a613342c797e2140e6cd0f059339f9b72e89cc46219986169ace4866a61d04364294760feaf
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Rack::JsonWebTokenAuth
|
2
2
|
|
3
|
+
[](https://travis-ci.org/grempe/rack-json_web_token_auth)
|
4
|
+
[](https://codeclimate.com/github/grempe/rack-json_web_token_auth)
|
5
|
+
|
3
6
|
## WARNING
|
4
7
|
|
5
8
|
This is pre-release software. It is pretty well tested but has not yet
|
@@ -104,18 +107,25 @@ incoming tokens. The available claims are processed by the [garyf/jwt_claims](ht
|
|
104
107
|
claims can be found in the README for that project. At a minimum a `:key` must
|
105
108
|
be provided except if the `none` algorithm is being used (probably not recommended).
|
106
109
|
|
110
|
+
For `secured` resources you can optionally also pass in a `:methods` option,
|
111
|
+
which specifies an array of HTTP methods that are allowed for the specified `resource`.
|
112
|
+
One or more of `[:any, :get, :head, :post, :put, :patch, :delete, :options]`
|
113
|
+
can be provided. If the `:any` option is desired it must be the only option provided.
|
114
|
+
|
107
115
|
Configuration directives are processed in the order that you provide and requests
|
108
|
-
match against the first path match
|
116
|
+
match against the **first path match**. For this reason you should probably put your
|
109
117
|
`unsecured` resources first and order all resources from most specific to least
|
110
|
-
specific.
|
118
|
+
specific. If multiple resources with the same path are configured, but with different
|
119
|
+
options, only the first resource matched will be used to test the request, all
|
120
|
+
others will be ignored.
|
111
121
|
|
112
122
|
The DSL was heavily inspired by the [rack-cors](https://github.com/cyu/rack-cors)
|
113
|
-
gem
|
123
|
+
gem.
|
114
124
|
|
115
125
|
```ruby
|
116
126
|
require 'rack/json_web_token_auth'
|
117
127
|
|
118
|
-
# Sinatra `use` syntax
|
128
|
+
# Sinatra style Rack middleware `use` syntax
|
119
129
|
use Rack::JsonWebTokenAuth do
|
120
130
|
|
121
131
|
# You can define JWT options for all `secured` resources globally
|
@@ -170,6 +180,35 @@ use Rack::JsonWebTokenAuth do
|
|
170
180
|
resource '/another/path', jwt: {key: 'a long random key', alg: 'HS512'}
|
171
181
|
end
|
172
182
|
|
183
|
+
# You can get very granular by specifying that a resource can only be accessed
|
184
|
+
# when requested with certain HTTP methods. The default for any resource is
|
185
|
+
# to allow HTTP `GET` requests only. You need to pass in a :methods array if
|
186
|
+
# you want to expose additional methods.
|
187
|
+
#
|
188
|
+
# The available choices are:
|
189
|
+
# [:any, :get, :head, :post, :put, :patch, :delete, :options]
|
190
|
+
#
|
191
|
+
# If you try to specify :methods on an `unsecured` resource it will throw
|
192
|
+
# an exception.
|
193
|
+
secured do
|
194
|
+
# GET only
|
195
|
+
resource '/http_get_only', jwt: jwt_opts, methods: [:get]
|
196
|
+
|
197
|
+
# GET or POST
|
198
|
+
resource '/http_post_or_get', jwt: jwt_opts, methods: [:get, :post]
|
199
|
+
|
200
|
+
# ANY HTTP method allowed
|
201
|
+
resource '/http_any', jwt: jwt_opts, methods: [:any]
|
202
|
+
|
203
|
+
# ANY HTTP method allowed (alternate)
|
204
|
+
# This is the same as [:any]
|
205
|
+
resource '/http_any_manual', jwt: jwt_opts, methods: [:get, :head, :post, :put, :patch, :delete, :options]
|
206
|
+
|
207
|
+
# IGNORED! This resource path was already defined above!
|
208
|
+
# Even though it has different methods allowed it will be ignored.
|
209
|
+
resource '/http_post_or_get', jwt: jwt_opts, methods: [:post]
|
210
|
+
end
|
211
|
+
|
173
212
|
# You can have more than one `unsecured` or `secured` block if you like.
|
174
213
|
unsecured do
|
175
214
|
# WARNING : this resource will never be used since it is masked
|
@@ -3,30 +3,28 @@ require 'contracts'
|
|
3
3
|
require 'hashie'
|
4
4
|
require 'jwt_claims'
|
5
5
|
|
6
|
+
require 'rack/json_web_token_auth/exceptions'
|
6
7
|
require 'rack/json_web_token_auth/contracts'
|
7
8
|
require 'rack/json_web_token_auth/resources'
|
8
9
|
require 'rack/json_web_token_auth/resource'
|
9
10
|
|
10
11
|
module Rack
|
11
|
-
# Custom error class
|
12
|
-
class TokenError < StandardError; end
|
13
|
-
|
14
12
|
# Rack Middleware for JSON Web Token Authentication
|
15
13
|
class JsonWebTokenAuth
|
16
14
|
include Contracts::Core
|
17
|
-
|
15
|
+
include Contracts::Builtin
|
18
16
|
|
19
17
|
ENV_KEY = 'jwt.claims'.freeze
|
20
18
|
PATH_INFO_HEADER_KEY = 'PATH_INFO'.freeze
|
21
19
|
|
22
|
-
Contract
|
20
|
+
Contract Any, Proc => Any
|
23
21
|
def initialize(app, &block)
|
24
22
|
@app = app
|
25
23
|
# execute the block methods provided in the context of this class
|
26
24
|
instance_eval(&block)
|
27
25
|
end
|
28
26
|
|
29
|
-
Contract Proc =>
|
27
|
+
Contract Proc => ArrayOf[Resources]
|
30
28
|
def secured(&block)
|
31
29
|
resources = Resources.new(public_resource: false)
|
32
30
|
# execute the methods in the 'secured' block in the context of
|
@@ -35,7 +33,7 @@ module Rack
|
|
35
33
|
all_resources << resources
|
36
34
|
end
|
37
35
|
|
38
|
-
Contract Proc =>
|
36
|
+
Contract Proc => ArrayOf[Resources]
|
39
37
|
def unsecured(&block)
|
40
38
|
resources = Resources.new(public_resource: true)
|
41
39
|
# execute the methods in the 'unsecured' block in the context of
|
@@ -46,82 +44,88 @@ module Rack
|
|
46
44
|
|
47
45
|
Contract Hash => RackResponse
|
48
46
|
def call(env)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
raise TokenError, 'malformed Authorization header or token'
|
65
|
-
end
|
66
|
-
|
67
|
-
# Extract the token from the 'Authorization: Bearer token' string
|
68
|
-
token = BEARER_TOKEN_REGEX.match(env['HTTP_AUTHORIZATION'])[1]
|
69
|
-
|
70
|
-
# Verify the token and its claims are valid
|
71
|
-
jwt_opts = resource.opts[:jwt]
|
72
|
-
jwt = ::JwtClaims.verify(token, jwt_opts)
|
73
|
-
|
74
|
-
# JwtClaims.verify returns a JWT claims set hash, if the
|
75
|
-
# JWT Message Authentication Code (MAC), or signature,
|
76
|
-
# are verified and the registered claims are also verified.
|
77
|
-
if Contract.valid?(jwt, C::HashOf[ok: C::HashOf[Symbol => C::Any]])
|
78
|
-
# Authenticated! Pass all claims into the app env for app use
|
79
|
-
# with the hash keys converted to strings to match Rack env.
|
80
|
-
env[ENV_KEY] = Hashie.stringify_keys(jwt[:ok])
|
81
|
-
elsif Contract.valid?(jwt, C::HashOf[error: C::ArrayOf[Symbol]])
|
82
|
-
# a list of any registered claims that fail validation, if the JWT MAC is verified
|
83
|
-
raise TokenError, "invalid JWT claims : #{jwt[:error].sort.join(', ')}"
|
84
|
-
elsif Contract.valid?(jwt, C::HashOf[error: 'invalid JWT'])
|
85
|
-
# the JWT MAC is not verified
|
86
|
-
raise TokenError, 'invalid JWT'
|
87
|
-
elsif Contract.valid?(jwt, C::HashOf[error: 'invalid input'])
|
88
|
-
# otherwise
|
89
|
-
raise TokenError, 'invalid JWT input'
|
90
|
-
else
|
91
|
-
raise TokenError, 'unhandled JWT error'
|
92
|
-
end
|
93
|
-
|
94
|
-
@app.call(env)
|
47
|
+
resource = resource_for_path(env[PATH_INFO_HEADER_KEY])
|
48
|
+
|
49
|
+
# no matching `secured` or `unsecured` resource.
|
50
|
+
# fail-safe with 401 unauthorized
|
51
|
+
if resource.nil?
|
52
|
+
raise TokenError, 'No resource for path defined. Deny by default.'
|
53
|
+
end
|
54
|
+
|
55
|
+
if resource.public_resource?
|
56
|
+
# whitelisted as `unsecured`. skip all token authentication.
|
57
|
+
@app.call(env)
|
58
|
+
else
|
59
|
+
# HTTP method not permitted
|
60
|
+
if resource.invalid_http_method?(env['REQUEST_METHOD'])
|
61
|
+
raise HttpMethodError, 'HTTP request method denied'
|
95
62
|
end
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
63
|
+
|
64
|
+
# Test that `env` has a well formed Authorization header
|
65
|
+
unless Contract.valid?(env, RackRequestHttpAuth)
|
66
|
+
raise TokenError, 'malformed Authorization header or token'
|
67
|
+
end
|
68
|
+
|
69
|
+
# Extract the token from the 'Authorization: Bearer token' string
|
70
|
+
token = BEARER_TOKEN_REGEX.match(env['HTTP_AUTHORIZATION'])[1]
|
71
|
+
|
72
|
+
# Verify the token and its claims are valid
|
73
|
+
jwt_opts = resource.opts[:jwt]
|
74
|
+
jwt = ::JwtClaims.verify(token, jwt_opts)
|
75
|
+
handle_token(env, jwt)
|
76
|
+
|
77
|
+
@app.call(env)
|
109
78
|
end
|
79
|
+
rescue TokenError => e
|
80
|
+
return_401(e.message)
|
81
|
+
rescue StandardError
|
82
|
+
return_401
|
110
83
|
end
|
111
84
|
|
112
|
-
Contract
|
85
|
+
Contract None => Or[ArrayOf[Resources], []]
|
113
86
|
def all_resources
|
114
87
|
@all_resources ||= []
|
115
88
|
end
|
116
89
|
|
117
|
-
Contract String =>
|
90
|
+
Contract String => Maybe[Resource]
|
118
91
|
def resource_for_path(path_info)
|
119
92
|
all_resources.each do |r|
|
120
|
-
|
121
|
-
|
122
|
-
end
|
93
|
+
found = r.resource_for_path(path_info)
|
94
|
+
return found unless found.nil?
|
123
95
|
end
|
124
96
|
nil
|
125
97
|
end
|
98
|
+
|
99
|
+
Contract String => RackResponse
|
100
|
+
def return_401(msg = nil)
|
101
|
+
body = msg.nil? ? 'Unauthorized' : "Unauthorized : #{msg}"
|
102
|
+
headers = { 'WWW-Authenticate' => 'Bearer error="invalid_token"',
|
103
|
+
'Content-Type' => 'text/plain',
|
104
|
+
'Content-Length' => body.bytesize.to_s }
|
105
|
+
[401, headers, [body]]
|
106
|
+
end
|
107
|
+
|
108
|
+
# JwtClaims.verify returns a JWT claims set hash, if the
|
109
|
+
# JWT Message Authentication Code (MAC), or signature,
|
110
|
+
# are verified and the registered claims are also verified.
|
111
|
+
Contract Hash, Hash => Hash
|
112
|
+
def handle_token(env, jwt)
|
113
|
+
if Contract.valid?(jwt, HashOf[ok: HashOf[Symbol => Any]])
|
114
|
+
# Authenticated! Pass all claims into the app env for app use
|
115
|
+
# with the hash keys converted to strings to match Rack env.
|
116
|
+
env[ENV_KEY] = Hashie.stringify_keys(jwt[:ok])
|
117
|
+
elsif Contract.valid?(jwt, HashOf[error: ArrayOf[Symbol]])
|
118
|
+
# a list of any registered claims that fail validation, if the JWT MAC is verified
|
119
|
+
raise TokenError, "invalid JWT claims : #{jwt[:error].sort.join(', ')}"
|
120
|
+
elsif Contract.valid?(jwt, HashOf[error: 'invalid JWT'])
|
121
|
+
# the JWT MAC is not verified
|
122
|
+
raise TokenError, 'invalid JWT'
|
123
|
+
elsif Contract.valid?(jwt, HashOf[error: 'invalid input'])
|
124
|
+
# otherwise
|
125
|
+
raise TokenError, 'invalid JWT input'
|
126
|
+
else
|
127
|
+
raise TokenError, 'unhandled JWT error'
|
128
|
+
end
|
129
|
+
end
|
126
130
|
end
|
127
131
|
end
|
@@ -1,8 +1,5 @@
|
|
1
1
|
module Rack
|
2
2
|
class JsonWebTokenAuth
|
3
|
-
include Contracts::Core
|
4
|
-
C = Contracts
|
5
|
-
|
6
3
|
# Custom Contracts
|
7
4
|
# See : https://egonschiele.github.io/contracts.ruby/
|
8
5
|
|
@@ -19,76 +16,55 @@ module Rack
|
|
19
16
|
)$
|
20
17
|
}x
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
Contract.valid?(val, ({ 'HTTP_AUTHORIZATION' => BEARER_TOKEN_REGEX }))
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.to_s
|
28
|
-
'A Rack request with JWT auth header'
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class RackResponse
|
19
|
+
# These are Symbols and include the special :any value
|
20
|
+
class ResourceHttpMethods
|
33
21
|
def self.valid?(val)
|
34
|
-
Contract.valid?(val, [
|
22
|
+
Contract.valid?(val, Contracts::ArrayOf[Contracts::Enum[:any, :get, :head, :post, :put, :patch, :delete, :options]])
|
35
23
|
end
|
36
24
|
|
37
25
|
def self.to_s
|
38
|
-
'
|
26
|
+
'An array of allowed HTTP methods for initializing a Resource'
|
39
27
|
end
|
40
28
|
end
|
41
29
|
|
42
|
-
class
|
30
|
+
class HttpMethods
|
43
31
|
def self.valid?(val)
|
44
|
-
|
45
|
-
C::Or[String, OpenSSL::PKey::RSA, OpenSSL::PKey::EC].valid?(val)
|
32
|
+
Contract.valid?(val, Contracts::Enum['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'])
|
46
33
|
end
|
47
34
|
|
48
35
|
def self.to_s
|
49
|
-
'
|
36
|
+
'An array of allowed HTTP methods'
|
50
37
|
end
|
51
38
|
end
|
52
39
|
|
53
|
-
class
|
54
|
-
def self.valid?(val)
|
55
|
-
C::Enum['none', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512'].valid?(val)
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.to_s
|
59
|
-
'A valid JWT token signature algorithm, or none'
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class DecodedToken
|
40
|
+
class RackRequestHttpAuth
|
64
41
|
def self.valid?(val)
|
65
|
-
|
66
|
-
C::DecodedTokenClaims.valid?(val[0]) &&
|
67
|
-
C::DecodedTokenHeader.valid?(val[1])
|
42
|
+
Contract.valid?(val, ({ 'HTTP_AUTHORIZATION' => BEARER_TOKEN_REGEX }))
|
68
43
|
end
|
69
44
|
|
70
45
|
def self.to_s
|
71
|
-
'A
|
46
|
+
'A Rack request with JWT auth header'
|
72
47
|
end
|
73
48
|
end
|
74
49
|
|
75
|
-
class
|
50
|
+
class RackResponse
|
76
51
|
def self.valid?(val)
|
77
|
-
|
52
|
+
Contract.valid?(val, [Contracts::Int, Hash, Contracts::Any])
|
78
53
|
end
|
79
54
|
|
80
55
|
def self.to_s
|
81
|
-
'A
|
56
|
+
'A Rack response'
|
82
57
|
end
|
83
58
|
end
|
84
59
|
|
85
|
-
class
|
60
|
+
class Key
|
86
61
|
def self.valid?(val)
|
87
|
-
|
62
|
+
return false if val.is_a?(String) && val.strip.empty?
|
63
|
+
Contracts::Or[String, OpenSSL::PKey::RSA, OpenSSL::PKey::EC].valid?(val)
|
88
64
|
end
|
89
65
|
|
90
66
|
def self.to_s
|
91
|
-
'A
|
67
|
+
'A JWT secret string or signature key'
|
92
68
|
end
|
93
69
|
end
|
94
70
|
end
|
@@ -2,11 +2,11 @@ module Rack
|
|
2
2
|
class JsonWebTokenAuth
|
3
3
|
class Resource
|
4
4
|
include Contracts::Core
|
5
|
-
|
5
|
+
include Contracts::Builtin
|
6
6
|
|
7
|
-
|
7
|
+
attr_reader :public_resource, :path, :pattern, :methods, :opts
|
8
8
|
|
9
|
-
Contract
|
9
|
+
Contract Bool, String, ({ jwt: Maybe[Hash], methods: Maybe[ResourceHttpMethods] }) => Any
|
10
10
|
def initialize(public_resource, path, opts = {})
|
11
11
|
@public_resource = public_resource
|
12
12
|
@path = path
|
@@ -14,9 +14,14 @@ module Rack
|
|
14
14
|
@opts = opts
|
15
15
|
|
16
16
|
if public_resource
|
17
|
-
# unsecured resources should not have
|
17
|
+
# unsecured resources should not have a :jwt option defined
|
18
18
|
if @opts.key?(:jwt)
|
19
|
-
raise 'unexpected jwt
|
19
|
+
raise 'unexpected :jwt option provided for unsecured resource'
|
20
|
+
end
|
21
|
+
|
22
|
+
# unsecured resources should not have a :methods option defined
|
23
|
+
if @opts.key?(:methods)
|
24
|
+
raise 'unexpected :methods option provided for unsecured resource'
|
20
25
|
end
|
21
26
|
else
|
22
27
|
# secured resources must have a :jwt hash with a :key
|
@@ -24,42 +29,55 @@ module Rack
|
|
24
29
|
Contract.valid?(@opts, ({ jwt: { key: Key } }))
|
25
30
|
raise 'invalid or missing jwt options for secured resource'
|
26
31
|
end
|
32
|
+
|
33
|
+
# Don't allow providing other HTTP methods with :any
|
34
|
+
if opts[:methods] && opts[:methods].include?(:any) && opts[:methods].size > 1
|
35
|
+
raise 'unexpected additional methods provided with :any'
|
36
|
+
end
|
37
|
+
|
38
|
+
@methods = if opts[:methods].nil?
|
39
|
+
[:get]
|
40
|
+
elsif opts[:methods] == [:any]
|
41
|
+
[:get, :head, :post, :put, :patch, :delete, :options]
|
42
|
+
else
|
43
|
+
opts[:methods]
|
44
|
+
end.map { |e| e.to_s }
|
27
45
|
end
|
28
46
|
end
|
29
47
|
|
30
|
-
Contract String =>
|
48
|
+
Contract String => Maybe[Integer]
|
31
49
|
def matches_path?(path)
|
32
50
|
pattern =~ path
|
33
51
|
end
|
34
52
|
|
35
|
-
Contract
|
53
|
+
Contract None => Bool
|
36
54
|
def public_resource?
|
37
55
|
public_resource
|
38
56
|
end
|
39
57
|
|
58
|
+
Contract HttpMethods => Bool
|
59
|
+
def invalid_http_method?(request_method)
|
60
|
+
request_method.nil? || !methods.include?(request_method.downcase)
|
61
|
+
end
|
62
|
+
|
40
63
|
protected
|
41
64
|
|
42
65
|
Contract String => Regexp
|
43
66
|
def compile(path)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
/^#{pattern}$/
|
58
|
-
elsif path.respond_to? :match
|
59
|
-
path
|
60
|
-
else
|
61
|
-
raise TypeError, path
|
67
|
+
special_chars = %w{. + ( )}
|
68
|
+
|
69
|
+
pattern = path.gsub(/([\*#{special_chars.join}])/) do |match|
|
70
|
+
case match
|
71
|
+
when '*'
|
72
|
+
'(.*?)'
|
73
|
+
when *special_chars
|
74
|
+
Regexp.escape(match)
|
75
|
+
else
|
76
|
+
'([^/?&#]+)'
|
77
|
+
end
|
62
78
|
end
|
79
|
+
|
80
|
+
/^#{pattern}$/
|
63
81
|
end
|
64
82
|
end
|
65
83
|
end
|
@@ -4,25 +4,25 @@ module Rack
|
|
4
4
|
class JsonWebTokenAuth
|
5
5
|
class Resources
|
6
6
|
include Contracts::Core
|
7
|
-
|
7
|
+
include Contracts::Builtin
|
8
8
|
|
9
|
-
Contract
|
9
|
+
Contract KeywordArgs[public_resource: Bool] => Any
|
10
10
|
def initialize(public_resource: false)
|
11
11
|
@resources = []
|
12
12
|
@public_resource = public_resource
|
13
13
|
end
|
14
14
|
|
15
|
-
Contract
|
15
|
+
Contract None => Bool
|
16
16
|
def public_resource?
|
17
17
|
@public_resource
|
18
18
|
end
|
19
19
|
|
20
|
-
Contract String,
|
20
|
+
Contract String, Maybe[Hash] => ArrayOf[Resource]
|
21
21
|
def resource(path, opts = {})
|
22
22
|
@resources << Resource.new(public_resource?, path, opts)
|
23
23
|
end
|
24
24
|
|
25
|
-
Contract String =>
|
25
|
+
Contract String => Maybe[Resource]
|
26
26
|
def resource_for_path(path)
|
27
27
|
# return first match
|
28
28
|
@resources.detect { |r| r.matches_path?(path) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-json_web_token_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Glenn Rempe
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
vprF5QiDz8HshVP9DjJT2I1wyGyvxEdU3cTRo0upMP/VZLcgyBVFy90N2XYWWk2D
|
31
31
|
GIxGSw==
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2016-10-
|
33
|
+
date: 2016-10-16 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: contracts
|
@@ -198,6 +198,7 @@ files:
|
|
198
198
|
- README.md
|
199
199
|
- lib/rack/json_web_token_auth.rb
|
200
200
|
- lib/rack/json_web_token_auth/contracts.rb
|
201
|
+
- lib/rack/json_web_token_auth/exceptions.rb
|
201
202
|
- lib/rack/json_web_token_auth/resource.rb
|
202
203
|
- lib/rack/json_web_token_auth/resources.rb
|
203
204
|
- lib/rack/json_web_token_auth/version.rb
|
metadata.gz.sig
CHANGED
Binary file
|