grape-jwt-authentication 1.2.0 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7900166f72226d3f5dc97a2f025ff3d2e515555a3828382aaa6bbe40f76e7fd6
4
- data.tar.gz: bd31474aac492ba98f0eb86b1b669e948daac39686b4a12b7e658954a8687813
3
+ metadata.gz: 6e3f66e76b4c2b311f69dd18a6a5ad9288ec5ece3fc34a3cc7d11a685adf991c
4
+ data.tar.gz: da5277432b5e8eedad129c1fbf1236b1eca71bb01d32b9c2748dc5525e7e83d4
5
5
  SHA512:
6
- metadata.gz: d2f26a9a534a847b94cfc05db8dde97bf9592ff1ab42204e21e3c7334cfd9f6a2d4328948a23e536c07e48c027932ef17b68c58c9a40226d014cbb00498b6bf0
7
- data.tar.gz: dfa9f8e2362e79126df5e5ff6de634ef47c9cc2cb1f2cb44907766902772025d9d16e22a0fbc487c9c7058c1853f38b1459746100a4c06538e5b2d26fb6f8c11
6
+ metadata.gz: 002fcd02712c1b23edc746d7b396cf53fe1cc1586b91bf8c1b4d72eaa44daaf4ff1a6e39064f211543f46bdf0bf473baaacaf66134d2f17e75ada1f3f58f6a10
7
+ data.tar.gz: 9c9ca3eab5b1e6031bf0eca71655931c1ee742010cb02cb324e2be91f20e4cbb967be8153205d86b44e48288ad2f614a4b50c1a43b915054df9e46e5f47ea509
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /Gemfile.lock
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/.travis.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  env:
2
2
  global:
3
- - CC_TEST_REPORTER_ID=6e5d2de1ccc0412cdc8d01fdddc560fe3051b14f1c15fea55b0d6e32e27a81cf
3
+ - CC_TEST_REPORTER_ID=ecb753423174dbd8e4aaf04fb62bf4ef9c2a54904ac49a33fdf2b908b3c5e5f3
4
4
 
5
5
  sudo: false
6
6
  language: ruby
@@ -8,7 +8,6 @@ rvm:
8
8
  - 2.6
9
9
  - 2.5
10
10
  - 2.4
11
- - 2.3
12
11
 
13
12
  before_install: gem install bundler
14
13
 
data/CHANGELOG.md CHANGED
@@ -1,3 +1,33 @@
1
+ ### 2.0.3
2
+
3
+ * Pinned rspec-expectations to <= 3.9.2
4
+ * Removed the rspec-expectations pinning
5
+
6
+ ### 2.0.2
7
+
8
+ * Corrected some documentation glitches
9
+
10
+ ### 2.0.1
11
+
12
+ * Corrected a migration bug on the configuration which used the wrong namespace
13
+ for `RsaPublicKey` (resulted in `uninitialized constant
14
+ Grape::Jwt::Authentication::Configuration::RsaPublicKey`)
15
+
16
+ ### 2.0.0
17
+
18
+ * Extracted the JWT verification functionality into its own gem
19
+ ([keyless](https://github.com/hausgold/keyless)) (#6)
20
+ * This extraction allows users to use the JWT/RSA key handling without Grape
21
+ * The API/configuration stays the same
22
+ * With the major update to 2.0 we dropped a lot of code which is now located at
23
+ the Keyless gem:
24
+ * `Grape::Jwt::Authentication::Jwt` was replace with `Keyless::Jwt`
25
+ * `Grape::Jwt::Authentication::RsaPublicKey` was replace with `Keyless::RsaPublicKey`
26
+
27
+ ### 1.3.0
28
+
29
+ * Dropped support for EOL Ruby 2.3 (in addition to Grape)
30
+
1
31
  ### 1.2.0
2
32
 
3
33
  * Check the remote response on public key fetching (#3)
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  ![grape-jwt-authentication](doc/assets/project.svg)
2
2
 
3
- [![Build Status](https://travis-ci.org/hausgold/grape-jwt-authentication.svg?branch=master)](https://travis-ci.org/hausgold/grape-jwt-authentication)
3
+ [![Build Status](https://travis-ci.com/hausgold/grape-jwt-authentication.svg?branch=master)](https://travis-ci.com/hausgold/grape-jwt-authentication)
4
4
  [![Gem Version](https://badge.fury.io/rb/grape-jwt-authentication.svg)](https://badge.fury.io/rb/grape-jwt-authentication)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/446f3eff18bebff9c174/maintainability)](https://codeclimate.com/github/hausgold/grape-jwt-authentication/maintainability)
6
- [![Test Coverage](https://api.codeclimate.com/v1/badges/446f3eff18bebff9c174/test_coverage)](https://codeclimate.com/github/hausgold/grape-jwt-authentication/test_coverage)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/ab14a3bab572edfbf305/maintainability)](https://codeclimate.com/repos/5cac8bc06c282f791c009a66/maintainability)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/ab14a3bab572edfbf305/test_coverage)](https://codeclimate.com/repos/5cac8bc06c282f791c009a66/test_coverage)
7
7
  [![API docs](https://img.shields.io/badge/docs-API-blue.svg)](https://www.rubydoc.info/gems/grape-jwt-authentication)
8
8
 
9
9
  This gem is dedicated to easily integrate a JWT authentication to your
@@ -185,18 +185,18 @@ have your own mechanism.
185
185
 
186
186
  ```ruby
187
187
  # Get your public key, by using the global configuration
188
- public_key = Grape::Jwt::Authentication::RsaPublicKey.fetch
188
+ public_key = Keyless::RsaPublicKey.fetch
189
189
  # => OpenSSL::PKey::RSA
190
190
 
191
191
  # Using a local configuration
192
- fetcher = Grape::Jwt::Authentication::RsaPublicKey.instance
192
+ fetcher = Keyless::RsaPublicKey.instance
193
193
  fetcher.url = 'https://your.identity.provider/rsa_public_key'
194
194
  public_key = fetcher.fetch
195
195
  # => OpenSSL::PKey::RSA
196
196
  ```
197
197
 
198
198
  The following examples show you how to configure the
199
- `Grape::Jwt::Authentication::RsaPublicKey` class the global way. This is useful
199
+ `Keyless::RsaPublicKey` class the global way. This is useful
200
200
  for a shared initializer place.
201
201
 
202
202
  ##### RSA public key location (URL)
@@ -261,7 +261,7 @@ the `RsaPublicKey` fetcher class. (by default)
261
261
  raw_token = 'eyJ0eXAiOiJKV1QifQ.eyJ0ZXN0Ijp0cnVlfQ.'
262
262
 
263
263
  # Parse the raw token and create a instance of it
264
- token = Grape::Jwt::Authentication::Jwt.new(raw_token)
264
+ token = Keyless::Jwt.new(raw_token)
265
265
 
266
266
  # Access the payload easily (recursive-open-struct)
267
267
  token.payload.test
@@ -274,7 +274,7 @@ token.valid?
274
274
  ```
275
275
 
276
276
  The following examples show you how to configure the
277
- `Grape::Jwt::Authentication::Jwt` class the global way. This is useful for a
277
+ `Keyless::Jwt` class the global way. This is useful for a
278
278
  shared initializer place.
279
279
 
280
280
  ##### Issuer verification
@@ -305,7 +305,7 @@ end
305
305
  You can configure a different JSON Web Token verification option hash if your
306
306
  algorithm differs or you want some extra/different options. Just watch out
307
307
  that you have to pass a proc to this configuration property. On the
308
- `Grape::Jwt::Authentication::Jwt` class it has to be a simple hash. The default
308
+ `Keyless::Jwt` class it has to be a simple hash. The default
309
309
  is here the `RS256` algorithm with enabled expiration check, and issuer+audience
310
310
  check when the `jwt_issuer` / `jwt_beholder` are configured accordingly.
311
311
 
@@ -323,7 +323,7 @@ end
323
323
  You can configure your own verification key on the `Jwt` wrapper class. This
324
324
  way you can pass your HMAC secret or your ECDSA public key to the JSON Web
325
325
  Token validation method. Here you need to pass a proc, on the
326
- `Grape::Jwt::Authentication::Jwt` class it has to be a scalar value. By default
326
+ `Keyless::Jwt` class it has to be a scalar value. By default
327
327
  we use the `RsaPublicKey` class to retrieve the RSA public key.
328
328
 
329
329
  ```ruby
@@ -394,7 +394,7 @@ Grape::Jwt::Authentication.configure do |conf|
394
394
  # Custom verification logic.
395
395
  conf.authenticator = proc do |token|
396
396
  # Parse and instantiate a JWT verification instance
397
- jwt = Grape::Jwt::Authentication::Jwt.new(token)
397
+ jwt = Keyless::Jwt.new(token)
398
398
 
399
399
  # We just allow valid access tokens
400
400
  jwt.access_token? && jwt.valid?
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'rack', '~> 2.0'
26
26
  spec.add_development_dependency 'rack-test', '~> 0.8.2'
27
27
  spec.add_development_dependency 'rake', '~> 10.0'
28
- spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.9'
29
29
  spec.add_development_dependency 'simplecov', '~> 0.15'
30
30
  spec.add_development_dependency 'timecop', '~> 0.9.1'
31
31
  spec.add_development_dependency 'vcr', '~> 3.0'
@@ -36,4 +36,5 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency 'httparty'
37
37
  spec.add_runtime_dependency 'jwt', '~> 2.1'
38
38
  spec.add_runtime_dependency 'recursive-open-struct', '~> 1.0'
39
+ spec.add_runtime_dependency 'keyless', '~> 1.0'
39
40
  end
@@ -7,15 +7,13 @@ require 'active_support/cache'
7
7
  require 'active_support/core_ext/hash'
8
8
  require 'active_support/time'
9
9
  require 'active_support/time_with_zone'
10
-
11
10
  require 'jwt'
12
-
11
+ require 'keyless'
13
12
  require 'grape'
14
13
  require 'grape/jwt/authentication/version'
15
14
  require 'grape/jwt/authentication/configuration'
15
+ require 'grape/jwt/authentication/dependencies'
16
16
  require 'grape/jwt/authentication/jwt_handler'
17
- require 'grape/jwt/authentication/jwt'
18
- require 'grape/jwt/authentication/rsa_public_key'
19
17
 
20
18
  module Grape
21
19
  module Jwt
@@ -43,11 +41,13 @@ module Grape
43
41
  # end
44
42
  def self.configure
45
43
  yield(configuration)
44
+ configure_dependencies
46
45
  end
47
46
 
48
47
  # Reset the current configuration with the default one.
49
48
  def self.reset_configuration!
50
49
  self.configuration = Configuration.new
50
+ configure_dependencies
51
51
  end
52
52
 
53
53
  included do
@@ -65,7 +65,7 @@ module Grape
65
65
  # date, etc inside your API definition. When the authenticator stated
66
66
  # that the validation failed, then the parsed token is +nil+.
67
67
  #
68
- # @return [Grape::Jwt::Authentication::Jwt, nil] the parsed token
68
+ # @return [Keyless::Jwt, nil] the parsed token
69
69
  def request_jwt
70
70
  env['grape_jwt_auth.parsed_token']
71
71
  end
@@ -96,10 +96,10 @@ module Grape
96
96
  # You can configure a different JSON Web Token verification option hash
97
97
  # if your algorithm differs or you want some extra/different options.
98
98
  # Just watch out that you have to pass a proc to this configuration
99
- # property. On the {Grape::Jwt::Authentication::Jwt} class it has to be
100
- # a simple hash. The default is here the RS256 algorithm with enabled
101
- # expiration check, and issuer+audience check when the
102
- # {jwt_issuer}/{jwt_beholder} are configured accordingly.
99
+ # property. On the {Keyless::Jwt} class it has to be a simple hash. The
100
+ # default is here the RS256 algorithm with enabled expiration check,
101
+ # and issuer+audience check when the {jwt_issuer}/{jwt_beholder} are
102
+ # configured accordingly.
103
103
  config_accessor(:jwt_options) do
104
104
  proc do
105
105
  conf = Grape::Jwt::Authentication.configuration
@@ -117,12 +117,11 @@ module Grape
117
117
  # You can configure your own verification key on the Jwt wrapper class.
118
118
  # This way you can pass your HMAC secret or your ECDSA public key to
119
119
  # the JSON Web Token validation method. Here you need to pass a proc,
120
- # on the {Grape::Jwt::Authentication::Jwt} class it has to be a scalar
121
- # value. By default we use the
122
- # {Grape::Jwt::Authentication::RsaPublicKey} class to retrieve the RSA
123
- # public key.
120
+ # on the {Keyless::Jwt} class it has to be a scalar value. By default
121
+ # we use the {Keyless::RsaPublicKey} class to retrieve the RSA public
122
+ # key.
124
123
  config_accessor(:jwt_verification_key) do
125
- proc { RsaPublicKey.instance.fetch }
124
+ proc { Keyless::RsaPublicKey.instance.fetch }
126
125
  end
127
126
  end
128
127
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grape
4
+ module Jwt
5
+ module Authentication
6
+ # Specifies which configuration keys are shared between keyless
7
+ # and grape-jwt-authentication, so that we can easily pass through
8
+ # our configuration to keyless.
9
+ KEYLESS_CONFIGURATION = %i[
10
+ authenticator rsa_public_key_url rsa_public_key_caching
11
+ rsa_public_key_expiration jwt_issuer jwt_beholder jwt_options
12
+ jwt_verification_key
13
+ ]
14
+
15
+ # (Re)configure our gem dependencies. We take care of setting up
16
+ # +Keyless+, which has been extracted from this gem.
17
+ def self.configure_dependencies
18
+ configure_keyless
19
+ end
20
+
21
+ # Configure the +Keyless+ gem with our configuration.
22
+ def self.configure_keyless
23
+ configuration = Grape::Jwt::Authentication.configuration
24
+
25
+ Keyless.configure do |keyless|
26
+ KEYLESS_CONFIGURATION.each do |option|
27
+ keyless.send("#{option}=", configuration.send(option))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -91,8 +91,8 @@ module Grape
91
91
  # @param env [Hash{String => Mixed}] the Rack environment
92
92
  # @param token [String] the token parsed from the HTTP header
93
93
  def inject_token_into_env(env, token)
94
- env['grape_jwt_auth.parsed_token'] = Jwt.new(token)
95
- rescue *Jwt::RESCUE_JWT_EXCEPTIONS
94
+ env['grape_jwt_auth.parsed_token'] = Keyless::Jwt.new(token)
95
+ rescue *Keyless::Jwt::RESCUE_JWT_EXCEPTIONS
96
96
  env['grape_jwt_auth.parsed_token'] = nil
97
97
  ensure
98
98
  env['grape_jwt_auth.original_token'] = token
@@ -3,7 +3,7 @@
3
3
  module Grape
4
4
  module Jwt
5
5
  module Authentication
6
- VERSION = '1.2.0'.freeze
6
+ VERSION = '2.0.3'.freeze
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-jwt-authentication
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hermann Mayer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2021-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '3.0'
81
+ version: '3.9'
82
82
  type: :development
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '3.0'
88
+ version: '3.9'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: simplecov
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -212,6 +212,20 @@ dependencies:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
214
  version: '1.0'
215
+ - !ruby/object:Gem::Dependency
216
+ name: keyless
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: '1.0'
222
+ type: :runtime
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: '1.0'
215
229
  description: A reusable Grape JWT authentication concern
216
230
  email:
217
231
  - hermann.mayer92@gmail.com
@@ -227,7 +241,6 @@ files:
227
241
  - ".travis.yml"
228
242
  - CHANGELOG.md
229
243
  - Gemfile
230
- - Gemfile.lock
231
244
  - LICENSE
232
245
  - README.md
233
246
  - Rakefile
@@ -237,14 +250,13 @@ files:
237
250
  - grape-jwt-authentication.gemspec
238
251
  - lib/grape/jwt/authentication.rb
239
252
  - lib/grape/jwt/authentication/configuration.rb
240
- - lib/grape/jwt/authentication/jwt.rb
253
+ - lib/grape/jwt/authentication/dependencies.rb
241
254
  - lib/grape/jwt/authentication/jwt_handler.rb
242
- - lib/grape/jwt/authentication/rsa_public_key.rb
243
255
  - lib/grape/jwt/authentication/version.rb
244
256
  homepage: https://github.com/hausgold/grape-jwt-authentication
245
257
  licenses: []
246
258
  metadata: {}
247
- post_install_message:
259
+ post_install_message:
248
260
  rdoc_options: []
249
261
  require_paths:
250
262
  - lib
@@ -259,8 +271,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
271
  - !ruby/object:Gem::Version
260
272
  version: '0'
261
273
  requirements: []
262
- rubygems_version: 3.0.2
263
- signing_key:
274
+ rubygems_version: 3.2.16
275
+ signing_key:
264
276
  specification_version: 4
265
277
  summary: A reusable Grape JWT authentication concern
266
278
  test_files: []
data/Gemfile.lock DELETED
@@ -1,118 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- grape-jwt-authentication (1.1.0)
5
- activesupport (>= 3.2.0)
6
- grape (~> 1.0)
7
- httparty
8
- jwt (~> 2.1)
9
- recursive-open-struct (~> 1.0)
10
-
11
- GEM
12
- remote: https://rubygems.org/
13
- specs:
14
- activesupport (5.2.2)
15
- concurrent-ruby (~> 1.0, >= 1.0.2)
16
- i18n (>= 0.7, < 2)
17
- minitest (~> 5.1)
18
- tzinfo (~> 1.1)
19
- addressable (2.6.0)
20
- public_suffix (>= 2.0.2, < 4.0)
21
- axiom-types (0.1.1)
22
- descendants_tracker (~> 0.0.4)
23
- ice_nine (~> 0.11.0)
24
- thread_safe (~> 0.3, >= 0.3.1)
25
- builder (3.2.3)
26
- coercible (1.0.0)
27
- descendants_tracker (~> 0.0.1)
28
- concurrent-ruby (1.1.4)
29
- crack (0.4.3)
30
- safe_yaml (~> 1.0.0)
31
- descendants_tracker (0.0.4)
32
- thread_safe (~> 0.3, >= 0.3.1)
33
- diff-lcs (1.3)
34
- docile (1.3.1)
35
- equalizer (0.0.11)
36
- grape (1.2.3)
37
- activesupport
38
- builder
39
- mustermann-grape (~> 1.0.0)
40
- rack (>= 1.3.0)
41
- rack-accept
42
- virtus (>= 1.0.0)
43
- hashdiff (0.3.8)
44
- httparty (0.16.4)
45
- mime-types (~> 3.0)
46
- multi_xml (>= 0.5.2)
47
- i18n (1.5.3)
48
- concurrent-ruby (~> 1.0)
49
- ice_nine (0.11.2)
50
- json (2.1.0)
51
- jwt (2.1.0)
52
- mime-types (3.2.2)
53
- mime-types-data (~> 3.2015)
54
- mime-types-data (3.2018.0812)
55
- minitest (5.11.3)
56
- multi_xml (0.6.0)
57
- mustermann (1.0.3)
58
- mustermann-grape (1.0.0)
59
- mustermann (~> 1.0.0)
60
- public_suffix (3.0.3)
61
- rack (2.0.6)
62
- rack-accept (0.4.5)
63
- rack (>= 0.4)
64
- rack-test (0.8.3)
65
- rack (>= 1.0, < 3)
66
- rake (10.5.0)
67
- recursive-open-struct (1.1.0)
68
- rspec (3.8.0)
69
- rspec-core (~> 3.8.0)
70
- rspec-expectations (~> 3.8.0)
71
- rspec-mocks (~> 3.8.0)
72
- rspec-core (3.8.0)
73
- rspec-support (~> 3.8.0)
74
- rspec-expectations (3.8.2)
75
- diff-lcs (>= 1.2.0, < 2.0)
76
- rspec-support (~> 3.8.0)
77
- rspec-mocks (3.8.0)
78
- diff-lcs (>= 1.2.0, < 2.0)
79
- rspec-support (~> 3.8.0)
80
- rspec-support (3.8.0)
81
- safe_yaml (1.0.4)
82
- simplecov (0.16.1)
83
- docile (~> 1.1)
84
- json (>= 1.8, < 3)
85
- simplecov-html (~> 0.10.0)
86
- simplecov-html (0.10.2)
87
- thread_safe (0.3.6)
88
- timecop (0.9.1)
89
- tzinfo (1.2.5)
90
- thread_safe (~> 0.1)
91
- vcr (3.0.3)
92
- virtus (1.0.5)
93
- axiom-types (~> 0.1)
94
- coercible (~> 1.0)
95
- descendants_tracker (~> 0.0, >= 0.0.3)
96
- equalizer (~> 0.0, >= 0.0.9)
97
- webmock (3.5.1)
98
- addressable (>= 2.3.6)
99
- crack (>= 0.3.2)
100
- hashdiff
101
-
102
- PLATFORMS
103
- ruby
104
-
105
- DEPENDENCIES
106
- bundler (>= 1.16, < 3)
107
- grape-jwt-authentication!
108
- rack (~> 2.0)
109
- rack-test (~> 0.8.2)
110
- rake (~> 10.0)
111
- rspec (~> 3.0)
112
- simplecov (~> 0.15)
113
- timecop (~> 0.9.1)
114
- vcr (~> 3.0)
115
- webmock (~> 3.1)
116
-
117
- BUNDLED WITH
118
- 1.17.3
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'recursive-open-struct'
4
-
5
- module Grape
6
- module Jwt
7
- module Authentication
8
- # A easy to use model for verification of JSON Web Tokens. This is just a
9
- # wrapper class for the excellent ruby-jwt gem. It's completely up to you
10
- # to use it. But be aware, its a bit optinionated by default.
11
- class Jwt
12
- # All the following JWT verification issues lead to a failed validation.
13
- RESCUE_JWT_EXCEPTIONS = [
14
- ::JWT::DecodeError,
15
- ::JWT::VerificationError,
16
- ::JWT::ExpiredSignature,
17
- ::JWT::IncorrectAlgorithm,
18
- ::JWT::ImmatureSignature,
19
- ::JWT::InvalidIssuerError,
20
- ::JWT::InvalidIatError,
21
- ::JWT::InvalidAudError,
22
- ::JWT::InvalidSubError,
23
- ::JWT::InvalidJtiError,
24
- ::JWT::InvalidPayload
25
- ].freeze
26
-
27
- # :reek:Attribute because its fine to be extern-modifiable at these
28
- # instances
29
- attr_reader :payload, :token
30
- attr_writer :verification_key, :jwt_options
31
- attr_accessor :issuer, :beholder
32
-
33
- # Setup a new JWT instance. You have to pass the raw JSON Web Token to
34
- # the initializer. Example:
35
- #
36
- # Jwt.new('j.w.t')
37
- # # => <Jwt>
38
- #
39
- # @return [Jwt]
40
- def initialize(token)
41
- parsed_payload = JWT.decode(token, nil, false).first.symbolize_keys
42
- @token = token
43
- @payload = RecursiveOpenStruct.new(parsed_payload)
44
- end
45
-
46
- # Checks if the payload says this is a refresh token.
47
- #
48
- # @return [Boolean] Whenever this is a access token
49
- def access_token?
50
- payload.typ == 'access'
51
- end
52
-
53
- # Checks if the payload says this is a refresh token.
54
- #
55
- # @return [Boolean] Whenever this is a refresh token
56
- def refresh_token?
57
- payload.typ == 'refresh'
58
- end
59
-
60
- # Retrives the expiration date from the payload when set.
61
- #
62
- # @return [nil|ActiveSupport::TimeWithZone] The expiration date
63
- def expires_at
64
- exp = payload.exp
65
- return nil unless exp
66
-
67
- Time.zone.at(exp)
68
- end
69
-
70
- # Deliver the public key for verification by default. This uses the
71
- # {RsaPublicKey} class, but you can configure the verification key the
72
- # way you like. (Especially for different algorithms, like HMAC or
73
- # ECDSA) Just make use of the same named setter.
74
- #
75
- # @return [OpenSSL::PKey::RSA|Mixed] The verification key
76
- def verification_key
77
- unless @verification_key
78
- conf = Grape::Jwt::Authentication.configuration
79
- return conf.jwt_verification_key.call
80
- end
81
- @verification_key
82
- end
83
-
84
- # This getter passes back the default JWT verification option hash
85
- # which is optinionated. You can change this the way you like by
86
- # configuring your options with the help of the same named setter.
87
- #
88
- # @return [Hash] The JWT verification options hash
89
- def jwt_options
90
- unless @jwt_options
91
- conf = Grape::Jwt::Authentication.configuration
92
- return conf.jwt_options.call
93
- end
94
- @jwt_options
95
- end
96
-
97
- # Verify the current token by our hard and strict rules. Whenever the
98
- # token was not parsed from a string, we encode the current state to a
99
- # JWT string representation and check this.
100
- #
101
- # @return [Boolean] Whenever the token is valid or not
102
- #
103
- # :reek:NilCheck because we have to check the token
104
- # origin and react on it
105
- def valid?
106
- JWT.decode(token, verification_key, true, jwt_options) && true
107
- rescue *RESCUE_JWT_EXCEPTIONS
108
- false
109
- end
110
- end
111
- end
112
- end
113
- end
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
- require 'openssl'
5
- require 'httparty'
6
-
7
- module Grape
8
- module Jwt
9
- module Authentication
10
- # A common purpose RSA public key fetching/caching helper. With the help
11
- # of this class you are able to retrieve the RSA public key from a remote
12
- # server or a local file. This is naturally only useful if you care about
13
- # JSON Web Token which are signed by the RSA algorithm.
14
- class RsaPublicKey
15
- # A internal exception handling for failed fetch attempts.
16
- class FetchError < StandardError; end
17
-
18
- include Singleton
19
-
20
- # Setup all the getters and setters.
21
- attr_accessor :cache
22
- attr_writer :url, :expiration, :caching
23
-
24
- # Setup the instance.
25
- def initialize
26
- @expiration = 1.hour
27
- @cache = ActiveSupport::Cache::MemoryStore.new
28
- end
29
-
30
- # Just a simple shortcut class method to access the fetch method
31
- # without specifying the singleton instance.
32
- #
33
- # @return [OpenSSL::PKey::RSA]
34
- def self.fetch
35
- instance.fetch
36
- end
37
-
38
- # Configure the single instance. This is just a wrapper (like tap)
39
- # to the instance itself.
40
- def configure
41
- yield(self)
42
- end
43
-
44
- # Fetch the public key with the help of the configuration. You can
45
- # configure the public key location (local file, remote (HTTP/HTTPS)
46
- # file), whenever we should cache and how long to cache.
47
- #
48
- # @return [OpenSSL::PKey::RSA]
49
- def fetch
50
- encoded_key = if cache?
51
- cache.fetch('encoded_key', expires_in: expiration) do
52
- fetch_encoded_key
53
- end
54
- else
55
- fetch_encoded_key
56
- end
57
-
58
- OpenSSL::PKey::RSA.new(encoded_key)
59
- end
60
-
61
- # Fetch the encoded (DER, or PEM) public key from a remote or local
62
- # location.
63
- #
64
- # @return [String] The encoded public key
65
- def fetch_encoded_key
66
- raise ArgumentError, 'No URL for RsaPublicKey configured' unless url
67
-
68
- if remote?
69
- res = HTTParty.get(url)
70
- raise FetchError, res.inspect unless (200..299).include? res.code
71
- res.body
72
- else
73
- File.read(url)
74
- end
75
- end
76
-
77
- # A helper for the caching configuration.
78
- #
79
- # @return [Boolean]
80
- def cache?
81
- caching && true
82
- end
83
-
84
- # A helper to determine if the configured URL is on a remote server or
85
- # it is local on the filesystem. Whenever the configured URL specifies
86
- # the HTTP/HTTPS protocol, we assume it is remote.
87
- #
88
- # @return [Boolean]
89
- def remote?
90
- !(url =~ /^https?/).nil?
91
- end
92
-
93
- # This getter passes back the default RSA public key. You can change
94
- # this the way you like by configuring your URL with the help of the
95
- # same named setter.
96
- #
97
- # @return [String] The configured public key location
98
- def url
99
- unless @url
100
- conf = Grape::Jwt::Authentication.configuration
101
- return conf.rsa_public_key_url
102
- end
103
- @url
104
- end
105
-
106
- # This getter passes back the default public key cache expiration time.
107
- # You can change this time with the help of the same named setter.
108
- #
109
- # @return [Integer] The configured cache expiration time
110
- def expiration
111
- unless @expiration
112
- conf = Grape::Jwt::Authentication.configuration
113
- return conf.rsa_public_key_expiration
114
- end
115
- @expiration
116
- end
117
-
118
- # This getter passes back the caching flag. You can change this flag
119
- # with the help of the same named setter.
120
- #
121
- # @return [Boolean] Whenever we should cache or not
122
- def caching
123
- unless @caching
124
- conf = Grape::Jwt::Authentication.configuration
125
- return conf.rsa_public_key_caching
126
- end
127
- @caching
128
- end
129
- end
130
- end
131
- end
132
- end