warden-auth0 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6535f50d8f192c86cebdd135e411c1e7d28f54c2681a4a3993b730dfaed368b5
4
+ data.tar.gz: 0df77297cee513a2eb030e6456f5c4b38b7a3780c8e34682e5dea388f7c50303
5
+ SHA512:
6
+ metadata.gz: 4438b8d430ce357ce55bf6b9088ba27a38e00f7d9232e615fd71cda465e77aef224bea62679211edbf4f0bb99d3ab4ea354be9bf5c1ce46798dbfbbee18bbe60
7
+ data.tar.gz: 9c2b3dcb75741bab6732faf2d5876b2d07b8e42978f4baa7e5e478ecc23f019f8e78dce919d4d04b5a09e2b82364710dd188a0960c6eb6e8abaa285730efd017
data/.codeclimate.yml ADDED
@@ -0,0 +1,17 @@
1
+ engines:
2
+ duplication:
3
+ enabled: true
4
+ config:
5
+ languages:
6
+ - ruby
7
+ fixme:
8
+ enabled: true
9
+ rubocop:
10
+ enabled: true
11
+ ratings:
12
+ paths:
13
+ - "**.rb"
14
+ exclude_paths:
15
+ - spec/
16
+ - Gemfile
17
+ - warden-jwt_auth.gemspec
@@ -0,0 +1 @@
1
+ github: waiting-for-dev
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .overcommit_gems.rb.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,51 @@
1
+ require: rubocop-rspec
2
+ AllCops:
3
+ TargetRubyVersion: 2.7
4
+ Exclude:
5
+ - Gemfile
6
+ - warden-jwt_auth.gemspec
7
+ - spec/support/shared_contexts/*rb
8
+ - vendor/**/*
9
+ RSpec/NestedGroups:
10
+ Max: 3
11
+ RSpec/MessageExpectation:
12
+ EnforcedStyle: 'expect'
13
+ Metrics/BlockLength:
14
+ Exclude:
15
+ - "spec/**/*.rb"
16
+ Style/SafeNavigation:
17
+ Enabled: false
18
+ Layout/EmptyLinesAroundAttributeAccessor:
19
+ Enabled: true
20
+ Layout/SpaceAroundMethodCallOperator:
21
+ Enabled: true
22
+ Lint/DeprecatedOpenSSLConstant:
23
+ Enabled: true
24
+ Lint/MixedRegexpCaptureTypes:
25
+ Enabled: true
26
+ Lint/RaiseException:
27
+ Enabled: true
28
+ Lint/StructNewOverride:
29
+ Enabled: true
30
+ Style/AccessorGrouping:
31
+ Enabled: true
32
+ Style/BisectedAttrAccessor:
33
+ Enabled: true
34
+ Style/ExponentialNotation:
35
+ Enabled: true
36
+ Style/HashEachMethods:
37
+ Enabled: true
38
+ Style/HashTransformKeys:
39
+ Enabled: true
40
+ Style/HashTransformValues:
41
+ Enabled: true
42
+ Style/RedundantAssignment:
43
+ Enabled: true
44
+ Style/RedundantFetchBlock:
45
+ Enabled: true
46
+ Style/RedundantRegexpCharacterClass:
47
+ Enabled: true
48
+ Style/RedundantRegexpEscape:
49
+ Enabled: true
50
+ Style/SlicingWithRange:
51
+ Enabled: true
data/.travis.yml ADDED
@@ -0,0 +1,21 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.6
5
+ - 2.7
6
+ - 3.0
7
+ - ruby-head
8
+ before_install:
9
+ - gem update --system --no-doc
10
+ - gem install bundler
11
+ script:
12
+ - bundle exec rspec
13
+ - bundle exec rubocop
14
+ - bundle exec codeclimate-test-reporter
15
+ jobs:
16
+ allow_failures:
17
+ - rvm: ruby-head
18
+ addons:
19
+ code_climate:
20
+ repo_token:
21
+ secure: neJ5LVLV6vgeCnerSQjUpLuQDvxEH87iW8swCSWl2hTtPcD/GuwYSeSXnhH72HVHi/9basHHhaYPcE2YeBwBCr39PhiHMNwS5GGGk/RGjKpU/Gt1KXV8KXTbNGT4v+ZMM3cdsdDfe8OnzGguNVsdxseHa3KE2pyuvo2a0swXwKa7BU9VB/3ZoZvvfI3Xr9im4eklWam5yCwVR0FOF7epzmNTKMXcUga2BOc9PV5aVELzLILLCHCJSCupe5Rx8mfcsRoRmZXKduF8Ke3eq8eULvLEo4EGfC107najOqrKt7x8uDVIsuGrP4LUQ4ainmNEb2jIvpjuqAxpusMjhpjCINF1Tn0OXK93OXAp4QKeIYoYEqKtzRxX0TWFNWHB8ombF9HTMF2DmloDZyFRiI40JSMImU0hc4MDxRgiTW5MDWGbohDaJ+9VV6+rIqtlEfLhgj1grFBAroaJce9BB7RQEmfsZPzhC2VXwGxHw/YkJgzBNGq1/9E1DoTY9RPSNTQfSRodhI3XW8LSQSHTBeXZvymVcjeOyYgjzJYviLHR8QS4cXpUALtlFXyaMkPHUBLUn8XsBa5Azfh5y3qPMGiJq1/qaHA4mKj5ls+ngFbzOq82sYGAKgQHj/ZDb+FZMQQanp4jyWADKcpXcmINb9jEQwkU0bjpuhUYtghASxH1Kl8=
data/CHANGELOG.md ADDED
@@ -0,0 +1,97 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/).
6
+
7
+ ## [0.8.0] - 2024-06-28
8
+ - Add support for issue claim ([56](https://github.com/waiting-for-dev/warden-jwt_auth/pull/56))
9
+
10
+ ## [0.8.0] - 2023-01-31
11
+ - Add support for secret rotation ([49](https://github.com/waiting-for-dev/warden-jwt_auth/pull/49))
12
+ - Support dry-* v1 ([52](https://github.com/waiting-for-dev/warden-jwt_auth/pull/52))
13
+
14
+ ## [0.7.0] - 2022-09-12
15
+ - Support asymmetric algorithms ([40](https://github.com/waiting-for-dev/warden-jwt_auth/issues/40))
16
+
17
+ ## [0.6.0] - 2021-09-21
18
+ - Support ruby 3.0 and deprecate 2.5
19
+ - Fixed dry-configurable compatibility. ([28](https://github.com/waiting-for-dev/warden-jwt_auth/issues/28))
20
+
21
+ ## [0.5.0]
22
+ ### Fixed
23
+ - Fixed dry-configurable compatibility. ([28](https://github.com/waiting-for-dev/warden-jwt_auth/issues/28))
24
+
25
+ ## [0.4.2] - 2020-03-19
26
+ ### Fixed
27
+ - Lock dry-configurable dependency to fix upstream regression. ([21](https://github.com/waiting-for-dev/warden-jwt_auth/issues/21))
28
+ - Fix ruby 2.7 warnings (@trevorrjohn [23](https://github.com/waiting-for-dev/warden-jwt_auth/pull/23) )
29
+
30
+ ## [0.4.1] - 2020-02-23
31
+ ### Fixed
32
+ - Upgrade dry-configurable dependency to fix upstream bug preventing
33
+ warden-jwt_auth to be loaded ([21](https://github.com/waiting-for-dev/warden-jwt_auth/issues/21)).
34
+
35
+ ## [0.4.0] - 2019-08-01
36
+ ### Added
37
+ - Allow configuration of the signing algorithm ([19](https://github.com/waiting-for-dev/warden-jwt_auth/pull/19)].
38
+
39
+ ## [0.3.6] - 2019-03-29
40
+ ### Fixed
41
+ - Update depencies.
42
+
43
+ ## [0.3.5] - 2018-01-30
44
+ ### Fixed
45
+ - Do not disallow fetching JWT scopes from session
46
+
47
+ ## [0.3.4] - 2018-01-09
48
+ ### Fixed
49
+ - Do not log out from session for standard AJAX requests
50
+
51
+ ## [0.3.3] - 2017-12-31
52
+ ### Fixed
53
+ - Check it is not a html request when disallowing fetching from session
54
+
55
+ ## [0.3.2] - 2017-12-23
56
+ ### Fixed
57
+ - Do not couple `aud_header` env value to the setting
58
+
59
+ ## [0.3.1] - 2017-12-11
60
+ ### Added
61
+ - Ensure JWT scopes are not fetched from session. Workaround for
62
+ https://github.com/hassox/warden/pull/118
63
+
64
+ ## [0.3.0] - 2017-12-06
65
+ ### Added
66
+ - Add and call hook method `on_jwt_dispatch` on user instance
67
+ - Encode and validate an `aud` claim from the request headers
68
+
69
+ ## [0.2.1] - 2017-12-04
70
+ ### Added
71
+ - Allow configuring classes as strings
72
+
73
+ ### Fixed
74
+ - Take `PATH_INFO` as an empty string when it is not present
75
+
76
+ ## [0.2.0] - 2017-11-23
77
+ ### Added
78
+ - `fail!` with message
79
+
80
+ ### Fixed
81
+ - Unauthorize when fetched user is nil
82
+
83
+ ## [0.1.4] - 2017-11-21
84
+ ### Fixed
85
+ - Update `jwt` dependency
86
+
87
+ ## [0.1.3] - 2017-04-15
88
+ ### Fixed
89
+ - Coerce `sub` to string to conform with JWT specification
90
+
91
+ ## [0.1.2] - 2017-04-13
92
+ ### Fixed
93
+ - Ignore expired tokens on revocation instead of fail
94
+
95
+ ## [0.1.1] - 2017-02-28
96
+ ### Fixed
97
+ - Explicit require of `securerandom` standard library
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at marc@lamarciana.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Dockerfile ADDED
@@ -0,0 +1,5 @@
1
+ FROM ruby:3.0.0
2
+ ENV APP_USER warden_jwt_auth_user
3
+ RUN useradd -ms /bin/bash $APP_USER
4
+ USER $APP_USER
5
+ WORKDIR /home/$APP_USER/app
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in warden-jwt_auth.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Marc Busqué
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # Warden::Auth0
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/warden-jwt_auth.svg)](https://badge.fury.io/rb/warden-jwt_auth)
4
+ [![Build Status](https://travis-ci.org/waiting-for-dev/warden-jwt_auth.svg?branch=master)](https://travis-ci.org/waiting-for-dev/warden-jwt_auth)
5
+ [![Code Climate](https://codeclimate.com/github/waiting-for-dev/warden-jwt_auth/badges/gpa.svg)](https://codeclimate.com/github/waiting-for-dev/warden-jwt_auth)
6
+ [![Test Coverage](https://codeclimate.com/github/waiting-for-dev/warden-jwt_auth/badges/coverage.svg)](https://codeclimate.com/github/waiting-for-dev/warden-jwt_auth/coverage)
7
+
8
+ `warden-jwt_auth` is a [warden](https://github.com/hassox/warden) extension which uses [JWT](https://jwt.io/) tokens for user authentication. It follows [secure by default](https://en.wikipedia.org/wiki/Secure_by_default) principle.
9
+
10
+ This gem is just a replacement for cookies when these can't be used. As
11
+ cookies, a token expired with `warden-jwt_auth` will mandatorily have an
12
+ expiration time. If you need that your users never sign out, you will be better
13
+ off with a solution using refresh tokens, like some implementation of OAuth2.
14
+
15
+ You can read about which security concerns this library takes into account and about JWT generic secure usage in the following series of posts:
16
+
17
+ - [Stand Up for JWT Revocation](http://waiting-for-dev.github.io/blog/2017/01/23/stand_up_for_jwt_revocation)
18
+ - [JWT Revocation Strategies](http://waiting-for-dev.github.io/blog/2017/01/24/jwt_revocation_strategies)
19
+ - [JWT Secure Usage](http://waiting-for-dev.github.io/blog/2017/01/25/jwt_secure_usage)
20
+ - [A secure JWT authentication implementation for Rack and Rails](http://waiting-for-dev.github.io/blog/2017/01/26/a_secure_jwt_authentication_implementation_for_rack_and_rails)
21
+
22
+ If what you need is a JWT authentication library for [devise](https://github.com/plataformatec/devise), better look at [devise-jwt](https://github.com/waiting-for-dev/devise-jwt), which is just a thin layer on top of this gem.
23
+
24
+ ## Installation
25
+
26
+ ```ruby
27
+ gem 'warden-jwt_auth'
28
+ ```
29
+
30
+ And then execute:
31
+
32
+ $ bundle
33
+
34
+ Or install it yourself as:
35
+
36
+ $ gem install warden-jwt_auth
37
+
38
+ ## Usage
39
+
40
+ You can look at this gem's wiki to see some [example applications](https://github.com/waiting-for-dev/warden-jwt_auth/wiki). Please, add yours if you think it can help somebody.
41
+
42
+ At its core, this library consists of:
43
+
44
+ - A Warden strategy that authenticates a user if a valid JWT token is present in the request headers.
45
+ - A rack middleware which adds a JWT token to the response headers in configured requests.
46
+ - A rack middleware which revokes JWT tokens in configured requests.
47
+
48
+ As you see, JWT revocation is supported. I wrote [why I think JWT tokens revocation is useful and needed](http://waiting-for-dev.github.io/blog/2017/01/23/stand_up_for_jwt_revocation/).
49
+
50
+ ### Secret key configuration
51
+
52
+ First of all, you have to configure the secret key that will be used to sign generated tokens.
53
+
54
+ ```ruby
55
+ Warden::Auth0.configure do |config|
56
+ config.secret = ENV['WARDEN_JWT_SECRET_KEY']
57
+ end
58
+ ```
59
+
60
+ **Important:** You are encouraged to use a dedicated secret key, different than others in use in your application. If several components share the same secret key, chances that a vulnerability in one of them has a wider impact increase. Also, never share your secrets pushing it to a remote repository, you are better off using an environment variable like in the example.
61
+
62
+ Currently, HS256 algorithm is the default.
63
+ Configure the matching secret and algorithm name to use a different one (e.g. RS256) (see [ruby-jwt](https://github.com/jwt/ruby-jwt#algorithms-and-usage) to see which are supported)
64
+ ```ruby
65
+ Warden::Auth0.configure do |config|
66
+ config.secret = OpenSSL::PKey::RSA.new(ENV['WARDEN_JWT_SECRET_KEY'])
67
+ config.algorithm = ENV['WARDEN_JWT_ALGORITHM']
68
+ end
69
+ ```
70
+
71
+ If the algorithm is asymmetric (e.g. RS256) and necessitates a different decoding secret than the encoding secret, configure the `decoding_secret` setting as well.
72
+
73
+ ```ruby
74
+ Warden::Auth0.configure do |config|
75
+ config.secret = OpenSSL::PKey::RSA.new(ENV['WARDEN_JWT_PRIVATE_KEY'])
76
+ config.decoding_secret = OpenSSL::PKey::RSA.new(ENV['WARDEN_JWT_PUBLIC_KEY'])
77
+ config.algorithm = 'RS256' # or other asymmetric algorithm
78
+ end
79
+ ```
80
+
81
+ ### Warden scopes configuration
82
+
83
+ You have to map the warden scopes that will be authenticatable through JWT, with the user repositories from where these scope user records can be fetched. If a string is supplied, the user repository will first be looked up as a constant.
84
+
85
+ For instance:
86
+
87
+ ```ruby
88
+ config.mappings = { user: UserRepository }
89
+ ```
90
+
91
+ For this example, `UserRepository` must implement a method `find_for_jwt_authentication` that takes as argument the `sub` claim in the JWT payload. This method should return a user record from `:user` scope:
92
+
93
+ ```ruby
94
+ module UserRepository
95
+ # @returns User
96
+ def self.find_for_jwt_authentication(sub)
97
+ Repo.find_user_by_id(sub)
98
+ end
99
+ end
100
+ ```
101
+
102
+ User records must implement a `jwt_subject` method returning what should be encoded in the `sub` claim on dispatch time. Be aware that what is returned must be coercible to string in order to conform with [RFC7519 standard for `sub` claim](https://tools.ietf.org/html/rfc7519#section-4.1.2).
103
+
104
+ ```ruby
105
+ User = Struct.new(:id, :name)
106
+ def jwt_subject
107
+ id
108
+ end
109
+ end
110
+ ```
111
+
112
+ User records may also implement a `jwt_payload` method, which gives it a chance to add something to the JWT payload:
113
+
114
+ ```ruby
115
+ def jwt_payload
116
+ { 'foo' => 'bar' }
117
+ end
118
+ ```
119
+
120
+ Just when a token is going to be dispatched to a client, a hook method `on_jwt_dispatch` is invoked, only when it exist, on the user record. This method takes the `token` and the `payload` as arguments.
121
+
122
+ ```ruby
123
+ def on_jwt_dispatch(token, payload)
124
+ # Do something
125
+ end
126
+ ```
127
+
128
+ ### Middlewares addition
129
+
130
+ You need to add `Warden::Auth0::Middleware` to your rack middlewares stack. Actually, it is just a wrapper which adds two middlewares that do the actual job: dispatching tokens and revoking tokens.
131
+
132
+ ### Token dispatch configuration
133
+
134
+ You need to tell which requests will dispatch tokens for the user that has been previously authenticated (usually through some other warden strategy, such as one requiring username and email parameters).
135
+
136
+ To configure it, you must provide a bidimensional array, each item being an array of two elements: the request method and a regular expression that must match the request path.
137
+
138
+ For example:
139
+
140
+ ```ruby
141
+ config.dispatch_requests = [
142
+ ['POST', %r{^/sign_in$}]
143
+ ]
144
+ ```
145
+
146
+ **Important**: You are encouraged to delimit your regular expression with `^` and `$` to avoid unintentional matches.
147
+
148
+ Tokens will be returned in the `Authorization` response header (configurable via `config.token_header`), with format `Bearer #{token}`.
149
+
150
+ ### Requests authentication
151
+
152
+ Once you have a valid token, you can authenticate following requests providing the token in the `Authorization` request header, with format `Bearer #{token}`.
153
+
154
+ ### Revocation configuration
155
+
156
+ You need to tell which requests will revoke incoming JWT tokens.
157
+
158
+ To configure it, you must provide a bidimensional array, each item being an array of two elements: the request method and a regular expression that must match the request path.
159
+
160
+ For example:
161
+
162
+ ```ruby
163
+ config.revocation_requests = [
164
+ ['DELETE', %r{^/sign_out$}]
165
+ ]
166
+ ```
167
+
168
+ **Important**: You are encouraged to delimit your regular expression with `^` and `$` to avoid unintentional matches.
169
+
170
+ Besides, you need to configure which revocation strategy will be used for each scope. If a string is supplied, the revocation strategy will first be looked up as a constant.
171
+
172
+ ```ruby
173
+ config.revocation_strategies = { user: RevocationStrategy }
174
+ ```
175
+
176
+ The implementation of the revocation strategy is also on your side. They just need to implement two methods: `jwt_revoked?` and `revoke_jwt`, both of them accepting as parameters the JWT payload and the user record, in this order.
177
+
178
+ You can read about which [JWT recovation strategies](http://waiting-for-dev.github.io/blog/2017/01/24/jwt_revocation_strategies/) can be implement with their pros and cons.
179
+
180
+ ```ruby
181
+ module RevocationStrategy
182
+ def self.jwt_revoked?(payload, user)
183
+ # Does something to check whether the JWT token is revoked for given user
184
+ end
185
+
186
+ def self.revoke_jwt(payload, user)
187
+ # Does something to revoke the JWT token for given user
188
+ end
189
+ end
190
+ ```
191
+
192
+ ### Requesting client validation
193
+
194
+ Authentication will be refused if a client requesting to be authenticated through a token is not the same to which it was originally issued. To do so, the content of the header `JWT_AUD` (configurable via `config.aud_header`) is stored as `aud` claim. If you don't want to differentiate between clients, you don't need to provide that header.
195
+
196
+ **Important:** Be aware that this workflow is not bullet proof. In some scenarios a user can handcraft the request headers, therefore being able to impersonate any client. In such cases you could need something more robust, like an OAuth workflow with client id and client secret.
197
+
198
+ ### Secret rotation
199
+
200
+ Secret rotation is supported by setting `rotation_secret`. Set the new secret as the `secret` and copy the previous secret to `rotation_secret`
201
+
202
+ ```ruby
203
+ Warden::Auth0.configure do |config|
204
+ config.secret = ENV['WARDEN_JWT_SECRET_KEY']
205
+ config.rotation_secret = ENV['WARDEN_JWT_SECRET_KEY_ROTATION']
206
+ end
207
+ ```
208
+
209
+ You can remove the `rotation_secret` when you are condifent that large enough user base has the fetched the token encrypted with the new secret.
210
+
211
+ ### Multiple issuers
212
+
213
+ When your application handles JWT tokens from multiple sources (e.g. webhooks authenticated via provider JTW tokens) you can configure this gem to use the [issuer claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1) to only handle tokens it has issued.
214
+
215
+ ```ruby
216
+ Warden::Auth0.configure do |config|
217
+ config.secret = ENV['WARDEN_JWT_SECRET_KEY']
218
+ config.issuer = 'http://my-application.com'
219
+ end
220
+ ```
221
+
222
+ ## Development
223
+
224
+ There are docker and docker-compose files configured to create a development environment for this gem. So, if you use Docker you only need to run:
225
+
226
+ `docker-compose up -d`
227
+
228
+ An then, for example:
229
+
230
+ `docker-compose exec app rspec`
231
+
232
+ ## Contributing
233
+
234
+ Bug reports and pull requests are welcome on GitHub at https://github.com/waiting-for-dev/warden-jwt_auth. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
235
+
236
+ ## Release Policy
237
+
238
+ `warden-jwt_auth` follows the principles of [semantic versioning](http://semver.org/).
239
+
240
+ ## License
241
+
242
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
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
data/bin/console ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # !/usr/bin/env ruby
4
+
5
+ require 'bundler/setup'
6
+ require 'warden/jwt_auth'
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+
11
+ # (If you use this, don't forget to add pry to your Gemfile!)
12
+ # require "pry"
13
+ # Pry.start
14
+
15
+ require 'irb'
16
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ version: '2'
2
+ services:
3
+ app:
4
+ build: .
5
+ image: warden_jwt_auth
6
+ command: bash -c "bundle && tail -f Gemfile"
7
+ volumes:
8
+ - .:/home/warden_jwt_auth_user/app
9
+ tty: true
10
+ stdin_open: true
11
+ tmpfs:
12
+ - /tmp
data/issue_template.md ADDED
@@ -0,0 +1,25 @@
1
+ Please, for a bug report fill in the following template. Before that, make sure to read the whole [README](https://github.com/waiting-for-dev/warden-jwt_auth/blob/master/README.md).
2
+
3
+ Feature requests and questions about `warden-jwt_auth` are also accepted.
4
+
5
+ ## Expected behavior
6
+
7
+ ## Actual behavior
8
+
9
+ ## Steps to Reproduce the Problem
10
+
11
+ 1.
12
+ 2.
13
+ 3.
14
+
15
+ ## Debugging information
16
+
17
+ Provide following information. Please, format pasted output as code. Feel free to remove the secret key value.
18
+
19
+ - Version of `warden-jwt_auth` in use
20
+ - Output of `Warden::Auth0.config`
21
+ - If your issue is related with not getting a JWT from the server:
22
+ - Involved request path, method and request headers
23
+ - Response headers for that request
24
+ - If your issue is related with not being able to revoke a JWT:
25
+ - Involved request path, method and request headers
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warden
4
+ module Auth0
5
+ # Helper functions to centralize working with rack env.
6
+ #
7
+ # It follows
8
+ # [rack](http://www.rubydoc.info/github/rack/rack/file/SPEC#The_Environment)
9
+ # and [PEP 333](https://www.python.org/dev/peps/pep-0333/#environ-variables)
10
+ # conventions.
11
+ module EnvHelper
12
+ # Returns PATH_INFO environment variable
13
+ #
14
+ # @param env [Hash] Rack env
15
+ # @return [String]
16
+ def self.path_info(env)
17
+ env['PATH_INFO'] || ''
18
+ end
19
+
20
+ # Returns REQUEST_METHOD environment variable
21
+ #
22
+ # @param env [Hash] Rack env
23
+ # @return [String]
24
+ def self.request_method(env)
25
+ env['REQUEST_METHOD']
26
+ end
27
+
28
+ # Returns header configured through `token_header` option
29
+ #
30
+ # @param env [Hash] Rack env
31
+ # @return [String]
32
+ def self.authorization_header(env)
33
+ header_env_name = env_name(Auth0.config.token_header)
34
+ env[header_env_name]
35
+ end
36
+
37
+ # Returns a copy of `env` with value added to the environment variable
38
+ # configured through `token_header` option
39
+ #
40
+ # Be aware than `env` is not modified in place and still an updated copy
41
+ # is returned.
42
+ #
43
+ # @param env [Hash] Rack env
44
+ # @param value [String]
45
+ # @return [Hash] modified rack env
46
+ def self.set_authorization_header(env, value)
47
+ env = env.dup
48
+ header_env_name = env_name(Auth0.config.token_header)
49
+ env[header_env_name] = value
50
+ env
51
+ end
52
+
53
+ # Returns the ENV name for a given header
54
+ #
55
+ # @param header [String] Header name
56
+ # @return [String]
57
+ def self.env_name(header)
58
+ ('HTTP_' + header.upcase).tr('-', '_')
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warden
4
+ module Auth0
5
+ module Errors
6
+ # Error raised when trying to decode a token that has been revoked for an
7
+ # user
8
+ class RevokedToken < JWT::DecodeError
9
+ end
10
+
11
+ # Error raised when no issuer has been configured
12
+ class NoConfiguredIssuer < JWT::DecodeError
13
+ end
14
+
15
+ # Error raised when no aud has been configured
16
+ class NoConfiguredAud < JWT::DecodeError
17
+ end
18
+
19
+ # Error raised when the user decoded from a token is nil
20
+ class NilUser < JWT::DecodeError
21
+ end
22
+
23
+ # Error raised when trying to decode a token whose "issuer" does not match the expected one
24
+ class WrongIssuer < JWT::DecodeError
25
+ end
26
+
27
+ # Error raised when trying to decode a token for an scope that doesn't
28
+ # match the one encoded in the payload
29
+ class WrongScope < JWT::DecodeError
30
+ end
31
+
32
+ # Error raised when trying to decode a token which `aud` claim does not
33
+ # match with the expected one
34
+ class WrongAud < JWT::DecodeError
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warden
4
+ module Auth0
5
+ # Helpers to parse token from a request and to a response
6
+ module HeaderParser
7
+ # Method for `Authorization` header. Token is present in request/response
8
+ # headers as `Bearer %token%`
9
+ METHOD = 'Bearer'
10
+
11
+ # Parses the token from a rack request
12
+ #
13
+ # @param env [Hash] rack env hash
14
+ # @return [String] JWT token
15
+ # @return [nil] if token is not present
16
+ def self.from_env(env)
17
+ auth = EnvHelper.authorization_header(env)
18
+ return nil unless auth
19
+
20
+ method, token = auth.split
21
+ method == METHOD ? token : nil
22
+ end
23
+
24
+ # Returns a copy of `env` with token added to the header configured through
25
+ # `token_header` option. Be aware than `env` is not modified in place.
26
+ #
27
+ # @param env [Hash] rack env hash
28
+ # @param token [String] JWT token
29
+ # @return [Hash] modified rack env
30
+ def self.to_env(env, token)
31
+ EnvHelper.set_authorization_header(env, "#{METHOD} #{token}")
32
+ end
33
+
34
+ # Returns a copy of headers with token added in the `Authorization` key.
35
+ # Be aware that headers is not modified in place
36
+ #
37
+ # @param headers [Hash] rack hash response headers
38
+ # @param token [String] JWT token
39
+ # @return [Hash] response headers with the token added
40
+ def self.to_headers(headers, token)
41
+ headers = headers.dup
42
+ headers[Auth0.config.token_header] = "#{METHOD} #{token}"
43
+ headers
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'warden'
4
+
5
+ module Warden
6
+ module Auth0
7
+ # Warden strategy to authenticate a user through a JWT token in the
8
+ # `Authorization` request header
9
+ class Strategy < Warden::Strategies::Base
10
+ def valid?
11
+ token_exists? && issuer_claim_valid? && aud_claim_valid?
12
+ end
13
+
14
+ def store?
15
+ false
16
+ end
17
+
18
+ def authenticate!
19
+ raise Errors::WrongIssuer, 'wrong issuer' unless issuer_claim_valid?
20
+
21
+ raise Errors::WrongAud, 'wrong audience' unless aud_claim_valid?
22
+
23
+ user = Warden::Auth0.config.user_resolver.call(decoded_token)
24
+
25
+ raise Warden::Auth0::Errors::NilUser, 'nil user' unless user
26
+
27
+ success!(user)
28
+ rescue JWT::DecodeError => e
29
+ puts "Failing to authenticate with #{e.message}"
30
+ fail!(e.message)
31
+ end
32
+
33
+ private
34
+
35
+ def issuer_claim_valid?
36
+ issuer = configured_issuer
37
+ issuer_matches?(decoded_token, issuer)
38
+ rescue JWT::DecodeError
39
+ false
40
+ end
41
+
42
+ def aud_claim_valid?
43
+ aud = configured_aud
44
+ aud_matches?(decoded_token, aud)
45
+ rescue JWT::DecodeError
46
+ false
47
+ end
48
+
49
+ def decoded_token
50
+ TokenDecoder.new.call(token)
51
+ end
52
+
53
+ def configured_aud
54
+ configured_aud = Warden::Auth0.config.aud
55
+ raise Errors::NoConfiguredAud if configured_aud.nil?
56
+
57
+ configured_aud
58
+ end
59
+
60
+ def configured_issuer
61
+ configured_issuer = Warden::Auth0.config.issuer
62
+ raise Errors::NoConfiguredIssuer if configured_issuer.nil?
63
+
64
+ configured_issuer
65
+ end
66
+
67
+ def token_exists?
68
+ !token.nil?
69
+ end
70
+
71
+ def issuer_matches?(payload, issuer)
72
+ payload['iss'] == issuer.to_s
73
+ end
74
+
75
+ def aud_matches?(payload, aud)
76
+ return true if payload['aud'] == aud.to_s
77
+
78
+ payload['aud'].is_a?(Array) && payload['aud'].include?(aud)
79
+ end
80
+
81
+ def token
82
+ @token ||= HeaderParser.from_env(env)
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ Warden::Strategies.add(:auth0, Warden::Auth0::Strategy)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jwt/error'
4
+
5
+ module Warden
6
+ module Auth0
7
+ # Decodes a JWT into a hash payload into a JWT token
8
+ class TokenDecoder
9
+ include Auth0::Import['decoding_secret', 'algorithm']
10
+
11
+ # Decodes the payload from a JWT as a hash
12
+ #
13
+ # @see JWT.decode for all the exceptions than can be raised when given
14
+ # token is invalid
15
+ #
16
+ # @param token [String] a JWT
17
+ # @return [Hash] payload decoded from the JWT
18
+ def call(token)
19
+ decode(token, decoding_secret)
20
+ end
21
+
22
+ private
23
+
24
+ def decode(token, secret)
25
+ JWT.decode(token,
26
+ secret,
27
+ true,
28
+ algorithm: algorithm,
29
+ verify_jti: true)[0]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Warden
4
+ module Auth0
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/configurable'
4
+ require 'dry/auto_inject'
5
+ require 'jwt'
6
+ require 'warden'
7
+
8
+ module Warden
9
+ # Auth0 authentication plugin for warden.
10
+ #
11
+ # It consists of a strategy which tries to authenticate an user decoding a
12
+ # token present in the `Authentication` header (as `Bearer %token%`).
13
+ module Auth0
14
+ extend Dry::Configurable
15
+
16
+ def symbolize_keys(hash)
17
+ hash.transform_keys(&:to_sym)
18
+ end
19
+
20
+ def upcase_first_items(array)
21
+ array.map do |tuple|
22
+ method, path = tuple
23
+ [method.to_s.upcase, path]
24
+ end
25
+ end
26
+
27
+ def constantize_values(hash)
28
+ hash.transform_values do |value|
29
+ value.is_a?(String) ? Object.const_get(value) : value
30
+ end
31
+ end
32
+
33
+ module_function :constantize_values, :symbolize_keys, :upcase_first_items
34
+
35
+ # The secret used to decode the token, defaults to `secret` if not provided
36
+ setting :decoding_secret, constructor: ->(value) { value || config.secret }
37
+
38
+ # Request header that will be used for receiving and returning the token.
39
+ setting :token_header, default: 'Authorization'
40
+
41
+ # The algorithm used to encode the token
42
+ setting :algorithm
43
+
44
+ # The issuer claims associated with the tokens
45
+ #
46
+ # Will be used to only apply the warden strategy when the issuer matches.
47
+ # This allows for multiple token issuers being used.
48
+ # @see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1
49
+ setting :issuer, default: nil
50
+
51
+ # The aud claims associated with the tokens
52
+ #
53
+ # Will be used to only apply the warden strategy when the audience matches.
54
+ setting :aud, default: nil
55
+
56
+ # This is a method that takes in the payload sub and should return a User
57
+ setting :user_resolver
58
+
59
+ Import = Dry::AutoInject(config)
60
+ end
61
+ end
62
+
63
+ require 'warden/auth0/version'
64
+ require 'warden/auth0/errors'
65
+ require 'warden/auth0/header_parser'
66
+ require 'warden/auth0/env_helper'
67
+ require 'warden/auth0/token_decoder'
68
+ require 'warden/auth0/strategy'
@@ -0,0 +1,40 @@
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 'warden/auth0/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'warden-auth0'
9
+ spec.version = Warden::Auth0::VERSION
10
+ spec.authors = ['1KOMMA5º']
11
+
12
+ spec.summary = 'Auth0 authentication for Warden.'
13
+ spec.description = 'Auth0 authentication for Warden, ORM agnostic and accepting the implementation of token revocation strategies.'
14
+ spec.homepage = 'https://github.com/sarakola/warden-jwt_auth'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
23
+
24
+ spec.add_dependency 'dry-auto_inject', '>= 0.8', '< 2'
25
+ spec.add_dependency 'dry-configurable', '>= 0.13', '< 2'
26
+ spec.add_dependency 'jwt', '~> 2.1'
27
+ spec.add_dependency 'warden', '~> 1.2'
28
+
29
+ spec.add_development_dependency 'bundler'
30
+ spec.add_development_dependency 'pry-byebug', '~> 3.7'
31
+ spec.add_development_dependency 'rack-test', '~> 1.1'
32
+ spec.add_development_dependency 'rake', '~> 12.3'
33
+ spec.add_development_dependency 'rspec', '~> 3.8'
34
+ # Cops
35
+ spec.add_development_dependency 'rubocop', '~> 0.87'
36
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.42'
37
+ # Test reporting
38
+ spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0'
39
+ spec.add_development_dependency 'simplecov', '0.17'
40
+ end
metadata ADDED
@@ -0,0 +1,263 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: warden-auth0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 1KOMMA5º
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-09-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-auto_inject
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: dry-configurable
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0.13'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '2'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0.13'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '2'
53
+ - !ruby/object:Gem::Dependency
54
+ name: jwt
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '2.1'
60
+ type: :runtime
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '2.1'
67
+ - !ruby/object:Gem::Dependency
68
+ name: warden
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '1.2'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '1.2'
81
+ - !ruby/object:Gem::Dependency
82
+ name: bundler
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: pry-byebug
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '3.7'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '3.7'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rack-test
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '1.1'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '1.1'
123
+ - !ruby/object:Gem::Dependency
124
+ name: rake
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '12.3'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '12.3'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rspec
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '3.8'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '3.8'
151
+ - !ruby/object:Gem::Dependency
152
+ name: rubocop
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '0.87'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '0.87'
165
+ - !ruby/object:Gem::Dependency
166
+ name: rubocop-rspec
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: '1.42'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: '1.42'
179
+ - !ruby/object:Gem::Dependency
180
+ name: codeclimate-test-reporter
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: '1.0'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: '1.0'
193
+ - !ruby/object:Gem::Dependency
194
+ name: simplecov
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - '='
198
+ - !ruby/object:Gem::Version
199
+ version: '0.17'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - '='
205
+ - !ruby/object:Gem::Version
206
+ version: '0.17'
207
+ description: Auth0 authentication for Warden, ORM agnostic and accepting the implementation
208
+ of token revocation strategies.
209
+ email:
210
+ executables: []
211
+ extensions: []
212
+ extra_rdoc_files: []
213
+ files:
214
+ - ".codeclimate.yml"
215
+ - ".github/FUNDING.yml"
216
+ - ".gitignore"
217
+ - ".rspec"
218
+ - ".rubocop.yml"
219
+ - ".travis.yml"
220
+ - CHANGELOG.md
221
+ - CODE_OF_CONDUCT.md
222
+ - Dockerfile
223
+ - Gemfile
224
+ - LICENSE.txt
225
+ - README.md
226
+ - Rakefile
227
+ - bin/console
228
+ - bin/setup
229
+ - docker-compose.yml
230
+ - issue_template.md
231
+ - lib/warden/auth0.rb
232
+ - lib/warden/auth0/env_helper.rb
233
+ - lib/warden/auth0/errors.rb
234
+ - lib/warden/auth0/header_parser.rb
235
+ - lib/warden/auth0/strategy.rb
236
+ - lib/warden/auth0/token_decoder.rb
237
+ - lib/warden/auth0/version.rb
238
+ - warden-auth0.gemspec
239
+ homepage: https://github.com/sarakola/warden-jwt_auth
240
+ licenses:
241
+ - MIT
242
+ metadata:
243
+ rubygems_mfa_required: 'true'
244
+ post_install_message:
245
+ rdoc_options: []
246
+ require_paths:
247
+ - lib
248
+ required_ruby_version: !ruby/object:Gem::Requirement
249
+ requirements:
250
+ - - ">="
251
+ - !ruby/object:Gem::Version
252
+ version: '0'
253
+ required_rubygems_version: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ requirements: []
259
+ rubygems_version: 3.4.19
260
+ signing_key:
261
+ specification_version: 4
262
+ summary: Auth0 authentication for Warden.
263
+ test_files: []