bs_jwt 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.gitlab-ci.yml +25 -0
- data/.rspec +3 -0
- data/.rubocop.yml +42 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +72 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +102 -0
- data/LICENSE +11 -0
- data/README.md +69 -0
- data/Rakefile +16 -0
- data/bin/build_and_publish +10 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/bs_jwt.gemspec +43 -0
- data/config/initializers/bs_jwt.rb +4 -0
- data/lib/bs_jwt/authentication.rb +42 -0
- data/lib/bs_jwt/factories/authentications.rb +13 -0
- data/lib/bs_jwt/factories.rb +3 -0
- data/lib/bs_jwt/railtie.rb +9 -0
- data/lib/bs_jwt/tasks/install.rake +16 -0
- data/lib/bs_jwt/version.rb +5 -0
- data/lib/bs_jwt.rb +90 -0
- metadata +207 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fd45222b4a9bdddb2f839cc91d7de23275fdaacbf7535f3e9b0d5a2a1cc29bf6
|
4
|
+
data.tar.gz: f15546b20ca37c595fe2bd0ffbc7a2a958b2348a716f74bd5e8fe17cd4a354d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 701309fd19d4aa51851382198d30c7e1ca24d2e84ff13e1b5e034971ee18d1a90458abbbdb9f76d60a183252766d042220f0ce6eebef89874e3cfe60dae1ebb9
|
7
|
+
data.tar.gz: 1a7abc5763cd6d03b1e4dda287e6c241556c8ed74db31732c61bc810c59e22191c2a2b9e2a95c6049a1021bbacb23795bed9864b3631e212b0a7bdb4ca01fb7f
|
data/.gitignore
ADDED
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
image: "ruby:2.5"
|
2
|
+
|
3
|
+
before_script:
|
4
|
+
- ruby -v
|
5
|
+
- gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
|
6
|
+
|
7
|
+
rubocop:
|
8
|
+
stage: test
|
9
|
+
script:
|
10
|
+
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
|
11
|
+
- bundle exec rubocop
|
12
|
+
|
13
|
+
rspec:
|
14
|
+
stage: test
|
15
|
+
script:
|
16
|
+
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
|
17
|
+
- bundle exec rspec spec
|
18
|
+
|
19
|
+
publish_gem:
|
20
|
+
stage: deploy
|
21
|
+
only:
|
22
|
+
- master
|
23
|
+
when: manual
|
24
|
+
script:
|
25
|
+
- 'bin/build_and_publish'
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# This is the configuration used to check the rubocop source code.
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
TargetRubyVersion: 2.5
|
5
|
+
Exclude:
|
6
|
+
- 'vendor/**/*'
|
7
|
+
- 'spec/fixtures/**/*'
|
8
|
+
|
9
|
+
Lint/HandleExceptions:
|
10
|
+
Exclude:
|
11
|
+
- 'bin/rails'
|
12
|
+
- 'bin/rake'
|
13
|
+
- 'bin/rspec'
|
14
|
+
|
15
|
+
Style/Encoding:
|
16
|
+
Enabled: true
|
17
|
+
|
18
|
+
Style/NumericLiterals:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/RescueModifier:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
# false error when run with Neomake
|
25
|
+
Naming/FileName:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Metrics/LineLength:
|
29
|
+
Max: 120
|
30
|
+
|
31
|
+
Style/RescueStandardError:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/Documentation:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Metrics/BlockLength:
|
38
|
+
Exclude:
|
39
|
+
- '**/*.rake'
|
40
|
+
- 'spec/**/*.rb'
|
41
|
+
- 'config/**/*.rb'
|
42
|
+
- '*.gemspec'
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.5.1
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
|
+
## Unreleased
|
5
|
+
## [2.0.1] - 2018-07-23
|
6
|
+
No changes. Version 2.0.0 was accidentally deleted from ruby gems.
|
7
|
+
|
8
|
+
## [2.0.0] - 2018-07-13
|
9
|
+
### Removed
|
10
|
+
- Remove Authentication#buddy_id
|
11
|
+
|
12
|
+
## [1.2.0] - 2018-07-10
|
13
|
+
### Added
|
14
|
+
- Add issued_at to the authentication model
|
15
|
+
|
16
|
+
## [1.1.0] - 2018-07-09
|
17
|
+
### Added
|
18
|
+
- Authentication#to_h returns the instance attributes as hash.
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
- Authentication.new now accepts an attribute hash.
|
22
|
+
|
23
|
+
## [1.0.3] - 2018-07-02
|
24
|
+
### Changed
|
25
|
+
- Rename factory authentication to bs_jwt_authentication.
|
26
|
+
|
27
|
+
## [1.0.2] - 2018-06-26
|
28
|
+
### Changed
|
29
|
+
- Set email and display_name in the authentication factory for better testing support.
|
30
|
+
|
31
|
+
## [1.0.1] - 2018-06-22
|
32
|
+
### Added
|
33
|
+
- `BsJwt.verify_and_decode/1` and `BsJwt.verify_and_decode_auth0_hash`, which basically do
|
34
|
+
the same as the bang version, but instead of raising exceptions, they return `nil`.
|
35
|
+
|
36
|
+
## [1.0.0] - 2018-06-22
|
37
|
+
### Added
|
38
|
+
- `Authentication` class, which is now returned by the `BsJwt.verify_and_decode!/1` and
|
39
|
+
`BsJwt.verify_and_decode_auth0_hash!/1` (formerly `process_auth0_hash/1`) in place of
|
40
|
+
a payload Hash.
|
41
|
+
|
42
|
+
### Changed
|
43
|
+
- `BsJwt.process_auth0_hash/1` has been renamed to `BsJwt.verify_and_decode_auth0_hash!/1`
|
44
|
+
- `BsJwt.process_jwt/1` has been renamed to `BsJwt.verify_and_decode!/1`
|
45
|
+
Due to the change in public method names, major version has been bumped to 1.
|
46
|
+
|
47
|
+
## Unreleased
|
48
|
+
### Added
|
49
|
+
- First version of this gem.
|
50
|
+
-----------------------------------------------------------------------------------------
|
51
|
+
|
52
|
+
Template:
|
53
|
+
## [0.0.0] - 2014-05-31
|
54
|
+
### Added
|
55
|
+
- something was added
|
56
|
+
|
57
|
+
### Changed
|
58
|
+
- something changed
|
59
|
+
|
60
|
+
### Deprecated
|
61
|
+
- something is deprecated
|
62
|
+
|
63
|
+
### Removed
|
64
|
+
- something was removed
|
65
|
+
|
66
|
+
### Fixed
|
67
|
+
- something was fixed
|
68
|
+
|
69
|
+
### Security
|
70
|
+
- a security fix
|
71
|
+
|
72
|
+
Following "[Keep a CHANGELOG](http://keepachangelog.com/)"
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bs_jwt (2.0.1)
|
5
|
+
activesupport (>= 4.0)
|
6
|
+
faraday (>= 0.8)
|
7
|
+
json-jwt (~> 1.9.4)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (5.2.0)
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
|
+
i18n (>= 0.7, < 2)
|
15
|
+
minitest (~> 5.1)
|
16
|
+
tzinfo (~> 1.1)
|
17
|
+
addressable (2.5.2)
|
18
|
+
public_suffix (>= 2.0.2, < 4.0)
|
19
|
+
aes_key_wrap (1.0.1)
|
20
|
+
ast (2.4.0)
|
21
|
+
bindata (2.4.3)
|
22
|
+
byebug (10.0.2)
|
23
|
+
coderay (1.1.2)
|
24
|
+
concurrent-ruby (1.0.5)
|
25
|
+
crack (0.4.3)
|
26
|
+
safe_yaml (~> 1.0.0)
|
27
|
+
diff-lcs (1.3)
|
28
|
+
factory_bot (4.10.0)
|
29
|
+
activesupport (>= 3.0.0)
|
30
|
+
faraday (0.15.2)
|
31
|
+
multipart-post (>= 1.2, < 3)
|
32
|
+
hashdiff (0.3.7)
|
33
|
+
i18n (1.0.1)
|
34
|
+
concurrent-ruby (~> 1.0)
|
35
|
+
jaro_winkler (1.5.1)
|
36
|
+
json-jwt (1.9.4)
|
37
|
+
activesupport
|
38
|
+
aes_key_wrap
|
39
|
+
bindata
|
40
|
+
method_source (0.9.0)
|
41
|
+
minitest (5.11.3)
|
42
|
+
multipart-post (2.0.0)
|
43
|
+
parallel (1.12.1)
|
44
|
+
parser (2.5.1.0)
|
45
|
+
ast (~> 2.4.0)
|
46
|
+
powerpack (0.1.2)
|
47
|
+
pry (0.11.3)
|
48
|
+
coderay (~> 1.1.0)
|
49
|
+
method_source (~> 0.9.0)
|
50
|
+
pry-byebug (3.6.0)
|
51
|
+
byebug (~> 10.0)
|
52
|
+
pry (~> 0.10)
|
53
|
+
public_suffix (3.0.2)
|
54
|
+
rainbow (3.0.0)
|
55
|
+
rake (10.5.0)
|
56
|
+
rspec (3.7.0)
|
57
|
+
rspec-core (~> 3.7.0)
|
58
|
+
rspec-expectations (~> 3.7.0)
|
59
|
+
rspec-mocks (~> 3.7.0)
|
60
|
+
rspec-core (3.7.1)
|
61
|
+
rspec-support (~> 3.7.0)
|
62
|
+
rspec-expectations (3.7.0)
|
63
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
64
|
+
rspec-support (~> 3.7.0)
|
65
|
+
rspec-mocks (3.7.0)
|
66
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
+
rspec-support (~> 3.7.0)
|
68
|
+
rspec-support (3.7.1)
|
69
|
+
rubocop (0.57.2)
|
70
|
+
jaro_winkler (~> 1.5.1)
|
71
|
+
parallel (~> 1.10)
|
72
|
+
parser (>= 2.5)
|
73
|
+
powerpack (~> 0.1)
|
74
|
+
rainbow (>= 2.2.2, < 4.0)
|
75
|
+
ruby-progressbar (~> 1.7)
|
76
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
77
|
+
ruby-progressbar (1.9.0)
|
78
|
+
safe_yaml (1.0.4)
|
79
|
+
thread_safe (0.3.6)
|
80
|
+
tzinfo (1.2.5)
|
81
|
+
thread_safe (~> 0.1)
|
82
|
+
unicode-display_width (1.4.0)
|
83
|
+
webmock (3.4.2)
|
84
|
+
addressable (>= 2.3.6)
|
85
|
+
crack (>= 0.3.2)
|
86
|
+
hashdiff
|
87
|
+
|
88
|
+
PLATFORMS
|
89
|
+
ruby
|
90
|
+
|
91
|
+
DEPENDENCIES
|
92
|
+
bs_jwt!
|
93
|
+
bundler (~> 1.16)
|
94
|
+
factory_bot
|
95
|
+
pry-byebug
|
96
|
+
rake (~> 10.0)
|
97
|
+
rspec (~> 3.0)
|
98
|
+
rubocop (= 0.57.2)
|
99
|
+
webmock
|
100
|
+
|
101
|
+
BUNDLED WITH
|
102
|
+
1.16.2
|
data/LICENSE
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Copyright 2018 Karol Moroz <k.j.moroz@gmail.com>
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
4
|
+
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
6
|
+
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
8
|
+
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
10
|
+
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# BS::JWT
|
2
|
+
|
3
|
+
Simple library for verifying Auth0 JWTs
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'bs-jwt'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install bs-jwt
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Set the auth0 domain (in an initializer).
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
BsJwt.auth0_domain = ENV.fetch('AUTH0_DOMAIN', 'reverse-retail.eu.auth0.com')
|
27
|
+
```
|
28
|
+
|
29
|
+
Decode a JWT token:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
jwt_token =
|
33
|
+
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5FTTNNRFZGTlRZME5VTkRRVEpEUWtFeE5rRkJSamhET0RBMlF6Y3hOemd4TkRrNU1FRXh' \
|
34
|
+
'SUSJ9.eyJodHRwczovL2J1ZGR5LmJ1ZGR5YW5kc2VsbHkuY29tL2J1ZGR5X2lkIjozMzcsImh0dHBzOi8vYnVkZHkuYnVkZHlhbmRzZWxseS5jb20vc' \
|
35
|
+
'm9sZXMiOlsiYWRtaW4iXSwibmlja25hbWUiOiJKYW5uaWsgR3JhdyIsIm5hbWUiOiJqLmdyYXdAYnVkZHlhbmRzZWxseS5jb20iLCJ1cGRhdGVkX2F0' \
|
36
|
+
'IjoiMjAxOC0wNi0yMlQwOToxMDoyNS45NDhaIiwiaXNzIjoiaHR0cHM6Ly9yZXZlcnNlLXJldGFpbC5ldS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB' \
|
37
|
+
'8NGUzYTJmZWY3MWI1NzE5NjFjMWIyMjkiLCJhdWQiOiJDdE9kbDVkMERVNE9HMWJEdEZmT3ZWbFVoN0YxODlHMiIsImlhdCI6MTUyOTY1ODYyOSwiZX' \
|
38
|
+
'hwIjoxNTI5Njk0NjI5fQ.omtjxv_4OJ1gG3RnfsBRn7jBY1oLExYcOrKKIrDIBKdtYoBtzbNZuLfXi2rfEnBMEd3f-MNPU9Ynot6VF6Ps16-V_LHGWb' \
|
39
|
+
'jr4trkt2ACrXUKcg7cc3hxiMVauj2ehoofzsWXY78BGCZKXFWyUidnLcLBgY2yhAhTds5eWQpi7MOpDVTQqIcXuRpidS499myZnw0hueyztuM9yUhuN' \
|
40
|
+
'E6l_ygqEglgQ8qr0p6ljiZvQ1lq6w_alOvzyfqRP4a5ClKM7LzlnP5DCsUJN1qJdoPhJNYyjxu7H-1qxJtJaaBoD74-dX3-bYkinSRqfro19tD0FSON' \
|
41
|
+
'TOfdwWc1XPgJ-6bDzQ'
|
42
|
+
BsJwt.verify_and_decode!(jwt_token)
|
43
|
+
```
|
44
|
+
|
45
|
+
Decode a JWT token directly from the omniauth hash:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
BsJwt.verify_and_decode_auth0_hash!(request.env['omniauth.auth'])
|
49
|
+
```
|
50
|
+
|
51
|
+
## Testing support
|
52
|
+
|
53
|
+
Some `factory_bot` factories are included in this gem. To use them add
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require 'bs_jwt/factories'
|
57
|
+
```
|
58
|
+
|
59
|
+
before requiring `factory_bot` to your spec_helper.
|
60
|
+
|
61
|
+
## Publish new gem version
|
62
|
+
|
63
|
+
1) Set the new version in the [version file](lib/bs_jwt/version.rb).
|
64
|
+
|
65
|
+
2) Update the [changelog](CHANGELOG.md)
|
66
|
+
|
67
|
+
3) Make a bump version commit and push it
|
68
|
+
|
69
|
+
4) Visit https://gitlab.com/ReverseRetail/bs_jwt/pipelines. Wait for the tests to pass and trigger the publish_gem job.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
task default: :spec
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'rubocop/rake_task'
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
task default: :rubocop
|
14
|
+
rescue LoadError => e
|
15
|
+
puts "rubocop not loaded (#{e.class.name})"
|
16
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'bs/jwt'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/bs_jwt.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'bs_jwt/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'bs_jwt'
|
9
|
+
spec.version = BsJwt::VERSION
|
10
|
+
spec.authors = ['Karol M']
|
11
|
+
spec.email = ['dmuhafc@gmail.com']
|
12
|
+
|
13
|
+
spec.summary = 'Simple library for verifying Auth0 JWTs.'
|
14
|
+
spec.homepage = 'http://buddy.buddyandselly.com'
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
20
|
+
else
|
21
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
22
|
+
'public gem pushes.'
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
f.match(%r{^(test|spec|features)/})
|
27
|
+
end
|
28
|
+
spec.bindir = 'exe'
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ['lib']
|
31
|
+
|
32
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
33
|
+
spec.add_development_dependency 'factory_bot'
|
34
|
+
spec.add_development_dependency 'pry-byebug'
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
36
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
|
+
spec.add_development_dependency 'rubocop', '0.57.2'
|
38
|
+
spec.add_development_dependency 'webmock'
|
39
|
+
|
40
|
+
spec.add_dependency 'activesupport', '>= 4.0'
|
41
|
+
spec.add_dependency 'faraday', '>= 0.8'
|
42
|
+
spec.add_dependency 'json-jwt', '~> 1.9.4'
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BsJwt
|
4
|
+
class Authentication
|
5
|
+
attr_accessor :roles, :display_name, :token, :expires_at, :email, :user_id, :issued_at
|
6
|
+
|
7
|
+
def self.from_jwt_payload(payload, jwt_token)
|
8
|
+
new(
|
9
|
+
roles: payload['https://buddy.buddyandselly.com/roles'],
|
10
|
+
display_name: payload['nickname'],
|
11
|
+
token: jwt_token,
|
12
|
+
expires_at: Time.at(payload['exp']),
|
13
|
+
email: payload['name'],
|
14
|
+
user_id: payload['sub'],
|
15
|
+
issued_at: Time.at(payload['iat'])
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(attributes = {})
|
20
|
+
attributes = attributes.with_indifferent_access
|
21
|
+
@roles = attributes[:roles] || []
|
22
|
+
@display_name = attributes[:display_name]
|
23
|
+
@token = attributes[:token]
|
24
|
+
@expires_at = attributes[:expires_at]
|
25
|
+
@email = attributes[:email]
|
26
|
+
@user_id = attributes[:user_id]
|
27
|
+
@issued_at = attributes[:issued_at]
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_role?(role) # rubocop:disable Naming/PredicateName
|
31
|
+
roles.include?(role)
|
32
|
+
end
|
33
|
+
|
34
|
+
def expired?
|
35
|
+
Time.now >= expires_at
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_h
|
39
|
+
instance_values
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BsJwt
|
4
|
+
FactoryBot.define do
|
5
|
+
factory :bs_jwt_authentication, class: Authentication do
|
6
|
+
issued_at { 1.hour.ago }
|
7
|
+
expires_at { 1.hour.from_now }
|
8
|
+
user_id "auth0|#{SecureRandom.hex(8)}"
|
9
|
+
email 'test@buddyandselly.com'
|
10
|
+
display_name 'Max Mustermann'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :bs_jwt do
|
4
|
+
desc 'Stub an initializer for BS::JWT configuration.'
|
5
|
+
task :install do
|
6
|
+
raise 'Rails not loaded!' unless defined?(Rails)
|
7
|
+
source = File.join(Gem.loaded_specs['bs_jwt'].full_gem_path, 'config', 'initializers', 'bs_jwt.rb')
|
8
|
+
target = File.join(Rails.root, 'config', 'initializers', 'bs_jwt.rb')
|
9
|
+
if File.exist?(target)
|
10
|
+
STDOUT.puts "File #{target} exists, overwriting..."
|
11
|
+
else
|
12
|
+
STDOUT.puts "Generating new initializer at #{target}..."
|
13
|
+
end
|
14
|
+
FileUtils.cp(source, target)
|
15
|
+
end
|
16
|
+
end
|
data/lib/bs_jwt.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bs_jwt/version'
|
4
|
+
require 'bs_jwt/authentication'
|
5
|
+
require 'bs_jwt/railtie' if defined?(Rails)
|
6
|
+
require 'json/jwt'
|
7
|
+
require 'faraday'
|
8
|
+
require 'active_support/core_ext'
|
9
|
+
|
10
|
+
##
|
11
|
+
# Module BsJwt
|
12
|
+
# Used to decode, verify, and process JSON Web Tokens (JWTs) issued by Auth0
|
13
|
+
# in applications developed and used at the company Reverse-Retail GmbH
|
14
|
+
# (www.buddyandselly.com), Hamburg, Germany.
|
15
|
+
# BS stands for Buddy&Selly.
|
16
|
+
#
|
17
|
+
# The purpose of this library is to avoid code duplication among different
|
18
|
+
# Rails apps, such as Buddy, B&S Inventory, or B&S Packing.
|
19
|
+
module BsJwt
|
20
|
+
class BaseError < RuntimeError; end
|
21
|
+
|
22
|
+
class ConfigMissing < BaseError; end
|
23
|
+
class VerificationError < BaseError; end
|
24
|
+
class NetworkError < BaseError; end
|
25
|
+
class InvalidToken < BaseError; end
|
26
|
+
|
27
|
+
mattr_accessor :auth0_domain
|
28
|
+
|
29
|
+
DEFAULT_ENDPOINT = '/.well-known/jwks.json'
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def verify_and_decode_auth0_hash!(auth0_hash)
|
33
|
+
raise ArgumentError, 'Auth0 Hash must be an instance of Hash' unless auth0_hash.is_a?(Hash)
|
34
|
+
jwt = auth0_hash.dig('credentials', 'id_token')
|
35
|
+
verify_and_decode!(jwt)
|
36
|
+
end
|
37
|
+
|
38
|
+
def verify_and_decode_auth0_hash(auth0_hash)
|
39
|
+
raise ArgumentError, 'Auth0 Hash must be an instance of Hash' unless auth0_hash.is_a?(Hash)
|
40
|
+
jwt = auth0_hash.dig('credentials', 'id_token')
|
41
|
+
verify_and_decode(jwt)
|
42
|
+
end
|
43
|
+
|
44
|
+
def verify_and_decode!(jwt)
|
45
|
+
raise InvalidToken, 'token is nil' if jwt.nil?
|
46
|
+
decoded = JSON::JWT.decode(jwt, jwks_key)
|
47
|
+
Authentication.from_jwt_payload(decoded, jwt)
|
48
|
+
rescue JSON::JWT::Exception
|
49
|
+
raise InvalidToken
|
50
|
+
end
|
51
|
+
|
52
|
+
def verify_and_decode(jwt)
|
53
|
+
return if jwt.nil?
|
54
|
+
decoded = JSON::JWT.decode(jwt, jwks_key)
|
55
|
+
Authentication.from_jwt_payload(decoded, jwt)
|
56
|
+
rescue JSON::JWT::Exception
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def jwks_key
|
61
|
+
@jwks_key ||= update_jwks
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Fetches and overwrites the JWKS
|
67
|
+
def update_jwks
|
68
|
+
check_config
|
69
|
+
fetch_jwks
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_config
|
73
|
+
%i[auth0_domain].each do |key|
|
74
|
+
val = send(key)
|
75
|
+
next if val && (val.respond_to?(:empty?) && !val.empty?) # present
|
76
|
+
raise ConfigMissing, "#{key} is not set"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch_jwks(domain: auth0_domain)
|
81
|
+
url = [domain, DEFAULT_ENDPOINT].join
|
82
|
+
url = 'https://' + url unless url =~ %r{https?://}
|
83
|
+
res = Faraday.get(url)
|
84
|
+
# raise if response code is not HTTP success
|
85
|
+
# Faraday's exception should fall through
|
86
|
+
raise(NetworkError, 'Fetching JWKS key failed') unless res.success?
|
87
|
+
JSON::JWK::Set.new(JSON.parse(res.body))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
metadata
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bs_jwt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Karol M
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-07-23 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.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: factory_bot
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.57.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.57.2
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: activesupport
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '4.0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '4.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: faraday
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.8'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.8'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: json-jwt
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 1.9.4
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.9.4
|
153
|
+
description:
|
154
|
+
email:
|
155
|
+
- dmuhafc@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gitignore"
|
161
|
+
- ".gitlab-ci.yml"
|
162
|
+
- ".rspec"
|
163
|
+
- ".rubocop.yml"
|
164
|
+
- ".ruby-version"
|
165
|
+
- ".travis.yml"
|
166
|
+
- CHANGELOG.md
|
167
|
+
- Gemfile
|
168
|
+
- Gemfile.lock
|
169
|
+
- LICENSE
|
170
|
+
- README.md
|
171
|
+
- Rakefile
|
172
|
+
- bin/build_and_publish
|
173
|
+
- bin/console
|
174
|
+
- bin/setup
|
175
|
+
- bs_jwt.gemspec
|
176
|
+
- config/initializers/bs_jwt.rb
|
177
|
+
- lib/bs_jwt.rb
|
178
|
+
- lib/bs_jwt/authentication.rb
|
179
|
+
- lib/bs_jwt/factories.rb
|
180
|
+
- lib/bs_jwt/factories/authentications.rb
|
181
|
+
- lib/bs_jwt/railtie.rb
|
182
|
+
- lib/bs_jwt/tasks/install.rake
|
183
|
+
- lib/bs_jwt/version.rb
|
184
|
+
homepage: http://buddy.buddyandselly.com
|
185
|
+
licenses: []
|
186
|
+
metadata: {}
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
require_paths:
|
190
|
+
- lib
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - ">="
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: '0'
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
requirements: []
|
202
|
+
rubyforge_project:
|
203
|
+
rubygems_version: 2.7.7
|
204
|
+
signing_key:
|
205
|
+
specification_version: 4
|
206
|
+
summary: Simple library for verifying Auth0 JWTs.
|
207
|
+
test_files: []
|