rack-json_web_token_auth 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/grempe/rack-json_web_token_auth.svg?branch=master)](https://travis-ci.org/grempe/rack-json_web_token_auth)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/grempe/rack-json_web_token_auth/badges/gpa.svg)](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
|