http-auth0 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f53f0e6ddc1989adf00d2f1cb4aee9aa53f47a543726f9c6fd89072db9d55149
4
+ data.tar.gz: d594ac5151d17c2d5e144544e0cdb5e6aa2cf7d9ddbda7c949f0e1a092cdc4c6
5
+ SHA512:
6
+ metadata.gz: 2f33d47e9c207ee606509782cdf33469c68d2018907bdaa41a21682fb74f4ff3e58d37bdad674d42e4346f27cd3af36e0bdc8ae5ab74b52b67e312cee5cceec8
7
+ data.tar.gz: 1eca6ddf26c59ffa868345bbc35dbf4ecfd9c571f2875f218a0107917025a088b4ee97abebffd9ae5a66b74510ff35c632b0f59a26edf152a5a07406fd500ab7
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 John Chlark Sumatra
4
+ Copyright (c) 2022 First Circle Growth Finance Corp.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # http-auth0
2
+
3
+ [![CI](https://github.com/itsmechlark/http-auth0/actions/workflows/release.yml/badge.svg)](https://github.com/itsmechlark/http-auth0/actions/workflows/release.yml)
4
+ [![Coverage Status](https://coveralls.io/repos/github/itsmechlark/http-auth0/badge.svg?branch=main)](https://coveralls.io/github/itsmechlark/http-auth0?branch=main)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/298974e71e03a3b26a47/maintainability)](https://codeclimate.com/github/itsmechlark/http-auth0/maintainability)
6
+
7
+ HTTP client abstraction layer for Auth Application [RFC](https://github.com/itsmechlark/rfcs/pull/2)
8
+
9
+ ## Installation
10
+
11
+ Add these lines to your application's Gemfile:
12
+
13
+ ```ruby
14
+ source 'https://rubygems.pkg.github.com/itsmechlark' do
15
+ gem 'http-auth0'
16
+ end
17
+ ```
18
+
19
+ And then execute:
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Configure the gem in an initializer
27
+
28
+ ```ruby
29
+ HTTP::Auth0.configure do |auth0|
30
+ auth0.domain = 'insert-domain-here.jp.auth0.com'
31
+ auth0.client_id = 'insert-client-id-here'
32
+ auth0.client_secret = 'insert-client-secret-here'
33
+ end
34
+ ```
35
+
36
+ ### Use with your preferred HTTP client
37
+ #### Faraday Example
38
+
39
+ ```ruby
40
+ require 'faraday'
41
+ require 'faraday/net_http'
42
+ require 'http/auth0/middleware'
43
+
44
+ conn = Faraday.new do |f|
45
+ f.use HTTP::Auth0::Middleware
46
+ end
47
+
48
+ conn.post("https://example.com/graphql")
49
+ ```
50
+
51
+ #### Net::HTTP Example
52
+
53
+ ```ruby
54
+ require 'http/auth0'
55
+ require 'net/http'
56
+
57
+ uri = URI("https://example.com/graphql")
58
+ req = Net::HTTP::Get.new(uri)
59
+ req['Authorization'] = HTTP::Auth0.token(aud: uri.to_s)
60
+
61
+ res = Net::HTTP.start(uri.hostname, uri.port) do |http|
62
+ http.request(req)
63
+ end
64
+
65
+ puts res.body
66
+ ```
67
+
68
+ ## Dependencies
69
+
70
+ - [Auth0](https://auth0.com/)
71
+ - [dry-configurable](https://github.com/dry-rb/dry-configurable)
72
+ - [ruby-jwt](https://github.com/jwt/ruby-jwt)
73
+
74
+ ## Contributing
75
+
76
+ 1. Clone the [http-auth0 repo](https://github.com/itsmechlark/http-auth0)
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create a new Pull Request
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "http/auth0"
5
+
6
+ module HTTP
7
+ class Auth0
8
+ # Request middleware for the Auth0 Authorization HTTP header
9
+ class Middleware < Faraday::Middleware
10
+ KEY = "Authorization"
11
+
12
+ # @param app [#call]
13
+ def initialize(app)
14
+ super(app)
15
+ end
16
+
17
+ # @param env [Faraday::Env]
18
+ def on_request(env)
19
+ return if env.request_headers[KEY]
20
+
21
+ env.request_headers[KEY] = "Bearer #{auth0_token(env)}"
22
+ end
23
+
24
+ private
25
+
26
+ # @param env [Faraday::Env]
27
+ # @return [String] a header value
28
+ def auth0_token(env)
29
+ uri = env.url.to_s
30
+ aud_uri = URI.parse(uri)
31
+ aud_uri.fragment = aud_uri.query = nil
32
+ Auth0.token(aud: aud_uri.to_s)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ Faraday::Request.register_middleware(auth0: HTTP::Auth0::Middleware)
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "jwt"
5
+ require "net/http"
6
+ require "openssl"
7
+ require "uri"
8
+
9
+ module HTTP
10
+ class Auth0
11
+ class ConfigurationError < StandardError; end
12
+
13
+ class Token
14
+ include Singleton
15
+
16
+ def token(aud:)
17
+ validate_configuration(key: :client_id)
18
+ validate_configuration(key: :client_secret)
19
+
20
+ if (cached = access_tokens[aud])
21
+ return cached unless expired?(token: cached)
22
+ end
23
+ request_access_token(aud: aud)
24
+ end
25
+
26
+ private
27
+
28
+ def access_tokens
29
+ @access_tokens ||= {}
30
+ end
31
+
32
+ def validate_configuration(key:)
33
+ raise ConfigurationError, "Missing #{key} in configuration" if [nil, ""].any?(config.send(key))
34
+ end
35
+
36
+ def expired?(token:)
37
+ decoded_token = JWT.decode(token, nil, false)
38
+ payload = decoded_token.first
39
+ expiration = payload["exp"]
40
+ current_time = Time.now.to_i
41
+ seconds_before_refresh = config.seconds_before_refresh
42
+ expiration_time = Time.at(expiration).to_i - seconds_before_refresh.to_i
43
+
44
+ current_time >= expiration_time
45
+ rescue StandardError => e
46
+ config.logger.error(e)
47
+ true
48
+ end
49
+
50
+ def request_access_token(aud:)
51
+ url = URI("#{issuer}/oauth/token")
52
+ http = Net::HTTP.new(url.host, url.port)
53
+ http.use_ssl = true
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
55
+
56
+ request = Net::HTTP::Post.new(url)
57
+ request["content-type"] = "application/x-www-form-urlencoded"
58
+
59
+ body = request_body(aud: aud)
60
+ request.body = body.map { |key, value| "#{key}=#{value}" }.join("&")
61
+
62
+ response = http.request(request)
63
+ body = response.read_body
64
+
65
+ case response
66
+ when Net::HTTPSuccess
67
+ auth0_response = JSON.parse(body)
68
+ auth0_response["access_token"].tap do |access_token|
69
+ access_tokens[aud] = access_token
70
+ end
71
+ else
72
+ config.logger.warn("#{response.message}: #{body}")
73
+ nil
74
+ end
75
+ end
76
+
77
+ def request_body(aud:)
78
+ {
79
+ audience: aud,
80
+ client_id: config.client_id,
81
+ client_secret: config.client_secret,
82
+ grant_type: "client_credentials",
83
+ }
84
+ end
85
+
86
+ def issuer
87
+ "https://#{config.custom_domain || config.domain}"
88
+ end
89
+
90
+ def config
91
+ ::HTTP::Auth0.config
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTP
4
+ class Auth0
5
+ VERSION = "1.0.0"
6
+
7
+ class << self
8
+ def gem_version
9
+ Gem::Version.new(VERSION)
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/http/auth0.rb ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/blank"
4
+ require "dry/configurable"
5
+
6
+ require_relative "auth0/token"
7
+
8
+ module HTTP
9
+ class Auth0
10
+ extend(Dry::Configurable)
11
+
12
+ setting(:client_id, default: ENV["AUTH0_CLIENT_ID"].presence)
13
+ setting(:client_secret, default: ENV["AUTH0_CLIENT_SECRET"].presence)
14
+ setting(:custom_domain, default: ENV["AUTH0_CUSTOM_DOMAIN"].presence)
15
+ setting(:domain, default: ENV["AUTH0_DOMAIN"].presence)
16
+ setting(:logger, default: Logger.new($stdout))
17
+ setting(:seconds_before_refresh, default: 60)
18
+
19
+ class << self
20
+ def token(aud:)
21
+ Token.instance.token(aud: aud)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ require_relative "auth0/version"
metadata ADDED
@@ -0,0 +1,348 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: http-auth0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John Chlark Sumatra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dry-configurable
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '2.0'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0.14'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: jwt
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '2.3'
54
+ - - "<"
55
+ - !ruby/object:Gem::Version
56
+ version: '2.8'
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '2.3'
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: '2.8'
67
+ - !ruby/object:Gem::Dependency
68
+ name: faraday
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '2.0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '2.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: bundler
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '2.0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: code-scanning-rubocop
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: faker
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '3.2'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '3.2'
123
+ - !ruby/object:Gem::Dependency
124
+ name: multipart-parser
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: 0.1.1
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: 0.1.1
137
+ - !ruby/object:Gem::Dependency
138
+ name: pry-byebug
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '3.7'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '3.7'
151
+ - !ruby/object:Gem::Dependency
152
+ name: rake
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '13.0'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '13.0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: rspec
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: '3.0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: '3.0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: rubocop-performance
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ - !ruby/object:Gem::Dependency
194
+ name: rubocop-rake
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ - !ruby/object:Gem::Dependency
208
+ name: rubocop-rspec
209
+ requirement: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
221
+ - !ruby/object:Gem::Dependency
222
+ name: rubocop-shopify
223
+ requirement: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - "~>"
226
+ - !ruby/object:Gem::Version
227
+ version: '2.14'
228
+ type: :development
229
+ prerelease: false
230
+ version_requirements: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - "~>"
233
+ - !ruby/object:Gem::Version
234
+ version: '2.14'
235
+ - !ruby/object:Gem::Dependency
236
+ name: simplecov
237
+ requirement: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - ">="
240
+ - !ruby/object:Gem::Version
241
+ version: 0.21.2
242
+ type: :development
243
+ prerelease: false
244
+ version_requirements: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: 0.21.2
249
+ - !ruby/object:Gem::Dependency
250
+ name: simplecov-lcov
251
+ requirement: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ">="
254
+ - !ruby/object:Gem::Version
255
+ version: '0'
256
+ type: :development
257
+ prerelease: false
258
+ version_requirements: !ruby/object:Gem::Requirement
259
+ requirements:
260
+ - - ">="
261
+ - !ruby/object:Gem::Version
262
+ version: '0'
263
+ - !ruby/object:Gem::Dependency
264
+ name: timecop
265
+ requirement: !ruby/object:Gem::Requirement
266
+ requirements:
267
+ - - "~>"
268
+ - !ruby/object:Gem::Version
269
+ version: 0.9.4
270
+ type: :development
271
+ prerelease: false
272
+ version_requirements: !ruby/object:Gem::Requirement
273
+ requirements:
274
+ - - "~>"
275
+ - !ruby/object:Gem::Version
276
+ version: 0.9.4
277
+ - !ruby/object:Gem::Dependency
278
+ name: vcr
279
+ requirement: !ruby/object:Gem::Requirement
280
+ requirements:
281
+ - - "~>"
282
+ - !ruby/object:Gem::Version
283
+ version: '6.0'
284
+ type: :development
285
+ prerelease: false
286
+ version_requirements: !ruby/object:Gem::Requirement
287
+ requirements:
288
+ - - "~>"
289
+ - !ruby/object:Gem::Version
290
+ version: '6.0'
291
+ - !ruby/object:Gem::Dependency
292
+ name: webmock
293
+ requirement: !ruby/object:Gem::Requirement
294
+ requirements:
295
+ - - "~>"
296
+ - !ruby/object:Gem::Version
297
+ version: '3.4'
298
+ type: :development
299
+ prerelease: false
300
+ version_requirements: !ruby/object:Gem::Requirement
301
+ requirements:
302
+ - - "~>"
303
+ - !ruby/object:Gem::Version
304
+ version: '3.4'
305
+ description: Faraday adapter for Auth0
306
+ email:
307
+ - clark@sumatra.com.ph
308
+ executables: []
309
+ extensions: []
310
+ extra_rdoc_files:
311
+ - LICENSE.md
312
+ - README.md
313
+ files:
314
+ - LICENSE.md
315
+ - README.md
316
+ - lib/http/auth0.rb
317
+ - lib/http/auth0/middleware.rb
318
+ - lib/http/auth0/token.rb
319
+ - lib/http/auth0/version.rb
320
+ homepage: https://github.com/itsmechlark/http-auth0
321
+ licenses:
322
+ - MIT
323
+ metadata:
324
+ homepage_uri: https://github.com/itsmechlark/http-auth0
325
+ changelog_uri: https://github.com/itsmechlark/http-auth0/releases/tag/v1.0.0
326
+ source_code_uri: https://github.com/itsmechlark/http-auth0/tree/v1.0.0
327
+ bug_tracker_uri: https://github.com/itsmechlark/http-auth0/issues
328
+ github_repo: https://github.com/itsmechlark/http-auth0
329
+ post_install_message:
330
+ rdoc_options: []
331
+ require_paths:
332
+ - lib
333
+ required_ruby_version: !ruby/object:Gem::Requirement
334
+ requirements:
335
+ - - ">="
336
+ - !ruby/object:Gem::Version
337
+ version: '2.7'
338
+ required_rubygems_version: !ruby/object:Gem::Requirement
339
+ requirements:
340
+ - - ">="
341
+ - !ruby/object:Gem::Version
342
+ version: '0'
343
+ requirements: []
344
+ rubygems_version: 3.2.33
345
+ signing_key:
346
+ specification_version: 4
347
+ summary: Faraday adapter for Auth0
348
+ test_files: []