Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ Please file a bug if you notice a violation of semantic versioning.

### Changed

- auth-sanitizer v0.1.3

### Deprecated

### Removed

### Fixed

- [gh!721][gh!721] Load `auth-sanitizer` through an internal isolated loader so requiring `oauth2` does not add top-level `Auth` or `AuthSanitizer` constants that may collide with downstream applications by @pboling

### Security

[gh!721]: https://github.com/ruby-oauth/oauth2/pull/721

## [2.0.19] - 2026-05-15

- TAG: [v2.0.19][2.0.19t]
Expand Down
26 changes: 13 additions & 13 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
PATH
remote: .
specs:
oauth2 (2.0.19)
auth-sanitizer (~> 0.1)
oauth2 (2.0.20)
auth-sanitizer (~> 0.1, >= 0.1.3)
faraday (>= 0.17.3, < 4.0)
jwt (>= 1.0, < 4.0)
logger (~> 1.2)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
snaky_hash (~> 2.0, >= 2.0.3)
snaky_hash (~> 2.0, >= 2.0.4)
version_gem (~> 1.1, >= 1.1.9)

GEM
Expand All @@ -22,7 +22,7 @@ GEM
rake (>= 10)
thor (>= 0.14)
ast (2.4.3)
auth-sanitizer (0.1.2)
auth-sanitizer (0.1.3)
version_gem (~> 1.1, >= 1.1.9)
backports (3.25.3)
base64 (0.3.0)
Expand Down Expand Up @@ -74,7 +74,7 @@ GEM
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-net_http (3.4.2)
faraday-net_http (3.4.3)
net-http (~> 0.5)
gem_bench (2.0.5)
bundler (>= 1.14)
Expand Down Expand Up @@ -280,7 +280,7 @@ GEM
simplecov-rcov (0.3.7)
simplecov (>= 0.4.1)
simplecov_json_formatter (0.1.4)
snaky_hash (2.0.3)
snaky_hash (2.0.4)
hashie (>= 0.1.0, < 6)
version_gem (>= 1.1.8, < 3)
standard (1.54.0)
Expand Down Expand Up @@ -330,7 +330,7 @@ GEM
yard
yard-relative_markdown_links (0.5.0)
nokogiri (>= 1.14.3, < 2)
zeitwerk (2.7.5)
zeitwerk (2.8.1)
zlib (3.2.3)

PLATFORMS
Expand All @@ -348,7 +348,7 @@ DEPENDENCIES
appraisal2 (~> 3.0, >= 3.0.6)
backports (~> 3.25, >= 3.25.1)
benchmark (~> 0.4, >= 0.4.1)
bundler-audit (~> 0.9.2)
bundler-audit (~> 0.9.3)
debug (>= 1.1)
erb (~> 5.0)
gem_bench (~> 2.0, >= 2.0.5)
Expand Down Expand Up @@ -386,7 +386,7 @@ CHECKSUMS
ansi (1.6.0) sha256=ac9ea0c0ea8d32fb4e271348e609963ac78882f34b73836c2a02b3622e666658
appraisal2 (3.0.6) sha256=09387896b6c8c8c0ff0749af691ddff5e3168de2f06b591a80d8fd8b6394d147
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
auth-sanitizer (0.1.2) sha256=29f7638d74b2a19ff890008f1561165668a78969a4d90bc85e991128825a7c03
auth-sanitizer (0.1.3) sha256=51002d96e921eb9610b197f39de92ae63df11eeb3c5f2bfd7829feb725911487
backports (3.25.3) sha256=94298d32dc3c40ca15633b54e282780b49e2db0c045f602ea1907e4f63a17235
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
benchmark (0.5.0) sha256=465df122341aedcb81a2a24b4d3bd19b6c67c1530713fd533f3ff034e419236c
Expand All @@ -408,7 +408,7 @@ CHECKSUMS
dry-types (1.9.1) sha256=baebeecdb9f8395d6c9d227b62011279440943e3ef2468fe8ccc1ba11467f178
erb (5.1.3) sha256=566e53057b6ba48699f824b578473b391fa8aef100aa14afad1c46725fae0e67
faraday (2.14.2) sha256=73ccb9994a9e8648f010e32eca2ae82e41c57860aa10932cda29418b9e0223ad
faraday-net_http (3.4.2) sha256=f147758260d3526939bf57ecf911682f94926a3666502e24c69992765875906c
faraday-net_http (3.4.3) sha256=9db13becec9312f345a769eeeecf9049c9287d54c0ae053d7235228993a4eec1
gem_bench (2.0.5) sha256=0dc0fb44a5a5eb7b2f5c1c68a5b0164d72007132822c012bac3abe976b199ead
gitmoji-regex (1.0.3) sha256=538c6f49f5af6dc36d1630edb89a5a66f6e14ec5850d7fd071e0331f940e553f
hashie (5.1.0) sha256=c266471896f323c446ea8207f8ffac985d2718df0a0ba98651a3057096ca3870
Expand Down Expand Up @@ -436,7 +436,7 @@ CHECKSUMS
nokogiri (1.19.3-x86_64-darwin) sha256=77f3fba57d46c53ab31e62fc6c28f705109d1bf6264356c76f132b2be5728d4d
nokogiri (1.19.3-x86_64-linux-gnu) sha256=2f5078620fe12e83669b5b17311b32532a8153d02eee7ad06948b926d6080976
nokogiri (1.19.3-x86_64-linux-musl) sha256=248c906d2166eca5efb56d52fdee5f9a1f51d69a72e2b64fdac647b4ce39ea3f
oauth2 (2.0.19)
oauth2 (2.0.20)
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
parallel (1.28.0) sha256=33e6de1484baf2524792d178b0913fc8eb94c628d6cfe45599ad4458c638c970
parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
Expand Down Expand Up @@ -489,7 +489,7 @@ CHECKSUMS
simplecov-lcov (0.9.0) sha256=7a77a31e200a595ed4b0249493056efd0c920601f53d2ef135ca34ee796346cd
simplecov-rcov (0.3.7) sha256=372f50bf6df6b6350b7d0c840f2f8bdabe021861a43c26877b747c9ac96139fc
simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
snaky_hash (2.0.3) sha256=25a3d299566e8153fb02fa23fd9a9358845950f7a523ddbbe1fa1e0d79a6d456
snaky_hash (2.0.4) sha256=2b12758c57defa6796341a1620f84b1a23737421d8d7e2575d0550b53cc4fece
standard (1.54.0) sha256=7a4b08f83d9893083c8f03bc486f0feeb6a84d48233b40829c03ef4767ea0100
standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b
standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
Expand All @@ -509,7 +509,7 @@ CHECKSUMS
yard-fence (0.8.2) sha256=4efa58d682fc0eb57258a6d6a8463b61af0890082cdea45f19088b8634d9ab6f
yard-junk (0.1.0) sha256=e85fe2ec1afa47313decd333447b53458cb1ed49b510b70015fdc3041a94bcdd
yard-relative_markdown_links (0.5.0) sha256=d5158786196bfb82ed8f6880cefea2ef3072cc9e774ecebd7803e0db9bbb3a71
zeitwerk (2.7.5) sha256=d8da92128c09ea6ec62c949011b00ed4a20242b255293dd66bf41545398f73dd
zeitwerk (2.8.1) sha256=1c85e0f28954d68cd16e575da37f26846f609b68d80b5942ccfd31030c2449d5
zlib (3.2.3) sha256=5bd316698b32f31a64ab910a8b6c282442ca1626a81bbd6a1674e8522e319c20

BUNDLED WITH
Expand Down
8 changes: 4 additions & 4 deletions lib/oauth2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
require "time"

# third party gems
require "auth/sanitizer"
require "snaky_hash"
require "version_gem"

# includes gem files
require_relative "oauth2/version"
require_relative "oauth2/auth_sanitizer"
require_relative "oauth2/filtered_attributes"
require_relative "oauth2/error"
require_relative "oauth2/authenticator"
Expand Down Expand Up @@ -92,10 +92,10 @@ def configure
end
end

# Wire Auth::Sanitizer's label provider to read from OAuth2.config so that
# FilteredAttributes-bearing objects and Auth::Sanitizer::SanitizedLogger instances
# Wire OAuth2::AUTH_SANITIZER's label provider to read from OAuth2.config so that
# FilteredAttributes-bearing objects and OAuth2::AUTH_SANITIZER::SanitizedLogger instances
# pick up OAuth2.config[:filtered_label] at their initialization time.
Auth::Sanitizer.filtered_label_provider = -> { OAuth2.config[:filtered_label] }
OAuth2::AUTH_SANITIZER.filtered_label_provider = -> { OAuth2.config[:filtered_label] }

# Extend OAuth2::Version with VersionGem helpers to provide semantic version helpers.
OAuth2::Version.class_eval do
Expand Down
32 changes: 32 additions & 0 deletions lib/oauth2/auth_sanitizer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module OAuth2
AUTH_SANITIZER = begin
auth_sanitizer_requirement = Gem::Requirement.new("~> 0.1", ">= 0.1.3")
auth_sanitizer_spec = Gem.loaded_specs["auth-sanitizer"]
unless auth_sanitizer_spec && auth_sanitizer_requirement.satisfied_by?(auth_sanitizer_spec.version)
auth_sanitizer_spec = Gem::Specification.find_by_name("auth-sanitizer", auth_sanitizer_requirement)
end

auth_sanitizer_loader_path = File.join(
auth_sanitizer_spec.full_gem_path,
"lib/auth_sanitizer/loader.rb",
)
unless File.file?(auth_sanitizer_loader_path)
raise LoadError, "oauth2 requires auth-sanitizer #{auth_sanitizer_requirement}; " \
"loader not found at #{auth_sanitizer_loader_path}"
end

auth_sanitizer_loader_namespace = Module.new
auth_sanitizer_loader_namespace.module_eval(
File.read(auth_sanitizer_loader_path),
auth_sanitizer_loader_path,
1,
)

auth_sanitizer_loader_namespace.
const_get(:AuthSanitizer).
const_get(:Loader).
load_isolated
end
end
4 changes: 2 additions & 2 deletions lib/oauth2/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Client # rubocop:disable Metrics/ClassLength
# @option options [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday
# @option options [Boolean] :raise_errors (true) whether to raise an OAuth2::Error on responses with 400+ status codes
# @option options [Integer] :max_redirects (5) maximum number of redirects to follow
# @option options [Logger] :logger (::Logger.new($stdout)) Logger instance for HTTP request/response output; requires OAUTH_DEBUG to be true. When debug logging is enabled, sensitive values are filtered using {Auth::Sanitizer::SanitizedLogger} initialized from `OAuth2.config[:filtered_label]` and the key names in `OAuth2.config[:filtered_debug_keys]`.
# @option options [Logger] :logger (::Logger.new($stdout)) Logger instance for HTTP request/response output; requires OAUTH_DEBUG to be true. When debug logging is enabled, sensitive values are filtered using {OAuth2::AUTH_SANITIZER::SanitizedLogger} initialized from `OAuth2.config[:filtered_label]` and the key names in `OAuth2.config[:filtered_debug_keys]`.
# @option options [Class] :access_token_class (AccessToken) class to use for access tokens; you can subclass OAuth2::AccessToken, @version 2.0+
# @option options [Hash] :ssl SSL options for Faraday
#
Expand Down Expand Up @@ -565,7 +565,7 @@ def build_access_token_legacy(response, access_token_opts, extract_access_token)
def oauth_debug_logging(builder)
builder.response(
:logger,
Auth::Sanitizer::SanitizedLogger.new(
OAuth2::AUTH_SANITIZER::SanitizedLogger.new(
options[:logger],
filtered_keys: OAuth2.config[:filtered_debug_keys],
label: OAuth2.config[:filtered_label],
Expand Down
7 changes: 2 additions & 5 deletions lib/oauth2/filtered_attributes.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# frozen_string_literal: true

module OAuth2
# Permanent alias for {Auth::Sanitizer::FilteredAttributes}.
# Permanent alias for {OAuth2::AUTH_SANITIZER::FilteredAttributes}.
#
# This constant is intentionally kept in the `OAuth2` namespace because it
# was part of the public API before the implementation was extracted into the
# `auth-sanitizer` gem. It will **not** be deprecated or removed.
#
# New code that does not need the `OAuth2::` namespace can use
# {Auth::Sanitizer::FilteredAttributes} directly.
FilteredAttributes = Auth::Sanitizer::FilteredAttributes
FilteredAttributes = OAuth2::AUTH_SANITIZER::FilteredAttributes
end
2 changes: 1 addition & 1 deletion lib/oauth2/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module OAuth2
module Version
VERSION = "2.0.19"
VERSION = "2.0.20"
end
VERSION = Version::VERSION # Traditional Constant Location
end
18 changes: 9 additions & 9 deletions oauth2.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,14 @@ Thanks, @pboling / @galtzo
spec.executables = []

# Utilities
spec.add_dependency("auth-sanitizer", "~> 0.1") # ruby >= 2.2.0
spec.add_dependency("faraday", [">= 0.17.3", "< 4.0"]) # ruby >= 1.9
spec.add_dependency("jwt", [">= 1.0", "< 4.0"]) # ruby >= 0
spec.add_dependency("logger", "~> 1.2") # ruby >= 0
spec.add_dependency("multi_xml", "~> 0.5") # ruby >= 0
spec.add_dependency("rack", [">= 1.2", "< 4"]) # ruby >= 0
spec.add_dependency("snaky_hash", "~> 2.0", ">= 2.0.3") # ruby >= 2.2
spec.add_dependency("version_gem", "~> 1.1", ">= 1.1.9") # ruby >= 2.2.0
spec.add_dependency("auth-sanitizer", "~> 0.1", ">= 0.1.3") # ruby >= 2.2.0
spec.add_dependency("faraday", [">= 0.17.3", "< 4.0"]) # ruby >= 1.9
spec.add_dependency("jwt", [">= 1.0", "< 4.0"]) # ruby >= 0
spec.add_dependency("logger", "~> 1.2") # ruby >= 0
spec.add_dependency("multi_xml", "~> 0.5") # ruby >= 0
spec.add_dependency("rack", [">= 1.2", "< 4"]) # ruby >= 0
spec.add_dependency("snaky_hash", "~> 2.0", ">= 2.0.4") # ruby >= 2.2.0
spec.add_dependency("version_gem", "~> 1.1", ">= 1.1.9") # ruby >= 2.2.0

# NOTE: It is preferable to list development dependencies in the gemspec due to increased
# visibility and discoverability.
Expand All @@ -156,7 +156,7 @@ Thanks, @pboling / @galtzo
spec.add_development_dependency("kettle-dev", "~> 2.0") # ruby >= 2.3.0

# Security
spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0
spec.add_development_dependency("bundler-audit", "~> 0.9.3") # ruby >= 2.0.0

# Tasks
spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2.0
Expand Down
10 changes: 6 additions & 4 deletions spec/auth/sanitizer/thing_filter_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# frozen_string_literal: true

RSpec.describe Auth::Sanitizer::ThingFilter do
RSpec.describe "OAuth2::AUTH_SANITIZER::ThingFilter" do
let(:thing_filter_class) { OAuth2::AUTH_SANITIZER::ThingFilter }

describe "#initialize" do
it "does not freeze caller-owned string inputs" do
things = [String.new("secret")]
label = String.new("[FILTERED]")

described_class.new(things, label: label)
thing_filter_class.new(things, label: label)

expect(things.first).not_to be_frozen
expect(label).not_to be_frozen
Expand All @@ -16,7 +18,7 @@
original_thing = String.new("secret")
original_label = String.new("[FILTERED]")

filter = described_class.new([original_thing], label: original_label)
filter = thing_filter_class.new([original_thing], label: original_label)

original_thing.replace("token")
original_label.replace("[REDACTED]")
Expand All @@ -30,7 +32,7 @@
describe "FilteredAttributes integration" do
let(:poro_class) do
Class.new do
include Auth::Sanitizer::FilteredAttributes
include OAuth2::AUTH_SANITIZER::FilteredAttributes

attr_reader :secret, :name
filtered_attributes :secret
Expand Down
12 changes: 12 additions & 0 deletions spec/oauth2/auth_sanitizer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

RSpec.describe "OAuth2::AUTH_SANITIZER" do
it "keeps auth-sanitizer constants isolated inside the OAuth2 namespace" do
expect(Object.const_defined?(:Auth, false)).to be(false)
expect(Object.const_defined?(:AuthSanitizer, false)).to be(false)
end

it "preserves the public OAuth2::FilteredAttributes alias" do
expect(OAuth2::FilteredAttributes).to be(OAuth2::AUTH_SANITIZER::FilteredAttributes)
end
end
Loading