grape-jwt-authentication 1.0.1 → 1.1.0

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
- SHA1:
3
- metadata.gz: 6a78c43fa11b24e40395c34bbc802f61c6e4646c
4
- data.tar.gz: ca386d7ac9298045d93e38b0c6df2c3e8ab1dcae
2
+ SHA256:
3
+ metadata.gz: ff7b66cbce6da2abf8a94f05de6e1193c28609ee3603c7373a7b189f1e9b67d4
4
+ data.tar.gz: 29f400c994e453466570810c10c1fcc6d674074a1edf5c2a3f8d282146c3e9fa
5
5
  SHA512:
6
- metadata.gz: 1b234415911e6f3f2820d9511af016e290ed4723521374913d9cb5b5e05925722a9222f48016c7f4a75f88ee30aa901aaa702f8699e86792e4ed9d58fab439c6
7
- data.tar.gz: 1557a1c9a4fc4acb8cf77be68fbaf4f5417753bc5e859917508bd334e36ca9449e9c483119b009158f9d0ac4202413a372ed2c4638d45444e0e9d6ce9594139a
6
+ metadata.gz: 4f7b6a29dbe8c3e6fe6e230efd52605b3729757b77ad47d2ead3d27f88f022d63d0f65a4eb11cbf99c5b23490331b1489d077e5ba49c7dd876b2843d05eeb269
7
+ data.tar.gz: d6235df2c6853433ed4a056eb2ddddeb84a2d64355fceac52181916afd6039a61c832f4a75b2283517f5abd2b3cdd40428ee007ba83babe0cc8f54692764a189
@@ -0,0 +1,30 @@
1
+ # http://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ indent_style = space
6
+ indent_size = 2
7
+ end_of_line = lf
8
+ charset = utf-8
9
+ trim_trailing_whitespace = true
10
+ insert_final_newline = true
11
+
12
+ [*.md]
13
+ trim_trailing_whitespace = true
14
+
15
+ [*.json]
16
+ indent_style = space
17
+ indent_size = 2
18
+
19
+ [*.yml]
20
+ indent_style = space
21
+ indent_size = 2
22
+
23
+ [Makefile]
24
+ trim_trailing_whitespace = true
25
+ indent_style = tab
26
+ indent_size = 4
27
+
28
+ [*.sh]
29
+ indent_style = space
30
+ indent_size = 2
@@ -0,0 +1,3 @@
1
+ SimpleCov.start 'test_frameworks' do
2
+ add_filter '/vendor/bundle/'
3
+ end
@@ -5,9 +5,10 @@ env:
5
5
  sudo: false
6
6
  language: ruby
7
7
  rvm:
8
- - 2.2
9
- - 2.3
8
+ - 2.5
10
9
  - 2.4
10
+ - 2.3
11
+ - 2.2
11
12
 
12
13
  before_install: gem install bundler
13
14
 
@@ -15,6 +16,6 @@ before_script:
15
16
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
16
17
  - chmod +x ./cc-test-reporter
17
18
  - ./cc-test-reporter before-build
18
-
19
+ script: bundle exec rake
19
20
  after_script:
20
21
  - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
@@ -1,3 +1,8 @@
1
+ ### 1.1.0
2
+
3
+ * Added the parsed and original token to the Rack environment (#2)
4
+ * Two new helper methods are now available to access the JWT from an API spec
5
+
1
6
  ### 1.0.1
2
7
 
3
8
  * First public release of the gem
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grape-jwt-authentication (1.0.1)
4
+ grape-jwt-authentication (1.1.0)
5
5
  activesupport (>= 3.2.0)
6
6
  grape (~> 1.0)
7
7
  httparty
@@ -11,9 +11,9 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activesupport (5.1.4)
14
+ activesupport (5.2.1)
15
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
- i18n (~> 0.7)
16
+ i18n (>= 0.7, < 2)
17
17
  minitest (~> 5.1)
18
18
  tzinfo (~> 1.1)
19
19
  addressable (2.5.2)
@@ -33,7 +33,7 @@ GEM
33
33
  diff-lcs (1.3)
34
34
  docile (1.1.5)
35
35
  equalizer (0.0.11)
36
- grape (1.0.1)
36
+ grape (1.1.0)
37
37
  activesupport
38
38
  builder
39
39
  mustermann-grape (~> 1.0.0)
@@ -41,16 +41,16 @@ GEM
41
41
  rack-accept
42
42
  virtus (>= 1.0.0)
43
43
  hashdiff (0.3.7)
44
- httparty (0.15.6)
44
+ httparty (0.16.2)
45
45
  multi_xml (>= 0.5.2)
46
- i18n (0.9.1)
46
+ i18n (1.1.1)
47
47
  concurrent-ruby (~> 1.0)
48
48
  ice_nine (0.11.2)
49
49
  json (2.1.0)
50
50
  jwt (2.1.0)
51
- minitest (5.10.3)
51
+ minitest (5.11.3)
52
52
  multi_xml (0.6.0)
53
- mustermann (1.0.1)
53
+ mustermann (1.0.3)
54
54
  mustermann-grape (1.0.0)
55
55
  mustermann (~> 1.0.0)
56
56
  public_suffix (3.0.1)
@@ -60,7 +60,7 @@ GEM
60
60
  rack-test (0.8.2)
61
61
  rack (>= 1.0, < 3)
62
62
  rake (10.5.0)
63
- recursive-open-struct (1.0.5)
63
+ recursive-open-struct (1.1.0)
64
64
  rspec (3.7.0)
65
65
  rspec-core (~> 3.7.0)
66
66
  rspec-expectations (~> 3.7.0)
@@ -82,7 +82,7 @@ GEM
82
82
  simplecov-html (0.10.2)
83
83
  thread_safe (0.3.6)
84
84
  timecop (0.9.1)
85
- tzinfo (1.2.4)
85
+ tzinfo (1.2.5)
86
86
  thread_safe (~> 0.1)
87
87
  vcr (3.0.3)
88
88
  virtus (1.0.5)
@@ -111,4 +111,4 @@ DEPENDENCIES
111
111
  webmock (~> 3.1)
112
112
 
113
113
  BUNDLED WITH
114
- 1.16.0
114
+ 1.16.5
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  ![grape-jwt-authentication](doc/assets/project.png)
2
2
 
3
- [![Build Status](https://api.travis-ci.org/hausgold/grape-jwt-authentication.svg)](https://travis-ci.org/hausgold/grape-jwt-authentication)
3
+ [![Build Status](https://travis-ci.org/hausgold/grape-jwt-authentication.svg?branch=master)](https://travis-ci.org/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
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/446f3eff18bebff9c174/maintainability)](https://codeclimate.com/github/hausgold/grape-jwt-authentication/maintainability)
6
- [![Test Coverage](https://codeclimate.com/github/hausgold/grape-jwt-authentication/badges/coverage.svg)](https://codeclimate.com/github/hausgold/grape-jwt-authentication/coverage)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/446f3eff18bebff9c174/test_coverage)](https://codeclimate.com/github/hausgold/grape-jwt-authentication/test_coverage)
7
+ [![API docs](https://img.shields.io/badge/docs-API-blue.svg)](https://www.rubydoc.info/gems/grape-jwt-authentication)
7
8
 
8
9
  This gem is dedicated to easily integrate a JWT authentication to your
9
10
  [Grape](https://github.com/ruby-grape/grape) API. The real authentication
@@ -13,6 +14,7 @@ flexible on the JWT verification level.
13
14
  - [Installation](#installation)
14
15
  - [Usage](#usage)
15
16
  - [Grape API](#grape-api)
17
+ - [Helpers](#helpers)
16
18
  - [Configuration](#configuration)
17
19
  - [Authenticator](#authenticator)
18
20
  - [Malformed token handling](#malformed-token-handling)
@@ -72,6 +74,42 @@ module UserApi
72
74
  end
73
75
  ```
74
76
 
77
+ #### Helpers
78
+
79
+ The inclusion of the `Grape::Jwt::Authentication` inserts some helpers to
80
+ access the parsed and original JWT. This can be handy when you need to work
81
+ with the JWT payload or perform some extra calculations with the expiration
82
+ date of it. The following example demonstrated the usage of the helpers.
83
+
84
+ ```ruby
85
+ module UserApi
86
+ class ApiV1 < Grape::API
87
+ # All your fancy Grape API stuff [..]
88
+ version 'v1', using: :path
89
+
90
+ resource :payload do
91
+ desc 'A JWT payload echo service.'
92
+ get do
93
+ # The parsed JWT which has an accessible payload (RecursiveOpenStruct)
94
+ { payload: request_jwt.payload.to_h }
95
+ end
96
+ end
97
+
98
+ resource :token do
99
+ desc 'A JWT echo service.'
100
+ get do
101
+ # The original JWT parsed from the HTTP authorization header
102
+ { token: original_request_jwt }
103
+ end
104
+ end
105
+
106
+ # Enable JWT authentication on this API
107
+ include Grape::Jwt::Authentication
108
+ auth :jwt
109
+ end
110
+ end
111
+ ```
112
+
75
113
  ### Configuration
76
114
 
77
115
  This gem is quite customizable and flexible to fulfill your needs. You can make
@@ -376,8 +414,8 @@ end
376
414
  ## Development
377
415
 
378
416
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
379
- `rake spec` to run the tests. You can also run `bin/console` for an interactive
380
- prompt that will allow you to experiment.
417
+ `bundle exec rake spec` to run the tests. You can also run `bin/console` for an
418
+ interactive prompt that will allow you to experiment.
381
419
 
382
420
  To install this gem onto your local machine, run `bundle exec rake install`. To
383
421
  release a new version, update the version number in `version.rb`, and then run
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'grape/jwt/authentication/version'
6
6
 
@@ -22,14 +22,14 @@ Gem::Specification.new do |spec|
22
22
  spec.require_paths = ['lib']
23
23
 
24
24
  spec.add_development_dependency 'bundler', '~> 1.16'
25
+ spec.add_development_dependency 'rack', '~> 2.0'
26
+ spec.add_development_dependency 'rack-test', '~> 0.8.2'
25
27
  spec.add_development_dependency 'rake', '~> 10.0'
26
28
  spec.add_development_dependency 'rspec', '~> 3.0'
27
29
  spec.add_development_dependency 'simplecov', '~> 0.15'
30
+ spec.add_development_dependency 'timecop', '~> 0.9.1'
28
31
  spec.add_development_dependency 'vcr', '~> 3.0'
29
32
  spec.add_development_dependency 'webmock', '~> 3.1'
30
- spec.add_development_dependency 'timecop', '~> 0.9.1'
31
- spec.add_development_dependency 'rack', '~> 2.0'
32
- spec.add_development_dependency 'rack-test', '~> 0.8.2'
33
33
 
34
34
  spec.add_runtime_dependency 'activesupport', '>= 3.2.0'
35
35
  spec.add_runtime_dependency 'grape', '~> 1.0'
@@ -58,6 +58,27 @@ module Grape
58
58
  Grape::Middleware::Auth::Strategies.add(:jwt,
59
59
  JwtHandler,
60
60
  ->(opts) { [opts] })
61
+
62
+ helpers do
63
+ # Get the parsed JWT from the authorization header of the current
64
+ # request. You could use it to access the payload or the expiration
65
+ # date, etc inside your API definition. When the authenticator stated
66
+ # that the validation failed, then the parsed token is +nil+.
67
+ #
68
+ # @return [Grape::Jwt::Authentication::Jwt, nil] the parsed token
69
+ def request_jwt
70
+ env['grape_jwt_auth.parsed_token']
71
+ end
72
+
73
+ # Get the original JWT from the authorization header of the current
74
+ # request, without further changes. You could use it to display a
75
+ # custom error or to parse it differently.
76
+ #
77
+ # @return [String] the JWT from the authorization header
78
+ def original_request_jwt
79
+ env['grape_jwt_auth.original_token']
80
+ end
81
+ end
61
82
  end
62
83
  end
63
84
  end
@@ -63,6 +63,7 @@ module Grape
63
63
  def expires_at
64
64
  exp = payload.exp
65
65
  return nil unless exp
66
+
66
67
  Time.zone.at(exp)
67
68
  end
68
69
 
@@ -15,8 +15,12 @@ module Grape
15
15
  # A internal exception handling for malformed headers.
16
16
  class MalformedHeaderError < StandardError; end
17
17
 
18
+ # A generic JWT part, the full token contains three parts
19
+ # separated by a period.
20
+ JWT_PART_REGEX = /([a-zA-Z0-9\-_]+)?/.freeze
21
+
18
22
  # A common JWT validation regex which meets the RFC specs.
19
- JWT_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/
23
+ JWT_REGEX = Regexp.new("^#{([JWT_PART_REGEX] * 3).join('\.')}$").freeze
20
24
 
21
25
  # Initialize a new Rack middleware for Bearer token
22
26
  # processing.
@@ -76,12 +80,30 @@ module Grape
76
80
  def parse_token(header)
77
81
  token = header.to_s.scan(/^Bearer (.*)/).flatten.first
78
82
  raise MalformedHeaderError unless JWT_REGEX =~ token
83
+
79
84
  token
80
85
  end
81
86
 
87
+ # Inject the token to the environment as a parsed version. This allows
88
+ # further usage like extracting the subject from the payload when the
89
+ # verification was valid.
90
+ #
91
+ # @param env [Hash{String => Mixed}] the Rack environment
92
+ # @param token [String] the token parsed from the HTTP header
93
+ def inject_token_into_env(env, token)
94
+ env['grape_jwt_auth.parsed_token'] = Jwt.new(token)
95
+ rescue *Jwt::RESCUE_JWT_EXCEPTIONS
96
+ env['grape_jwt_auth.parsed_token'] = nil
97
+ ensure
98
+ env['grape_jwt_auth.original_token'] = token
99
+ end
100
+
82
101
  # Perform the authentication logic on the Rack compatible
83
102
  # interface.
84
103
  #
104
+ # @param env [Hash{String => Mixed}] the Rack environment
105
+ #
106
+ # rubocop:disable Metrics/AbcSize because thats the auth handling core
85
107
  # :reek:TooManyStatements because reek counts exception
86
108
  # handling as statements
87
109
  def call(env)
@@ -94,11 +116,16 @@ module Grape
94
116
  # errors, that why we invoke the formatter middleware here.
95
117
  Grape::Middleware::Formatter.new(->(_) {}).call(env)
96
118
 
97
- # Parse the JWT token and give it to the user defined block
119
+ # Parse the JWT token from the request headers.
120
+ token = parse_token(env['HTTP_AUTHORIZATION'])
121
+
122
+ # Inject the parsed token to the Rack environment.
123
+ inject_token_into_env(env, token)
124
+
125
+ # Give the parsed token to the user defined block
98
126
  # for futher verification. The user given block MUST return
99
127
  # a positive result to allow the request to be further
100
128
  # processed, or a negative result to stop processing.
101
- token = parse_token(env['HTTP_AUTHORIZATION'])
102
129
  raise AuthenticationError unless authenticator.call(token)
103
130
 
104
131
  # Looks like we are on a good path and the given token was
@@ -112,6 +139,7 @@ module Grape
112
139
  # Call the user defined failed authentication handler.
113
140
  failed_handler.call(token, @app)
114
141
  end
142
+ # rubocop:enable Metrics/AbcSize
115
143
  end
116
144
  end
117
145
  end
@@ -61,6 +61,7 @@ module Grape
61
61
  # @return [String] The encoded public key
62
62
  def fetch_encoded_key
63
63
  raise ArgumentError, 'No URL for RsaPublicKey configured' unless url
64
+
64
65
  if remote?
65
66
  HTTParty.get(url).body
66
67
  else
@@ -3,7 +3,7 @@
3
3
  module Grape
4
4
  module Jwt
5
5
  module Authentication
6
- VERSION = '1.0.1'
6
+ VERSION = '1.1.0'.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.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hermann Mayer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-23 00:00:00.000000000 Z
11
+ date: 2018-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,49 +25,49 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.16'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '2.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rack-test
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: 0.8.2
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: 0.8.2
55
55
  - !ruby/object:Gem::Dependency
56
- name: simplecov
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.15'
61
+ version: '10.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.15'
68
+ version: '10.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: vcr
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
@@ -81,19 +81,19 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: webmock
84
+ name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.1'
89
+ version: '0.15'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.1'
96
+ version: '0.15'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: timecop
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -109,33 +109,33 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.9.1
111
111
  - !ruby/object:Gem::Dependency
112
- name: rack
112
+ name: vcr
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '2.0'
117
+ version: '3.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '2.0'
124
+ version: '3.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: rack-test
126
+ name: webmock
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.8.2
131
+ version: '3.1'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 0.8.2
138
+ version: '3.1'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: activesupport
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -213,9 +213,11 @@ executables: []
213
213
  extensions: []
214
214
  extra_rdoc_files: []
215
215
  files:
216
+ - ".editorconfig"
216
217
  - ".gitignore"
217
218
  - ".rspec"
218
219
  - ".rubocop.yml"
220
+ - ".simplecov"
219
221
  - ".travis.yml"
220
222
  - CHANGELOG.md
221
223
  - Gemfile
@@ -254,7 +256,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
256
  version: '0'
255
257
  requirements: []
256
258
  rubyforge_project:
257
- rubygems_version: 2.6.13
259
+ rubygems_version: 2.7.7
258
260
  signing_key:
259
261
  specification_version: 4
260
262
  summary: A reusable Grape JWT authentication concern