oauth 1.1.0 → 1.1.1

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.
data/REEK ADDED
File without changes
data/RUBOCOP.md ADDED
@@ -0,0 +1,71 @@
1
+ # RuboCop Usage Guide
2
+
3
+ ## Overview
4
+
5
+ A tale of two RuboCop plugin gems.
6
+
7
+ ### RuboCop Gradual
8
+
9
+ This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file.
10
+
11
+ ### RuboCop LTS
12
+
13
+ This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2.
14
+ RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more.
15
+
16
+ ## Checking RuboCop Violations
17
+
18
+ To check for RuboCop violations in this project, always use:
19
+
20
+ ```bash
21
+ bundle exec rake rubocop_gradual:check
22
+ ```
23
+
24
+ **Do not use** the standard RuboCop commands like:
25
+ - `bundle exec rubocop`
26
+ - `rubocop`
27
+
28
+ ## Understanding the Lock File
29
+
30
+ The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to:
31
+
32
+ 1. Prevent new violations while gradually fixing existing ones
33
+ 2. Track progress on code style improvements
34
+ 3. Ensure CI builds don't fail due to pre-existing violations
35
+
36
+ ## Common Commands
37
+
38
+ - **Check violations**
39
+ - `bundle exec rake rubocop_gradual`
40
+ - `bundle exec rake rubocop_gradual:check`
41
+ - **(Safe) Autocorrect violations, and update lockfile if no new violations**
42
+ - `bundle exec rake rubocop_gradual:autocorrect`
43
+ - **Force update the lock file (w/o autocorrect) to match violations present in code**
44
+ - `bundle exec rake rubocop_gradual:force_update`
45
+
46
+ ## Workflow
47
+
48
+ 1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect`
49
+ a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task.
50
+ 2. If there are new violations, either:
51
+ - Fix them in your code
52
+ - Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately)
53
+ 3. Commit the updated `.rubocop_gradual.lock` file along with your changes
54
+
55
+ ## Never add inline RuboCop disables
56
+
57
+ Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways:
58
+
59
+ - Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide.
60
+ - Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow:
61
+ - `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced)
62
+ - If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately)
63
+
64
+ In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test.
65
+
66
+ ## Benefits of rubocop_gradual
67
+
68
+ - Allows incremental adoption of code style rules
69
+ - Prevents CI failures due to pre-existing violations
70
+ - Provides a clear record of code style debt
71
+ - Enables focused efforts on improving code quality over time
data/SECURITY.md CHANGED
@@ -2,25 +2,41 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported | EOL |
6
- |---------|--------------------|---------|
7
- | 1.1.x | :white_check_mark: | 04/2025 |
8
- | 1.0.x | :white_check_mark: | 04/2025 |
9
- | 0.6.x | :white_check_mark: | 04/2024 |
10
- | 0.5.x | :white_check_mark: | 04/2023 |
11
- | <= 0.5 | :x: | :x: |
5
+ | Version | Supported | Post-EOL / Enterprise |
6
+ |---------|-----------|---------------------------------------|
7
+ | 1.1.x | | [Tidelift Subscription][tidelift-ref] |
8
+ | 1.0.x | | [Tidelift Subscription][tidelift-ref] |
9
+ | 0.6.x | 🚨 | [Tidelift Subscription][tidelift-ref] |
10
+ | 0.5.x | 🚨 | [Tidelift Subscription][tidelift-ref] |
11
+ | <= 0.5 | | |
12
+
13
+ LEGEND:
14
+ ✅ - Supported
15
+ 🚨 - Will only receive critical bug and security updates.
16
+ ⛔ - No Support
12
17
 
13
18
  ### EOL Policy
14
19
 
15
- Non-commercial support for the oldest version of Ruby (which itself is going EOL) will be dropped each year in April.
20
+ Non-commercial support for the oldest version of Ruby (which itself is going EOL) may be dropped each year in April.
16
21
 
17
- ## Reporting a Vulnerability
22
+ ## Security contact information
18
23
 
19
- To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
24
+ To report a security vulnerability, please use the
25
+ [Tidelift security contact](https://tidelift.com/security).
20
26
  Tidelift will coordinate the fix and disclosure.
21
27
 
22
28
  ## OAuth for Enterprise
23
29
 
24
30
  Available as part of the Tidelift Subscription.
25
31
 
26
- The maintainers of oauth and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.](https://tidelift.com/subscription/pkg/rubygems-oauth?utm_source=rubygems-oauth&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
32
+ The maintainers of oauth and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.][tidelift-ref]
33
+
34
+ [tidelift-ref]: https://tidelift.com/subscription/pkg/rubygems-oauth?utm_source=rubygems-oauth&utm_medium=referral&utm_campaign=enterprise&utm_term=repo
35
+
36
+ ## Additional Support
37
+
38
+ If you are interested in support for versions older than the latest release,
39
+ please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
40
+ or find other sponsorship links in the [README].
41
+
42
+ [README]: README.md
@@ -35,19 +35,23 @@ module ActionController
35
35
  end
36
36
 
37
37
  def configure_oauth(consumer = nil, token = nil, options = {})
38
- @oauth_options = { consumer: consumer,
39
- token: token,
40
- scheme: "header",
41
- signature_method: nil,
42
- nonce: nil,
43
- timestamp: nil }.merge(options)
38
+ @oauth_options = {
39
+ consumer: consumer,
40
+ token: token,
41
+ scheme: "header",
42
+ signature_method: nil,
43
+ nonce: nil,
44
+ timestamp: nil,
45
+ }.merge(options)
44
46
  end
45
47
 
46
48
  def apply_oauth!
47
49
  return unless ActionController::TestRequest.use_oauth? && @oauth_options
48
50
 
49
- @oauth_helper = OAuth::Client::Helper.new(self,
50
- @oauth_options.merge(request_uri: (respond_to?(:fullpath) ? fullpath : request_uri)))
51
+ @oauth_helper = OAuth::Client::Helper.new(
52
+ self,
53
+ @oauth_options.merge(request_uri: (respond_to?(:fullpath) ? fullpath : request_uri)),
54
+ )
51
55
  @oauth_helper.amend_user_agent_header(env)
52
56
 
53
57
  send("set_oauth_#{@oauth_options[:scheme]}")
@@ -62,6 +66,7 @@ module ActionController
62
66
  @query_parameters.merge!(oauth_signature: @oauth_helper.signature)
63
67
  end
64
68
 
65
- def set_oauth_query_string; end
69
+ def set_oauth_query_string
70
+ end
66
71
  end
67
72
  end
@@ -1,119 +1,126 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "em-http"
4
3
  require "oauth/helper"
5
- require "oauth/request_proxy/em_http_request"
4
+ require "oauth/optional"
6
5
 
7
- # Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
8
- # instance. This is purely syntactic sugar.
9
- module EventMachine
10
- class HttpClient
11
- attr_reader :oauth_helper
6
+ if OAuth::Optional.em_http_available?
7
+ require "oauth/request_proxy/em_http_request"
12
8
 
13
- # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
14
- # this may add a header, additional query string parameters, or additional POST body parameters.
15
- # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
16
- # header.
17
- #
18
- # * http - Configured Net::HTTP instance, ignored in this scenario except for getting host.
19
- # * consumer - OAuth::Consumer instance
20
- # * token - OAuth::Token instance
21
- # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
22
- # +signature_method+, +nonce+, +timestamp+)
23
- #
24
- # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
25
- #
26
- # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
27
- def oauth!(http, consumer = nil, token = nil, options = {})
28
- options = { request_uri: normalized_oauth_uri(http),
29
- consumer: consumer,
30
- token: token,
31
- scheme: "header",
32
- signature_method: nil,
33
- nonce: nil,
34
- timestamp: nil }.merge(options)
9
+ # Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
10
+ # instance. This is purely syntactic sugar.
11
+ module EventMachine
12
+ class HttpClient
13
+ attr_reader :oauth_helper
35
14
 
36
- @oauth_helper = OAuth::Client::Helper.new(self, options)
37
- __send__(:"set_oauth_#{options[:scheme]}")
38
- end
15
+ # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
16
+ # this may add a header, additional query string parameters, or additional POST body parameters.
17
+ # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
18
+ # header.
19
+ #
20
+ # * http - Configured Net::HTTP instance, ignored in this scenario except for getting host.
21
+ # * consumer - OAuth::Consumer instance
22
+ # * token - OAuth::Token instance
23
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
24
+ # +signature_method+, +nonce+, +timestamp+)
25
+ #
26
+ # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
27
+ #
28
+ # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
29
+ def oauth!(http, consumer = nil, token = nil, options = {})
30
+ options = {
31
+ request_uri: normalized_oauth_uri(http),
32
+ consumer: consumer,
33
+ token: token,
34
+ scheme: "header",
35
+ signature_method: nil,
36
+ nonce: nil,
37
+ timestamp: nil,
38
+ }.merge(options)
39
39
 
40
- # Create a string suitable for signing for an HTTP request. This process involves parameter
41
- # normalization as specified in the OAuth specification. The exact normalization also depends
42
- # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
43
- # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
44
- # header.
45
- #
46
- # * http - Configured Net::HTTP instance
47
- # * consumer - OAuth::Consumer instance
48
- # * token - OAuth::Token instance
49
- # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
50
- # +signature_method+, +nonce+, +timestamp+)
51
- #
52
- # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
53
- def signature_base_string(http, consumer = nil, token = nil, options = {})
54
- options = { request_uri: normalized_oauth_uri(http),
55
- consumer: consumer,
56
- token: token,
57
- scheme: "header",
58
- signature_method: nil,
59
- nonce: nil,
60
- timestamp: nil }.merge(options)
40
+ @oauth_helper = OAuth::Client::Helper.new(self, options)
41
+ __send__(:"set_oauth_#{options[:scheme]}")
42
+ end
61
43
 
62
- OAuth::Client::Helper.new(self, options).signature_base_string
63
- end
44
+ # Create a string suitable for signing for an HTTP request. This process involves parameter
45
+ # normalization as specified in the OAuth specification. The exact normalization also depends
46
+ # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
47
+ # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
48
+ # header.
49
+ #
50
+ # * http - Configured Net::HTTP instance
51
+ # * consumer - OAuth::Consumer instance
52
+ # * token - OAuth::Token instance
53
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
54
+ # +signature_method+, +nonce+, +timestamp+)
55
+ #
56
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
57
+ def signature_base_string(http, consumer = nil, token = nil, options = {})
58
+ options = {
59
+ request_uri: normalized_oauth_uri(http),
60
+ consumer: consumer,
61
+ token: token,
62
+ scheme: "header",
63
+ signature_method: nil,
64
+ nonce: nil,
65
+ timestamp: nil,
66
+ }.merge(options)
64
67
 
65
- # This code was lifted from the em-http-request because it was removed from
66
- # the gem June 19, 2010
67
- # see: http://github.com/igrigorik/em-http-request/commit/d536fc17d56dbe55c487eab01e2ff9382a62598b
68
- def normalize_uri
69
- @normalized_uri ||= begin
70
- uri = @conn.dup
71
- encoded_query = encode_query(@conn, @req[:query])
72
- path, query = encoded_query.split("?", 2)
73
- uri.query = query unless encoded_query.empty?
74
- uri.path = path
75
- uri
68
+ OAuth::Client::Helper.new(self, options).signature_base_string
76
69
  end
77
- end
78
70
 
79
- protected
71
+ # This code was lifted from the em-http-request because it was removed from
72
+ # the gem June 19, 2010
73
+ # see: http://github.com/igrigorik/em-http-request/commit/d536fc17d56dbe55c487eab01e2ff9382a62598b
74
+ def normalize_uri
75
+ @normalized_uri ||= begin
76
+ uri = @conn.dup
77
+ encoded_query = encode_query(@conn, @req[:query])
78
+ path, query = encoded_query.split("?", 2)
79
+ uri.query = query unless encoded_query.empty?
80
+ uri.path = path
81
+ uri
82
+ end
83
+ end
80
84
 
81
- def combine_query(path, query, uri_query)
82
- combined_query = if query.is_a?(Hash)
83
- query.map { |k, v| encode_param(k, v) }.join("&")
84
- else
85
- query.to_s
86
- end
87
- combined_query = [combined_query, uri_query].reject(&:empty?).join("&") unless uri_query.to_s.empty?
88
- combined_query.to_s.empty? ? path : "#{path}?#{combined_query}"
89
- end
85
+ protected
90
86
 
91
- # Since we expect to get the host etc details from the http instance (...),
92
- # we create a fake url here. Surely this is a horrible, horrible idea?
93
- def normalized_oauth_uri(http)
94
- uri = URI.parse(normalize_uri.path)
95
- uri.host = http.address
96
- uri.port = http.port
87
+ def combine_query(path, query, uri_query)
88
+ combined_query = if query.is_a?(Hash)
89
+ query.map { |k, v| encode_param(k, v) }.join("&")
90
+ else
91
+ query.to_s
92
+ end
93
+ combined_query = [combined_query, uri_query].reject(&:empty?).join("&") unless uri_query.to_s.empty?
94
+ combined_query.to_s.empty? ? path : "#{path}?#{combined_query}"
95
+ end
97
96
 
98
- uri.scheme = if http.respond_to?(:use_ssl?) && http.use_ssl?
99
- "https"
100
- else
101
- "http"
102
- end
103
- uri.to_s
104
- end
97
+ # Since we expect to get the host etc details from the http instance (...),
98
+ # we create a fake url here. Surely this is a horrible, horrible idea?
99
+ def normalized_oauth_uri(http)
100
+ uri = URI.parse(normalize_uri.path)
101
+ uri.host = http.address
102
+ uri.port = http.port
105
103
 
106
- def set_oauth_header
107
- req[:head] ||= {}
108
- req[:head].merge!("Authorization" => @oauth_helper.header)
109
- end
104
+ uri.scheme = if http.respond_to?(:use_ssl?) && http.use_ssl?
105
+ "https"
106
+ else
107
+ "http"
108
+ end
109
+ uri.to_s
110
+ end
110
111
 
111
- def set_oauth_body
112
- raise NotImplementedError, "please use the set_oauth_header method instead"
113
- end
112
+ def set_oauth_header
113
+ req[:head] ||= {}
114
+ req[:head].merge!("Authorization" => @oauth_helper.header)
115
+ end
114
116
 
115
- def set_oauth_query_string
116
- raise NotImplementedError, "please use the set_oauth_header method instead"
117
+ def set_oauth_body
118
+ raise NotImplementedError, "please use the set_oauth_header method instead"
119
+ end
120
+
121
+ def set_oauth_query_string
122
+ raise NotImplementedError, "please use the set_oauth_header method instead"
123
+ end
117
124
  end
118
125
  end
119
126
  end
@@ -37,29 +37,33 @@ module OAuth
37
37
  "oauth_timestamp" => timestamp,
38
38
  "oauth_nonce" => nonce,
39
39
  "oauth_verifier" => options[:oauth_verifier],
40
- "oauth_version" => (options[:oauth_version] || "1.0"),
41
- "oauth_session_handle" => options[:oauth_session_handle]
40
+ "oauth_version" => options[:oauth_version] || "1.0",
41
+ "oauth_session_handle" => options[:oauth_session_handle],
42
42
  }
43
43
  allowed_empty_params = options[:allow_empty_params]
44
44
  if allowed_empty_params != true && !allowed_empty_params.is_a?(Array)
45
- allowed_empty_params = allowed_empty_params == false ? [] : [allowed_empty_params]
45
+ allowed_empty_params = (allowed_empty_params == false) ? [] : [allowed_empty_params]
46
46
  end
47
47
  out.select! { |k, v| v.to_s != "" || allowed_empty_params == true || allowed_empty_params.include?(k) }
48
48
  out
49
49
  end
50
50
 
51
51
  def signature(extra_options = {})
52
- OAuth::Signature.sign(@request, { uri: options[:request_uri],
53
- consumer: options[:consumer],
54
- token: options[:token],
55
- unsigned_parameters: options[:unsigned_parameters] }.merge(extra_options))
52
+ OAuth::Signature.sign(@request, {
53
+ uri: options[:request_uri],
54
+ consumer: options[:consumer],
55
+ token: options[:token],
56
+ unsigned_parameters: options[:unsigned_parameters],
57
+ }.merge(extra_options))
56
58
  end
57
59
 
58
60
  def signature_base_string(extra_options = {})
59
- OAuth::Signature.signature_base_string(@request, { uri: options[:request_uri],
60
- consumer: options[:consumer],
61
- token: options[:token],
62
- parameters: oauth_parameters }.merge(extra_options))
61
+ OAuth::Signature.signature_base_string(@request, {
62
+ uri: options[:request_uri],
63
+ consumer: options[:consumer],
64
+ token: options[:token],
65
+ parameters: oauth_parameters,
66
+ }.merge(extra_options))
63
67
  end
64
68
 
65
69
  def token_request?
@@ -58,20 +58,31 @@ module Net
58
58
  private
59
59
 
60
60
  def oauth_helper_options(http, consumer, token, options)
61
- { request_uri: oauth_full_request_uri(http, options),
61
+ {
62
+ request_uri: oauth_full_request_uri(http, options),
62
63
  consumer: consumer,
63
64
  token: token,
64
65
  scheme: "header",
65
66
  signature_method: nil,
66
67
  nonce: nil,
67
68
  timestamp: nil,
68
- body_hash_enabled: true }.merge(options)
69
+ body_hash_enabled: true,
70
+ }.merge(options)
69
71
  end
70
72
 
71
73
  def oauth_full_request_uri(http, options)
72
74
  uri = URI.parse(path)
73
- uri.host = http.address
74
- uri.port = http.port
75
+
76
+ # Guard against strict doubles or alternative HTTP adapters that may not
77
+ # expose Net::HTTP's #address/#port API. Only set host/port when available;
78
+ # otherwise, leave them to be filled by other options (e.g., :site) or the
79
+ # request itself.
80
+ if http.respond_to?(:address)
81
+ uri.host ||= http.address
82
+ end
83
+ if http.respond_to?(:port)
84
+ uri.port ||= http.port
85
+ end
75
86
 
76
87
  if options[:request_endpoint] && options[:site]
77
88
  is_https = options[:site].match(%r{^https://})
@@ -79,11 +90,26 @@ module Net
79
90
  uri.port ||= is_https ? 443 : 80
80
91
  end
81
92
 
82
- uri.scheme = if http.respond_to?(:use_ssl?) && http.use_ssl?
83
- "https"
84
- else
85
- "http"
86
- end
93
+ # Fall back to the provided site URL if host/scheme are still missing.
94
+ if options[:site]
95
+ begin
96
+ site_uri = URI.parse(options[:site])
97
+ uri.host ||= site_uri.host
98
+ uri.scheme ||= site_uri.scheme
99
+ uri.port ||= site_uri.port
100
+ rescue URI::InvalidURIError
101
+ # ignore and use defaults below
102
+ end
103
+ end
104
+
105
+ # As a last resort, ensure scheme/host/port are present to avoid nil errors
106
+ uri.scheme ||= if http.respond_to?(:use_ssl?) && http.use_ssl?
107
+ "https"
108
+ else
109
+ "http"
110
+ end
111
+ uri.host ||= "localhost"
112
+ uri.port ||= ((uri.scheme == "https") ? 443 : 80)
87
113
 
88
114
  uri.to_s
89
115
  end
@@ -115,10 +141,10 @@ module Net
115
141
  oauth_params_str = @oauth_helper.oauth_parameters.map { |k, v| [escape(k), escape(v)].join("=") }.join("&")
116
142
  uri = URI.parse(path)
117
143
  uri.query = if uri.query.to_s == ""
118
- oauth_params_str
119
- else
120
- "#{uri.query}&#{oauth_params_str}"
121
- end
144
+ oauth_params_str
145
+ else
146
+ "#{uri.query}&#{oauth_params_str}"
147
+ end
122
148
 
123
149
  @path = uri.to_s
124
150