http-auth0 1.0.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: 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: []