jwt-bouncer 0.1.1
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 +7 -0
- data/.gitignore +9 -0
- data/Dockerfile +23 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +59 -0
- data/LICENSE +20 -0
- data/README.md +63 -0
- data/Rakefile +2 -0
- data/bin/bundle +2 -0
- data/bin/console +2 -0
- data/bin/docker/console +7 -0
- data/bin/docker/entrypoint +12 -0
- data/bin/docker/rake +3 -0
- data/bin/rake +2 -0
- data/bin/rspec +2 -0
- data/bin/run +2 -0
- data/docker-compose.yml +14 -0
- data/docs/development.md +9 -0
- data/jwt-bouncer.gemspec +29 -0
- data/lib/jwt_bouncer.rb +8 -0
- data/lib/jwt_bouncer/permissions.rb +46 -0
- data/lib/jwt_bouncer/request.rb +57 -0
- data/lib/jwt_bouncer/sign_request.rb +21 -0
- data/lib/jwt_bouncer/token.rb +21 -0
- data/lib/jwt_bouncer/version.rb +3 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9d0c3be8cdfa58b6baa7ec47c8df5f3a5efc823e
|
4
|
+
data.tar.gz: ebd73773ea8d3feb01635c12a4baa43817e07589
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1fec43fdf1bbf19cebe162727c8ab454ce6f6c1dbc529489f55f11df0da5876f508ead002f1f4ad104bb2fb8806e1b1c75330af45c7ece6259f581d33759f108
|
7
|
+
data.tar.gz: 05af534ca792ae6a2e26621f002b31b4697152671f0edc713d99342dad52426d999edfbee4e9909b6040b91c9c6cd1ed387cd0e099845ab8e31d44255c3461c5
|
data/.gitignore
ADDED
data/Dockerfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
FROM ruby:2.4-slim
|
2
|
+
LABEL maintainer "ryan@ryantownsend.co.uk"
|
3
|
+
|
4
|
+
# Install basic packages
|
5
|
+
RUN apt-get update -qq && apt-get install -y --no-install-recommends \
|
6
|
+
build-essential \
|
7
|
+
curl \
|
8
|
+
git
|
9
|
+
|
10
|
+
# Configure the main working directory
|
11
|
+
ENV app /app
|
12
|
+
RUN mkdir $app
|
13
|
+
WORKDIR $app
|
14
|
+
|
15
|
+
# Set the where to install gems
|
16
|
+
ENV GEM_HOME /rubygems
|
17
|
+
ENV BUNDLE_PATH /rubygems
|
18
|
+
|
19
|
+
# Link the whole application up
|
20
|
+
ADD . $app
|
21
|
+
|
22
|
+
# Ensure our gems are installed when running commands
|
23
|
+
ENTRYPOINT bin/docker/entrypoint $0 $@
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
jwt-bouncer (0.1.0)
|
5
|
+
jwt (~> 1.5, >= 1.5.6)
|
6
|
+
rack (~> 2.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport (5.0.1)
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
+
i18n (~> 0.7)
|
14
|
+
minitest (~> 5.1)
|
15
|
+
tzinfo (~> 1.1)
|
16
|
+
coderay (1.1.1)
|
17
|
+
concurrent-ruby (1.0.4)
|
18
|
+
diff-lcs (1.3)
|
19
|
+
i18n (0.8.1)
|
20
|
+
jwt (1.5.6)
|
21
|
+
method_source (0.8.2)
|
22
|
+
minitest (5.10.1)
|
23
|
+
pry (0.10.4)
|
24
|
+
coderay (~> 1.1.0)
|
25
|
+
method_source (~> 0.8.1)
|
26
|
+
slop (~> 3.4)
|
27
|
+
rack (2.0.1)
|
28
|
+
rake (10.5.0)
|
29
|
+
rspec (3.5.0)
|
30
|
+
rspec-core (~> 3.5.0)
|
31
|
+
rspec-expectations (~> 3.5.0)
|
32
|
+
rspec-mocks (~> 3.5.0)
|
33
|
+
rspec-core (3.5.4)
|
34
|
+
rspec-support (~> 3.5.0)
|
35
|
+
rspec-expectations (3.5.0)
|
36
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
37
|
+
rspec-support (~> 3.5.0)
|
38
|
+
rspec-mocks (3.5.0)
|
39
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
40
|
+
rspec-support (~> 3.5.0)
|
41
|
+
rspec-support (3.5.0)
|
42
|
+
slop (3.6.0)
|
43
|
+
thread_safe (0.3.5)
|
44
|
+
tzinfo (1.2.2)
|
45
|
+
thread_safe (~> 0.1)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
activesupport (~> 5.0, >= 5.0.1)
|
52
|
+
bundler (~> 1.14)
|
53
|
+
jwt-bouncer!
|
54
|
+
pry (~> 0.10)
|
55
|
+
rake (~> 10.0)
|
56
|
+
rspec (~> 3.5)
|
57
|
+
|
58
|
+
BUNDLED WITH
|
59
|
+
1.14.3
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Shift Commerce Ltd
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
[](https://jwt.io/)
|
2
|
+
|
3
|
+
JwtBouncer is an abstraction for JWT-based authentication/authorisation.
|
4
|
+
|
5
|
+
### Usage
|
6
|
+
|
7
|
+
#### Parsing incoming requests
|
8
|
+
|
9
|
+
JwtBouncer includes a request parser which accepts a standard Rack request object and provides automated decoding and verification of the JWT.
|
10
|
+
|
11
|
+
You can then call various methods on this for authorisation. It's best demonstrated through an example:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
require 'jwt_bouncer/request'
|
15
|
+
|
16
|
+
r = JwtBouncer::Request.new(request)
|
17
|
+
|
18
|
+
# is the token valid
|
19
|
+
r.authenticated?
|
20
|
+
|
21
|
+
# checks whether permissions has this key and it's truthy
|
22
|
+
r.can?(:update_product)
|
23
|
+
|
24
|
+
# who is authenticated, returns a hash of data
|
25
|
+
r.actor
|
26
|
+
|
27
|
+
# access the raw permissions hash
|
28
|
+
r.permissions
|
29
|
+
```
|
30
|
+
|
31
|
+
#### Signing outbound requests
|
32
|
+
|
33
|
+
JwtBouncer isn't currently designed to provide extensive JWT signing, however it does provide a small service object for signing outbound requests. This can be useful for test suites where you may want to fake a JWT signed request.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'jwt_bouncer/sign_request'
|
37
|
+
|
38
|
+
# assuming you're using rspec-mocks here, but this could be a real request
|
39
|
+
request = double(:request, headers: {})
|
40
|
+
|
41
|
+
# some data to pass in
|
42
|
+
shared_secret = 'leeroy'
|
43
|
+
permissions = { update_product: true }
|
44
|
+
actor = { type: 'user', id: 1, name: 'Jenkins' }
|
45
|
+
|
46
|
+
# expiry is optional
|
47
|
+
expiry = Time.now.to_i + 60
|
48
|
+
|
49
|
+
# sign the request
|
50
|
+
JwtBouncer::SignRequest.call request, shared_secret: shared_secret,
|
51
|
+
permissions: permissions,
|
52
|
+
actor: actor,
|
53
|
+
expiry: expiry
|
54
|
+
|
55
|
+
# the request will now have the token in the header
|
56
|
+
request.headers['Authorization'] # => "Bearer ..."
|
57
|
+
```
|
58
|
+
|
59
|
+
### Contributing
|
60
|
+
|
61
|
+
Read the [development documentation](https://github.com/shiftcommerce/jwt-bouncer/blob/master/docs/development.md) to understand how to work on the library locally.
|
62
|
+
|
63
|
+
We welcome pull requests.
|
data/Rakefile
ADDED
data/bin/bundle
ADDED
data/bin/console
ADDED
data/bin/docker/console
ADDED
data/bin/docker/rake
ADDED
data/bin/rake
ADDED
data/bin/rspec
ADDED
data/bin/run
ADDED
data/docker-compose.yml
ADDED
data/docs/development.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
This library is setup using Docker and docker-compose, meaning you don't even need to have Ruby or any of the dependencies installed locally – you only need the [Docker Toolbox](https://www.docker.com/products/docker-toolbox).
|
2
|
+
|
3
|
+
Once you have the toolbox installed and running, you can boot a Pry console with the library loaded by simply running `./bin/console`. docker-compose will take care of downloading and installing dependencies.
|
4
|
+
|
5
|
+
For your common commands, you'll need to use the script equivalents in the `bin` folder, e.g. `./bin/bundle exec ...`, `./bin/rake -T` etc.
|
6
|
+
|
7
|
+
Tests can be run simply by using `./bin/rspec`.
|
8
|
+
|
9
|
+
If you need to run a custom command, you can use `./bin/run command here`, e.g. `./bin/run bash` will give you a bash console to the Docker instance.
|
data/jwt-bouncer.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jwt_bouncer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'jwt-bouncer'
|
8
|
+
spec.version = JwtBouncer::VERSION
|
9
|
+
spec.authors = ['Ryan Townsend']
|
10
|
+
spec.email = ['ryan@ryantownsend.co.uk']
|
11
|
+
|
12
|
+
spec.summary = 'jwt-bouncer is an abstraction for JWT-based authentication/authorisation'
|
13
|
+
spec.homepage = 'https://github.com/ryantownsend/jwt-bouncer'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.5'
|
26
|
+
spec.add_development_dependency 'activesupport', '~> 5.0', '>= 5.0.1'
|
27
|
+
spec.add_dependency 'rack', '~> 2.0'
|
28
|
+
spec.add_dependency 'jwt', '~> 1.5', '>= 1.5.6'
|
29
|
+
end
|
data/lib/jwt_bouncer.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'jwt'
|
4
|
+
require 'zlib'
|
5
|
+
|
6
|
+
module JwtBouncer
|
7
|
+
module Permissions
|
8
|
+
def self.compress(permissions)
|
9
|
+
stream = StringIO.new
|
10
|
+
zip = Zlib::GzipWriter.new(stream)
|
11
|
+
begin
|
12
|
+
zip.write(permissions.to_json)
|
13
|
+
ensure
|
14
|
+
zip.close
|
15
|
+
end
|
16
|
+
|
17
|
+
Base64.encode64(stream.string)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.decompress(permissions)
|
21
|
+
unzipped_stream = StringIO.new
|
22
|
+
StringIO.open(Base64.decode64(permissions)) do |stream|
|
23
|
+
unzip = Zlib::GzipReader.new(stream)
|
24
|
+
begin
|
25
|
+
unzipped_stream.write(unzip.read)
|
26
|
+
ensure
|
27
|
+
unzip.close
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
JSON.parse(unzipped_stream.string)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.destructure(permissions)
|
35
|
+
destructured_permissions = []
|
36
|
+
permissions.each do |service, resources|
|
37
|
+
resources.each do |resource, resource_permissions|
|
38
|
+
resource_permissions.each do |permission|
|
39
|
+
destructured_permissions << [service, resource, permission].join('_')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
destructured_permissions
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'jwt_bouncer/token'
|
4
|
+
require 'jwt_bouncer/permissions'
|
5
|
+
require 'jwt'
|
6
|
+
|
7
|
+
module JwtBouncer
|
8
|
+
class Request
|
9
|
+
HEADER = 'Authorization'.freeze
|
10
|
+
|
11
|
+
def initialize(request, shared_secret: nil)
|
12
|
+
@encoded_token = Request.extract_token(request)
|
13
|
+
@shared_secret = shared_secret
|
14
|
+
end
|
15
|
+
|
16
|
+
def authenticated?
|
17
|
+
!!decoded_token
|
18
|
+
rescue JWT::DecodeError
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def actor
|
23
|
+
decoded_token['actor']
|
24
|
+
end
|
25
|
+
|
26
|
+
def account_reference
|
27
|
+
decoded_token['account_reference']
|
28
|
+
end
|
29
|
+
|
30
|
+
def permissions
|
31
|
+
@permissions ||= Permissions.decompress(decoded_token['permissions'])
|
32
|
+
end
|
33
|
+
|
34
|
+
def can?(action)
|
35
|
+
destructured_action_permissions = Permissions.destructure(action)
|
36
|
+
matching_permissions = destructured_action_permissions & destructured_permissions
|
37
|
+
matching_permissions == destructured_action_permissions
|
38
|
+
end
|
39
|
+
|
40
|
+
# extracts the encoded token from the given request
|
41
|
+
def self.extract_token(request)
|
42
|
+
return nil unless request.headers.key?(HEADER)
|
43
|
+
matches = request.headers.fetch(HEADER).match(/\ABearer\s(.*)\z/i)
|
44
|
+
matches[1] if matches
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def decoded_token
|
50
|
+
@decoded_token ||= Token.decode(@encoded_token, @shared_secret)
|
51
|
+
end
|
52
|
+
|
53
|
+
def destructured_permissions
|
54
|
+
Permissions.destructure(permissions)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
require 'jwt_bouncer/token'
|
3
|
+
require 'jwt_bouncer/permissions'
|
4
|
+
|
5
|
+
module JwtBouncer
|
6
|
+
module SignRequest
|
7
|
+
def self.call(request, **options)
|
8
|
+
request.headers['Authorization'] = "Bearer #{generate_token(**options)}"
|
9
|
+
request
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.generate_token(permissions: {}, actor: {}, account_reference:, shared_secret:, expiry: nil)
|
13
|
+
payload = {
|
14
|
+
permissions: Permissions.compress(permissions),
|
15
|
+
actor: actor,
|
16
|
+
account_reference: account_reference
|
17
|
+
}
|
18
|
+
Token.encode(payload, shared_secret, expiry: expiry)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
require 'jwt'
|
3
|
+
|
4
|
+
module JwtBouncer
|
5
|
+
module Token
|
6
|
+
ALGORITHM = 'HS256'
|
7
|
+
|
8
|
+
def self.encode(data, shared_secret, expiry: nil)
|
9
|
+
# setup our base payload
|
10
|
+
payload = { data: data, iat: Time.now.utc.to_i }
|
11
|
+
# apply expiry, if necessary
|
12
|
+
payload[:exp] = expiry.to_i if expiry
|
13
|
+
# build the JWT
|
14
|
+
JWT.encode(payload, shared_secret, ALGORITHM)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.decode(token, shared_secret)
|
18
|
+
JWT.decode(token, shared_secret, true, algorithm: ALGORITHM, verify_iat: true).dig(0, 'data')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jwt-bouncer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Townsend
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-04-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.0'
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 5.0.1
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - "~>"
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '5.0'
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 5.0.1
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rack
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '2.0'
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '2.0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: jwt
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.5'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 1.5.6
|
113
|
+
type: :runtime
|
114
|
+
prerelease: false
|
115
|
+
version_requirements: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.5'
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.5.6
|
123
|
+
description:
|
124
|
+
email:
|
125
|
+
- ryan@ryantownsend.co.uk
|
126
|
+
executables: []
|
127
|
+
extensions: []
|
128
|
+
extra_rdoc_files: []
|
129
|
+
files:
|
130
|
+
- ".gitignore"
|
131
|
+
- Dockerfile
|
132
|
+
- Gemfile
|
133
|
+
- Gemfile.lock
|
134
|
+
- LICENSE
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- bin/bundle
|
138
|
+
- bin/console
|
139
|
+
- bin/docker/console
|
140
|
+
- bin/docker/entrypoint
|
141
|
+
- bin/docker/rake
|
142
|
+
- bin/rake
|
143
|
+
- bin/rspec
|
144
|
+
- bin/run
|
145
|
+
- docker-compose.yml
|
146
|
+
- docs/development.md
|
147
|
+
- jwt-bouncer.gemspec
|
148
|
+
- lib/jwt_bouncer.rb
|
149
|
+
- lib/jwt_bouncer/permissions.rb
|
150
|
+
- lib/jwt_bouncer/request.rb
|
151
|
+
- lib/jwt_bouncer/sign_request.rb
|
152
|
+
- lib/jwt_bouncer/token.rb
|
153
|
+
- lib/jwt_bouncer/version.rb
|
154
|
+
homepage: https://github.com/ryantownsend/jwt-bouncer
|
155
|
+
licenses: []
|
156
|
+
metadata: {}
|
157
|
+
post_install_message:
|
158
|
+
rdoc_options: []
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
requirements: []
|
172
|
+
rubyforge_project:
|
173
|
+
rubygems_version: 2.6.8
|
174
|
+
signing_key:
|
175
|
+
specification_version: 4
|
176
|
+
summary: jwt-bouncer is an abstraction for JWT-based authentication/authorisation
|
177
|
+
test_files: []
|