oauth2 2.0.18 → 2.0.20

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f43a3e156646bef90634677d617a155cff1f87d57ca030674f3ee05c160fa4d9
4
- data.tar.gz: 5a2d29e7cd920d4e2f515afc23896795477e5cb357e47b6f5c3d0c797194d54c
3
+ metadata.gz: a50435455bab3e2cbebb651d7b88494ee04268367f1f8ab3dbacb479f1637b65
4
+ data.tar.gz: f9b36d98b44a56fbfc6e73b59c44829aa6f28eb24c16141c5052e23019145dcc
5
5
  SHA512:
6
- metadata.gz: 471a77bbc0bd8a428ce01ba42ba8e9cb0ad35793eb5f7ae352946b9dda9a448152280c3bdf445255adb47b7f45d65efa11bff2affc2c2200f8e43f57f2a19a91
7
- data.tar.gz: 6bae92dd35b1bf9efd38b4d3eceb2451c1016dbd9270947f74ba4ff389fa78420558df095acd8ff7404a2b8b2cdb9438983d1feb59751dd4252f2b7bc75c8d31
6
+ metadata.gz: 119ecedc64f4a158dcc0507b2da837ef2d44e6129803da0ebd383409a12670b43c892e596d2183a6e1095535ef0ed0e04769d4556f3111e392b12307a0c45e3c
7
+ data.tar.gz: 43bd592fbe5945d846b9791297ea307fe505a64e79b029b24302fe69fa246b57e7d279e1e87c1bf2c1cdc9e787a5d26e8fdbef15978dcfbb2efe277267d1628f
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,58 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [2.0.20] - 2026-05-20
34
+
35
+ - TAG: [v2.0.20][2.0.20t]
36
+ - COVERAGE: 99.62% -- 525/527 lines in 15 files
37
+ - BRANCH COVERAGE: 98.88% -- 176/178 branches in 15 files
38
+ - 88.35% documented
39
+
40
+ ### Added
41
+
42
+ - OAuth2::VERSION (Traditional Constant Location)
43
+
44
+ ### Changed
45
+
46
+ - auth-sanitizer v0.1.3
47
+
48
+ ### Fixed
49
+
50
+ - [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
51
+
52
+ ### Security
53
+
54
+ [gh!721]: https://github.com/ruby-oauth/oauth2/pull/721
55
+
56
+ ## [2.0.19] - 2026-05-15
57
+
58
+ - TAG: [v2.0.19][2.0.19t]
59
+ - COVERAGE: 100.00% -- 515/515 lines in 14 files
60
+ - BRANCH COVERAGE: 100.00% -- 174/174 branches in 14 files
61
+ - 89.11% documented
62
+
63
+ ### Added
64
+
65
+ - [gh!707][gh!707] Add `OAuth2.config[:filtered_label]` to configure the placeholder used for filtered sensitive values in inspected objects and debug logging output by @pboling
66
+ - [gh!707][gh!707] Add `OAuth2.config[:filtered_debug_keys]` to configure which key names have their values redacted from debug logging output by @pboling
67
+
68
+ ### Changed
69
+
70
+ - [gh!707][gh!707] Make inspect-time and debug-log filters snapshot their configuration at initialization time rather than tracking later config changes by @pboling
71
+ - [gh!714][gh!714]Refactor sensitive-value filtering to use `auth-sanitizer` while preserving `OAuth2::FilteredAttributes` as a permanent API alias by @pboling
72
+
73
+ ### Removed
74
+
75
+ - Remove the internal `OAuth2::ThingFilter` and `OAuth2::SanitizedLogger` implementations now provided by `auth-sanitizer` by @pboling
76
+
77
+ ### Security
78
+
79
+ - [gh!707][gh!707] Redact sensitive values from debug logging output, including Authorization headers and common token/secret fields in headers, query strings, form bodies, and JSON payloads by @pboling
80
+ - NOTE: debug logging has always been, and remains, opt-in. It is turned off by default.
81
+
82
+ [gh!707]: https://github.com/ruby-oauth/oauth2/pull/707
83
+ [gh!714]: https://github.com/ruby-oauth/oauth2/pull/714
84
+
33
85
  ## [2.0.18] - 2025-11-08
34
86
 
35
87
  - TAG: [v2.0.18][2.0.18t]
@@ -54,8 +106,6 @@ Please file a bug if you notice a violation of semantic versioning.
54
106
  - [gh!690][gh!690], [gh!691][gh!691], [gh!692][gh!692] - Add yard-fence
55
107
  - handle braces within code fences in markdown properly by @pboling
56
108
 
57
- ### Security
58
-
59
109
  [gh!683]: https://github.com/ruby-oauth/oauth2/pull/683
60
110
  [gh!684]: https://github.com/ruby-oauth/oauth2/pull/684
61
111
  [gh!685]: https://github.com/ruby-oauth/oauth2/pull/685
@@ -196,8 +246,6 @@ Please file a bug if you notice a violation of semantic versioning.
196
246
 
197
247
  - [gh!660][gh!660] - Links in README (including link to HEAD documentation) by @pboling
198
248
 
199
- ### Security
200
-
201
249
  [gh!660]: https://github.com/ruby-oauth/oauth2/pull/660
202
250
  [gh!657]: https://github.com/ruby-oauth/oauth2/pull/657
203
251
  [gh!656]: https://github.com/ruby-oauth/oauth2/pull/656
@@ -738,7 +786,11 @@ Please file a bug if you notice a violation of semantic versioning.
738
786
 
739
787
  [gemfiles/readme]: gemfiles/README.md
740
788
 
741
- [Unreleased]: https://github.com/ruby-oauth/oauth2/compare/v2.0.18...HEAD
789
+ [Unreleased]: https://github.com/ruby-oauth/oauth2/compare/v2.0.20...HEAD
790
+ [2.0.20]: https://github.com/ruby-oauth/oauth2/compare/v2.0.19...v2.0.20
791
+ [2.0.20t]: https://github.com/ruby-oauth/oauth2/releases/tag/v2.0.20
792
+ [2.0.19]: https://github.com/ruby-oauth/oauth2/compare/v2.0.18...v2.0.19
793
+ [2.0.19t]: https://github.com/ruby-oauth/oauth2/releases/tag/v2.0.19
742
794
  [2.0.18]: https://github.com/ruby-oauth/oauth2/compare/v2.0.17...v2.0.18
743
795
  [2.0.18t]: https://github.com/ruby-oauth/oauth2/releases/tag/v2.0.18
744
796
  [2.0.17]: https://github.com/ruby-oauth/oauth2/compare/v2.0.16...v2.0.17
data/CITATION.cff CHANGED
File without changes
data/CODE_OF_CONDUCT.md CHANGED
File without changes
data/CONTRIBUTING.md CHANGED
File without changes
data/FUNDING.md CHANGED
File without changes
data/IRP.md CHANGED
File without changes
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-2025 Peter H. Boling, of Galtzo.com, and oauth2 contributors
3
+ Copyright (c) 2017-2026 Peter H. Boling, of Galtzo.com, and oauth2 contributors
4
4
  Copyright (c) 2011-2013 Michael Bleigh and Intridea, Inc.
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
data/OIDC.md CHANGED
File without changes
data/README.md CHANGED
@@ -1,32 +1,3 @@
1
- | 📍 NOTE |
2
- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
3
- | RubyGems (the [GitHub org][rubygems-org], not the website) [suffered][draper-security] a [hostile takeover][ellen-takeover] in September 2025. |
4
- | Ultimately [4 maintainers][simi-removed] were [hard removed][martin-removed] and a reason has been given for only 1 of those, while 2 others resigned in protest. |
5
- | It is a [complicated story][draper-takeover] which is difficult to [parse quickly][draper-lies]. |
6
- | I'm adding notes like this to gems because I [don't condone theft][draper-theft] of repositories or gems from their rightful owners. |
7
- | If a similar theft happened with my repos/gems, I'd hope some would stand up for me. |
8
- | Disenfranchised former-maintainers have started [gem.coop][gem-coop]. |
9
- | Once available I will publish there exclusively; unless RubyCentral makes amends with the community. |
10
- | The ["Technology for Humans: Joel Draper"][reinteractive-podcast] podcast episode by [reinteractive][reinteractive] is the most cogent summary I'm aware of. |
11
- | See [here][gem-naming], [here][gem-coop] and [here][martin-ann] for more info on what comes next. |
12
- | What I'm doing: A (WIP) proposal for [bundler/gem scopes][gem-scopes], and a (WIP) proposal for a federated [gem server][gem-server]. |
13
-
14
- [rubygems-org]: https://github.com/rubygems/
15
- [draper-security]: https://joel.drapper.me/p/ruby-central-security-measures/
16
- [draper-takeover]: https://joel.drapper.me/p/ruby-central-takeover/
17
- [ellen-takeover]: https://pup-e.com/blog/goodbye-rubygems/
18
- [simi-removed]: https://www.reddit.com/r/ruby/s/gOk42POCaV
19
- [martin-removed]: https://bsky.app/profile/martinemde.com/post/3m3occezxxs2q
20
- [draper-lies]: https://joel.drapper.me/p/ruby-central-fact-check/
21
- [draper-theft]: https://joel.drapper.me/p/ruby-central/
22
- [reinteractive]: https://reinteractive.com/ruby-on-rails
23
- [gem-coop]: https://gem.coop
24
- [gem-naming]: https://github.com/gem-coop/gem.coop/issues/12
25
- [martin-ann]: https://martinemde.com/2025/10/05/announcing-gem-coop.html
26
- [gem-scopes]: https://github.com/galtzo-floss/bundle-namespace
27
- [gem-server]: https://github.com/galtzo-floss/gem-server
28
- [reinteractive-podcast]: https://youtu.be/_H4qbtC5qzU?si=BvuBU90R2wAqD2E6
29
-
30
1
  [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-i]][🖼️galtzo-discord] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![oauth2 Logo by Chris Messina, CC BY-SA 3.0][🖼️oauth2-i]][🖼️oauth2]
31
2
 
32
3
  [🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
@@ -38,9 +9,7 @@
38
9
 
39
10
  # 🔐 OAuth 2.0 Authorization Framework
40
11
 
41
- ⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
42
-
43
- [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
12
+ [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
44
13
 
45
14
  `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
46
15
 
@@ -50,13 +19,20 @@
50
19
 
51
20
  [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
52
21
 
22
+ <details>
23
+ <summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
24
+
25
+ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
26
+
27
+ </details>
28
+
53
29
  ## 🌻 Synopsis
54
30
 
55
31
  OAuth 2.0 is the industry-standard protocol for authorization.
56
- OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications,
57
- desktop applications, mobile phones, and living room devices.
58
32
  This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications.
59
33
 
34
+ ⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
35
+
60
36
  ### Quick Examples
61
37
 
62
38
  <details markdown="1">
@@ -75,13 +51,14 @@ curl --request POST \
75
51
  NOTE: In the ruby version below, certain params are passed to the `get_token` call, instead of the client creation.
76
52
 
77
53
  ```ruby
78
- OAuth2::Client.new(
54
+ client = OAuth2::Client.new(
79
55
  "REDMOND_CLIENT_ID", # client_id
80
56
  "REDMOND_CLIENT_SECRET", # client_secret
81
57
  auth_scheme: :request_body, # Other modes are supported: :basic_auth, :tls_client_auth, :private_key_jwt
82
58
  token_url: "oauth2/token", # relative path, except with leading `/`, then absolute path
83
59
  site: "https://login.microsoftonline.com/REDMOND_REDACTED",
84
- ). # The base path for token_url when it is relative
60
+ )
61
+ client.
85
62
  client_credentials. # There are many other types to choose from!
86
63
  get_token(resource: "REDMOND_RESOURCE_UUID")
87
64
  ```
@@ -344,33 +321,44 @@ See [SECURITY.md][🔐security] and [IRP.md][🔐irp].
344
321
 
345
322
  ## ⚙️ Configuration
346
323
 
347
- You can turn on additional warnings.
324
+ Global settings for the library:
348
325
 
349
326
  ```ruby
350
327
  OAuth2.configure do |config|
351
- # Turn on a warning like:
352
- # OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key
353
328
  config.silence_extra_tokens_warning = false # default: true
354
- # Set to true if you want to also show warnings about no tokens
355
- config.silence_no_tokens_warning = false # default: true,
329
+ config.silence_no_tokens_warning = false # default: true
356
330
  end
357
331
  ```
358
332
 
359
- The "extra tokens" problem comes from ambiguity in the spec about which token is the right token.
360
- Some OAuth 2.0 standards legitimately have multiple tokens.
361
- You may need to subclass `OAuth2::AccessToken`, or write your own custom alternative to it, and pass it in.
362
- Specify your custom class with the `access_token_class` option.
333
+ Filtering-related settings:
363
334
 
364
- If you only need one token, you can, as of v2.0.10,
365
- specify the exact token name you want to extract via the `OAuth2::AccessToken` using
366
- the `token_name` option.
335
+ ```ruby
336
+ OAuth2.configure do |config|
337
+ config.filtered_label = "[REDACTED]" # default: "[FILTERED]"
338
+ config.filtered_debug_keys += ["client_assertion"]
339
+ end
340
+ ```
367
341
 
368
- You'll likely need to do some source diving.
369
- This gem has 100% test coverage for lines and branches, so the specs are a great place to look for ideas.
370
- If you have time and energy, please contribute to the documentation!
342
+ - `filtered_label` controls the placeholder used when sensitive values are filtered from inspected objects and debug logging output.
343
+ - `filtered_debug_keys` controls which key names have their values redacted from debug logging output when `OAUTH_DEBUG=true`.
344
+ - Debug logging remains opt-in and should still be used cautiously in production environments.
371
345
 
372
346
  ## 🔧 Basic Usage
373
347
 
348
+ ### Client Initialization Options
349
+
350
+ `OAuth2::Client.new` accepts several options:
351
+
352
+ - `:site`: The base URL for the OAuth 2.0 provider.
353
+ - `:authorize_url`: The authorization endpoint (default: `"oauth/authorize"`).
354
+ - `:token_url`: The token endpoint (default: `"oauth/token"`).
355
+ - `:auth_scheme`: The authentication scheme (`:basic_auth`, `:request_body`, `:tls_client_auth`, `:private_key_jwt`). Default is `:basic_auth`.
356
+ - `:connection_opts`: Options for the underlying Faraday connection (timeouts, proxy, etc.).
357
+ - `:raise_errors`: Whether to raise `OAuth2::Error` on 400+ responses (default: `true`).
358
+
359
+ <details markdown="1">
360
+ <summary><em>authorize_url</em> and <em>token_url</em></summary>
361
+
374
362
  ### `authorize_url` and `token_url` are on site root (Just Works!)
375
363
 
376
364
  ```ruby
@@ -416,6 +404,25 @@ client.class.name
416
404
  # => OAuth2::Client
417
405
  ```
418
406
 
407
+ </details>
408
+
409
+ ### Advanced Initializers
410
+
411
+ ```ruby
412
+ client = OAuth2::Client.new(id, secret, site: site) do |faraday|
413
+ faraday.request(:url_encoded)
414
+ faraday.adapter(:net_http_persistent)
415
+ end
416
+ ```
417
+
418
+ ### AccessToken Features
419
+
420
+ Instances of `OAuth2::AccessToken` handle request signing and token expiration.
421
+
422
+ - **Snake Case & Indifferent Access**: `response.parsed` returns a `SnakyHash` allowing access via string/symbol and snake_case keys even if the provider returns CamelCase.
423
+ - **Auto-Refresh**: You can manually check `token.expired?` and call `token.refresh`.
424
+ - **Serialization**: Persist tokens using `token.to_hash` and restore via `OAuth2::AccessToken.from_hash(client, hash)`.
425
+
419
426
  ### snake_case and indifferent access in Response#parsed
420
427
 
421
428
  ```ruby
@@ -553,6 +560,13 @@ ENV["OAUTH_DEBUG"] = "true"
553
560
  By default, debug output will go to `$stdout`. This can be overridden when
554
561
  initializing your OAuth2::Client.
555
562
 
563
+ Sensitive values are filtered from debug logging output using:
564
+
565
+ - `OAuth2.config[:filtered_label]`
566
+ - `OAuth2.config[:filtered_debug_keys]`
567
+
568
+ Debug logging remains opt-in and should still be used cautiously in production environments.
569
+
556
570
  ```ruby
557
571
  require "oauth2"
558
572
  client = OAuth2::Client.new(
@@ -565,15 +579,30 @@ client = OAuth2::Client.new(
565
579
 
566
580
  </details>
567
581
 
582
+ ### Request Target Trust Boundaries
583
+
584
+ This gem supports request flows that can involve absolute URLs in addition to relative paths.
585
+ That flexibility can expand trust boundaries when a token-bearing client is asked to send requests
586
+ to caller-provided targets.
587
+
588
+ Practical guidance:
589
+
590
+ - prefer relative paths where practical
591
+ - do not pass untrusted absolute URLs into token-bearing clients
592
+ - validate or allowlist request targets at the application layer today if your deployment has strict trust-boundary requirements
593
+
594
+ This release line does not yet enforce same-host or allowlist request policy automatically.
595
+ If stricter outbound request controls are needed, they should currently be implemented by the calling application.
596
+
568
597
  ### OAuth2::Response
569
598
 
570
599
  The `AccessToken` methods `#get`, `#post`, `#put` and `#delete` and the generic `#request`
571
- will return an instance of the #OAuth2::Response class.
600
+ will return an instance of the `OAuth2::Response` class.
572
601
 
573
602
  This instance contains a `#parsed` method that will parse the response body and
574
603
  return a Hash-like [`SnakyHash::StringKeyed`](https://gitlab.com/ruby-oauth/snaky_hash/-/blob/main/lib/snaky_hash/string_keyed.rb) if the `Content-Type` is `application/x-www-form-urlencoded` or if
575
- the body is a JSON object. It will return an Array if the body is a JSON
576
- array. Otherwise, it will return the original body string.
604
+ the body is a JSON object. It will return an Array if the body is a JSON
605
+ array. Otherwise, it will return the original body string.
577
606
 
578
607
  The original response body, headers, and status can be accessed via their
579
608
  respective methods.
@@ -615,16 +644,22 @@ Response instance will contain the `OAuth2::Error` instance.
615
644
 
616
645
  ### Authorization Grants
617
646
 
618
- Note on OAuth 2.1 (draft):
647
+ Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
648
+ authentication grant types have helper strategy classes that simplify client
649
+ use. They are available via the [`#auth_code`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
650
+ [`#implicit`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
651
+ [`#password`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/password.rb),
652
+ [`#client_credentials`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/client_credentials.rb), and
653
+ [`#assertion`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/assertion.rb) methods respectively.
654
+
655
+ #### OAuth 2.1 (draft) Note:
619
656
 
620
- - PKCE is required for all OAuth clients using the authorization code flow (especially public clients). Implement PKCE in your app when required by your provider. See RFC 7636 and RFC 8252.
621
- - Redirect URIs must be compared using exact string matching by the Authorization Server.
622
- - The Implicit grant (response_type=token) and the Resource Owner Password Credentials grant are omitted from OAuth 2.1; they remain here for OAuth 2.0 compatibility but should be avoided for new apps.
623
- - Bearer tokens in the query string are omitted due to security risks; prefer Authorization header usage.
624
- - Refresh tokens for public clients must either be sender-constrained (e.g., DPoP/MTLS) or one-time use.
625
- - The definitions of public and confidential clients are simplified to refer only to whether the client has credentials.
657
+ - **PKCE** is required for all OAuth clients using the authorization code flow (especially public clients). Implement PKCE in your app when required by your provider. See RFC 7636 and RFC 8252.
658
+ - **Implicit grant** (response_type=token) and **Resource Owner Password Credentials grant** are omitted from OAuth 2.1; they remain here for OAuth 2.0 compatibility but should be avoided for new apps.
659
+ - **Redirect URIs** must be compared using exact string matching by the Authorization Server.
626
660
 
627
- References:
661
+ <details markdown="1">
662
+ <summary>OAuth 2.1 (draft) References</summary>
628
663
 
629
664
  - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
630
665
  - Aaron Parecki: https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1
@@ -633,13 +668,7 @@ References:
633
668
  - Video: https://www.youtube.com/watch?v=g_aVPdwBTfw
634
669
  - Differences overview: https://fusionauth.io/learn/expert-advice/oauth/differences-between-oauth-2-oauth-2-1/
635
670
 
636
- Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
637
- authentication grant types have helper strategy classes that simplify client
638
- use. They are available via the [`#auth_code`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
639
- [`#implicit`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
640
- [`#password`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/password.rb),
641
- [`#client_credentials`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/client_credentials.rb), and
642
- [`#assertion`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/assertion.rb) methods respectively.
671
+ </details>
643
672
 
644
673
  These aren't full examples, but demonstrative of the differences between usage for each strategy.
645
674
 
@@ -774,7 +803,7 @@ Notes:
774
803
 
775
804
  </details>
776
805
 
777
- ### Instagram API (verb‑dependent token mode)
806
+ ### Verb‑dependent Token Mode
778
807
 
779
808
  Providers like Instagram require the access token to be sent differently depending on the HTTP verb:
780
809
 
@@ -783,6 +812,14 @@ Providers like Instagram require the access token to be sent differently dependi
783
812
 
784
813
  Since v2.0.15, you can configure an AccessToken with a verb‑dependent mode. The gem will choose how to send the token based on the request method.
785
814
 
815
+ Tips:
816
+
817
+ - Avoid query‑string bearer tokens unless required by your provider. Instagram explicitly requires it for `GET` requests.
818
+ - If you need a custom rule, you can pass a `Proc` for `mode`, e.g. `mode: ->(verb) { verb == :get ? :query : :header }`.
819
+
820
+ <details markdown="1">
821
+ <summary>Instagram API Example</summary>
822
+
786
823
  Example: exchanging and refreshing long‑lived Instagram tokens, and making API calls
787
824
 
788
825
  ```ruby
@@ -841,10 +878,7 @@ me = long_lived.get("/me", params: {fields: "id,username"}).parsed
841
878
  # long_lived.post("/me/media", body: {image_url: "https://...", caption: "hello"})
842
879
  ```
843
880
 
844
- Tips:
845
-
846
- - Avoid query‑string bearer tokens unless required by your provider. Instagram explicitly requires it for `GET` requests.
847
- - If you need a custom rule, you can pass a `Proc` for `mode`, e.g. `mode: ->(verb) { verb == :get ? :query : :header }`.
881
+ </details>
848
882
 
849
883
  ### Refresh Tokens
850
884
 
@@ -1085,11 +1119,12 @@ access = client.get_token({
1085
1119
  })
1086
1120
  ```
1087
1121
 
1088
- ### OpenID Connect (OIDC) Notes
1122
+ ### OpenID Connect (OIDC)
1089
1123
 
1090
- - If the token response includes an `id_token` (a JWT), this gem surfaces it but does not validate the signature. Use a JWT library and your provider's JWKs to verify it.
1091
- - For private_key_jwt client authentication, provide `auth_scheme: :private_key_jwt` and ensure your key configuration matches the provider requirements.
1092
- - See [OIDC.md](OIDC.md) for a more complete OIDC overview, example, and links to the relevant specifications.
1124
+ - If the token response includes an `id_token` (a JWT), this gem surfaces it in `token.params['id_token']`.
1125
+ - **Note**: This gem does **not** validate the signature of the `id_token`. You must use a JWT library (like the `jwt` [gem](https://github.com/jwt/ruby-jwt)) and your provider's JWKs to verify it.
1126
+ - For `private_key_jwt` client authentication, provide `auth_scheme: :private_key_jwt` and ensure your key configuration matches the provider requirements.
1127
+ - See [OIDC.md](OIDC.md) for a more complete OIDC overview and examples.
1093
1128
 
1094
1129
  ### Debugging
1095
1130
 
@@ -1139,6 +1174,10 @@ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day
1139
1174
 
1140
1175
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
1141
1176
  No sponsors yet. Be the first!
1177
+
1178
+ ### Open Collective for Donors
1179
+
1180
+ [Bill Woika](https://opencollective.com/bill-woika)
1142
1181
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
1143
1182
 
1144
1183
  [kettle-readme-backers]: https://github.com/ruby-oauth/oauth2/blob/main/exe/kettle-readme-backers
@@ -1257,7 +1296,7 @@ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright
1257
1296
 
1258
1297
  <ul>
1259
1298
  <li>
1260
- Copyright (c) 2017 – 2025 Peter H. Boling, of
1299
+ Copyright (c) 2017 – 2026 Peter H. Boling, of
1261
1300
  <a href="https://discord.gg/3qme4XHNKN">
1262
1301
  Galtzo.com
1263
1302
  <picture>
@@ -1384,8 +1423,6 @@ Thanks for RTFM. ☺️
1384
1423
  [📜gh-wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
1385
1424
  [👽dl-rank]: https://bestgems.org/gems/oauth2
1386
1425
  [👽dl-ranki]: https://img.shields.io/gem/rd/oauth2.svg
1387
- [👽oss-help]: https://www.codetriage.com/ruby-oauth/oauth2
1388
- [👽oss-helpi]: https://www.codetriage.com/ruby-oauth/oauth2/badges/users.svg
1389
1426
  [👽version]: https://bestgems.org/gems/oauth2
1390
1427
  [👽versioni]: https://img.shields.io/gem/v/oauth2.svg
1391
1428
  [🏀qlty-mnt]: https://qlty.sh/gh/ruby-oauth/projects/oauth2
@@ -1477,7 +1514,7 @@ Thanks for RTFM. ☺️
1477
1514
  [📌gitmoji]: https://gitmoji.dev
1478
1515
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1479
1516
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1480
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.526-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1517
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.527-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1481
1518
  [🔐security]: SECURITY.md
1482
1519
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1483
1520
  [🔐irp]: IRP.md
data/REEK CHANGED
@@ -0,0 +1,2 @@
1
+ ./reek: 1: ./reek:: not found
2
+ ./reek: 2: ./reek:: not found
data/RUBOCOP.md CHANGED
File without changes
data/SECURITY.md CHANGED
@@ -12,7 +12,7 @@ To report a security vulnerability, please use the
12
12
  [Tidelift security contact](https://tidelift.com/security).
13
13
  Tidelift will coordinate the fix and disclosure.
14
14
 
15
- More detailed explanation of the process is in [IRP.md][IRP]
15
+ More detailed explanation of the process is in [IRP.md][IRP].
16
16
 
17
17
  ## Additional Support
18
18
 
data/THREAT_MODEL.md CHANGED
@@ -63,7 +63,16 @@ This document outlines the threat model for the `oauth2` Ruby gem, which impleme
63
63
  - Validate and sanitize all inputs
64
64
  - Use parameterized queries and safe APIs
65
65
 
66
- ### 5.7 Insufficient Logging and Monitoring
66
+ ### 5.7 Request-Target Trust Boundary Expansion
67
+ - **Threat:** Applications may pass untrusted or insufficiently validated absolute URLs into request paths that can carry OAuth credentials or authenticated state.
68
+ - **Risk:** This can expand trust boundaries, contributing to token leakage, authenticated requests to unintended hosts, or SSRF-like pivoting in the surrounding application.
69
+ - **Mitigations:**
70
+ - Prefer relative paths where practical
71
+ - Do not pass untrusted absolute URLs into token-bearing clients
72
+ - Validate or allowlist outbound request targets at the application layer
73
+ - Treat request-target validation as a separate concern from log redaction and token storage
74
+
75
+ ### 5.8 Insufficient Logging and Monitoring
67
76
  - **Threat:** Attacks go undetected
68
77
  - **Mitigations:**
69
78
  - Log security-relevant events (without sensitive data)
@@ -57,26 +57,23 @@ module OAuth2
57
57
  def from_hash(client, hash)
58
58
  fresh = hash.dup
59
59
  # If token_name is present, then use that key name
60
- key =
61
- if fresh.key?(:token_name)
62
- t_key = fresh[:token_name]
63
- no_tokens_warning(fresh, t_key)
64
- t_key
65
- else
66
- # Otherwise, if one of the supported default keys is present, use whichever has precedence
67
- supported_keys = TOKEN_KEY_LOOKUP & fresh.keys
68
- t_key = supported_keys[0]
69
- extra_tokens_warning(supported_keys, t_key)
70
- t_key
71
- end
60
+ if fresh.key?(:token_name)
61
+ t_key = fresh[:token_name]
62
+ no_tokens_warning(fresh, t_key)
63
+ else
64
+ # Otherwise, if one of the supported default keys is present, use whichever has precedence
65
+ supported_keys = TOKEN_KEY_LOOKUP & fresh.keys
66
+ t_key = supported_keys[0]
67
+ extra_tokens_warning(supported_keys, t_key)
68
+ end
72
69
  # :nocov:
73
70
  # TODO: Get rid of this branching logic when dropping Hashie < v3.2
74
71
  token = if !defined?(Hashie::VERSION) # i.e. <= "1.1.0"; the first Hashie to ship with a VERSION constant
75
72
  warn("snaky_hash and oauth2 will drop support for Hashie v0 in the next major version. Please upgrade to a modern Hashie.")
76
73
  # There is a bug in Hashie v0, which is accounts for.
77
- fresh.delete(key) || fresh[key] || ""
74
+ fresh.delete(t_key) || fresh[t_key] || ""
78
75
  else
79
- fresh.delete(key) || ""
76
+ fresh.delete(t_key) || ""
80
77
  end
81
78
  # :nocov:
82
79
  new(client, token, fresh)
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OAuth2
4
+ AUTH_SANITIZER = begin
5
+ auth_sanitizer_requirement = Gem::Requirement.new("~> 0.1", ">= 0.1.3")
6
+ auth_sanitizer_spec = Gem.loaded_specs["auth-sanitizer"]
7
+ unless auth_sanitizer_spec && auth_sanitizer_requirement.satisfied_by?(auth_sanitizer_spec.version)
8
+ # :nocov:
9
+ auth_sanitizer_spec = Gem::Specification.find_by_name("auth-sanitizer", auth_sanitizer_requirement)
10
+ # :nocov:
11
+ end
12
+
13
+ auth_sanitizer_loader_path = File.join(
14
+ auth_sanitizer_spec.full_gem_path,
15
+ "lib/auth_sanitizer/loader.rb",
16
+ )
17
+ unless File.file?(auth_sanitizer_loader_path)
18
+ # :nocov:
19
+ raise LoadError, "oauth2 requires auth-sanitizer #{auth_sanitizer_requirement}; " \
20
+ "loader not found at #{auth_sanitizer_loader_path}"
21
+ # :nocov:
22
+ end
23
+
24
+ auth_sanitizer_loader_namespace = Module.new
25
+ auth_sanitizer_loader_namespace.module_eval(
26
+ File.read(auth_sanitizer_loader_path),
27
+ auth_sanitizer_loader_path,
28
+ 1,
29
+ )
30
+
31
+ auth_sanitizer_loader_namespace.
32
+ const_get(:AuthSanitizer).
33
+ const_get(:Loader).
34
+ load_isolated
35
+ end
36
+ end
@@ -51,13 +51,15 @@ module OAuth2
51
51
  end
52
52
  end
53
53
 
54
- # Encodes a Basic Authorization header value for the provided credentials.
55
- #
56
- # @param [String] user The client identifier
57
- # @param [String] password The client secret
58
- # @return [String] The value to use for the Authorization header
59
- def self.encode_basic_auth(user, password)
60
- "Basic #{Base64.strict_encode64("#{user}:#{password}")}"
54
+ class << self
55
+ # Encodes a Basic Authorization header value for the provided credentials.
56
+ #
57
+ # @param [String] user The client identifier
58
+ # @param [String] password The client secret
59
+ # @return [String] The value to use for the Authorization header
60
+ def encode_basic_auth(user, password)
61
+ "Basic #{Base64.strict_encode64("#{user}:#{password}")}"
62
+ end
61
63
  end
62
64
 
63
65
  private
data/lib/oauth2/client.rb CHANGED
@@ -42,7 +42,7 @@ module OAuth2
42
42
  # @option options [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday
43
43
  # @option options [Boolean] :raise_errors (true) whether to raise an OAuth2::Error on responses with 400+ status codes
44
44
  # @option options [Integer] :max_redirects (5) maximum number of redirects to follow
45
- # @option options [Logger] :logger (::Logger.new($stdout)) Logger instance for HTTP request/response output; requires OAUTH_DEBUG to be true
45
+ # @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]`.
46
46
  # @option options [Class] :access_token_class (AccessToken) class to use for access tokens; you can subclass OAuth2::AccessToken, @version 2.0+
47
47
  # @option options [Hash] :ssl SSL options for Faraday
48
48
  #
@@ -563,7 +563,15 @@ module OAuth2
563
563
  end
564
564
 
565
565
  def oauth_debug_logging(builder)
566
- builder.response(:logger, options[:logger], bodies: true) if OAuth2::OAUTH_DEBUG
566
+ builder.response(
567
+ :logger,
568
+ OAuth2::AUTH_SANITIZER::SanitizedLogger.new(
569
+ options[:logger],
570
+ filtered_keys: OAuth2.config[:filtered_debug_keys],
571
+ label: OAuth2.config[:filtered_label],
572
+ ),
573
+ bodies: true,
574
+ ) if OAuth2::OAUTH_DEBUG
567
575
  end
568
576
  end
569
577
  end
data/lib/oauth2/error.rb CHANGED
@@ -17,6 +17,8 @@ module OAuth2
17
17
  # @param [OAuth2::Response, Hash, Object] response A Response or error payload
18
18
  def initialize(response)
19
19
  @response = response
20
+ @code = nil
21
+ @description = nil
20
22
  if response.respond_to?(:parsed)
21
23
  if response.parsed.is_a?(Hash)
22
24
  @code = response.parsed["error"]
@@ -1,52 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth2
2
- # Mixin that redacts sensitive instance variables in #inspect output.
4
+ # Permanent alias for {OAuth2::AUTH_SANITIZER::FilteredAttributes}.
3
5
  #
4
- # Classes include this module and declare which attributes should be filtered
5
- # using {.filtered_attributes}. Any instance variable name that includes one of
6
- # those attribute names will be shown as [FILTERED] in the object's inspect.
7
- module FilteredAttributes
8
- # Hook invoked when the module is included. Extends the including class with
9
- # class-level helpers.
10
- #
11
- # @param [Class] base The including class
12
- # @return [void]
13
- def self.included(base)
14
- base.extend(ClassMethods)
15
- end
16
-
17
- # Class-level helpers for configuring filtered attributes.
18
- module ClassMethods
19
- # Declare attributes that should be redacted in inspect output.
20
- #
21
- # @param [Array<Symbol, String>] attributes One or more attribute names
22
- # @return [void]
23
- def filtered_attributes(*attributes)
24
- @filtered_attribute_names = attributes.map(&:to_sym)
25
- end
26
-
27
- # The configured attribute names to filter.
28
- #
29
- # @return [Array<Symbol>]
30
- def filtered_attribute_names
31
- @filtered_attribute_names || []
32
- end
33
- end
34
-
35
- # Custom inspect that redacts configured attributes.
36
- #
37
- # @return [String]
38
- def inspect
39
- filtered_attribute_names = self.class.filtered_attribute_names
40
- return super if filtered_attribute_names.empty?
41
-
42
- inspected_vars = instance_variables.map do |var|
43
- if filtered_attribute_names.any? { |filtered_var| var.to_s.include?(filtered_var.to_s) }
44
- "#{var}=[FILTERED]"
45
- else
46
- "#{var}=#{instance_variable_get(var).inspect}"
47
- end
48
- end
49
- "#<#{self.class}:#{object_id} #{inspected_vars.join(", ")}>"
50
- end
51
- end
6
+ # This constant is intentionally kept in the `OAuth2` namespace because it
7
+ # was part of the public API before the implementation was extracted into the
8
+ # `auth-sanitizer` gem. It will **not** be deprecated or removed.
9
+ FilteredAttributes = OAuth2::AUTH_SANITIZER::FilteredAttributes
52
10
  end
@@ -43,18 +43,20 @@ module OAuth2
43
43
  "text/plain" => :text,
44
44
  }
45
45
 
46
- # Adds a new content type parser.
47
- #
48
- # @param [Symbol] key A descriptive symbol key such as :json or :query
49
- # @param [Array<String>, String] mime_types One or more mime types to which this parser applies
50
- # @yield [String] Block that will be called to parse the response body
51
- # @yieldparam [String] body The response body to parse
52
- # @return [void]
53
- def self.register_parser(key, mime_types, &block)
54
- key = key.to_sym
55
- @@parsers[key] = block
56
- Array(mime_types).each do |mime_type|
57
- @@content_types[mime_type] = key
46
+ class << self
47
+ # Adds a new content type parser.
48
+ #
49
+ # @param [Symbol] key A descriptive symbol key such as :json or :query
50
+ # @param [Array<String>, String] mime_types One or more mime types to which this parser applies
51
+ # @yield [String] Block that will be called to parse the response body
52
+ # @yieldparam [String] body The response body to parse
53
+ # @return [void]
54
+ def register_parser(key, mime_types, &block)
55
+ key = key.to_sym
56
+ @@parsers[key] = block
57
+ Array(mime_types).each do |mime_type|
58
+ @@content_types[mime_type] = key
59
+ end
58
60
  end
59
61
  end
60
62
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -2,6 +2,7 @@
2
2
 
3
3
  module OAuth2
4
4
  module Version
5
- VERSION = "2.0.18"
5
+ VERSION = "2.0.20"
6
6
  end
7
+ VERSION = Version::VERSION # Traditional Constant Location
7
8
  end
data/lib/oauth2.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # includes modules from stdlib
4
- require "cgi"
4
+ require "cgi/escape"
5
5
  require "time"
6
6
 
7
7
  # third party gems
@@ -10,6 +10,7 @@ require "version_gem"
10
10
 
11
11
  # includes gem files
12
12
  require_relative "oauth2/version"
13
+ require_relative "oauth2/auth_sanitizer"
13
14
  require_relative "oauth2/filtered_attributes"
14
15
  require_relative "oauth2/error"
15
16
  require_relative "oauth2/authenticator"
@@ -43,38 +44,59 @@ module OAuth2
43
44
  # config[:silence_no_tokens_warning] = false
44
45
  # end
45
46
  #
47
+ # @example Customize filtered output markers and debug-log value filtering by key name
48
+ # OAuth2.configure do |config|
49
+ # config[:filtered_label] = "[REDACTED]"
50
+ # config[:filtered_debug_keys] += ["client_assertion"]
51
+ # end
52
+ #
53
+ # Existing objects and logger wrappers snapshot filtering configuration during
54
+ # initialization. Changing these config values later affects only newly
55
+ # initialized objects and debug loggers.
56
+ #
46
57
  # @return [SnakyHash::SymbolKeyed] A mutable Hash-like config with symbol keys
47
58
  DEFAULT_CONFIG = SnakyHash::SymbolKeyed.new(
48
59
  silence_extra_tokens_warning: true,
49
60
  silence_no_tokens_warning: true,
61
+ filtered_label: "[FILTERED]",
62
+ filtered_debug_keys: %w[
63
+ access_token
64
+ refresh_token
65
+ id_token
66
+ client_secret
67
+ assertion
68
+ code_verifier
69
+ token
70
+ ],
50
71
  )
51
72
 
52
73
  # The current runtime configuration for the library.
53
74
  #
54
75
  # @return [SnakyHash::SymbolKeyed]
55
- @config = DEFAULT_CONFIG.dup
76
+ CONFIG = DEFAULT_CONFIG.dup
56
77
 
57
78
  class << self
58
- # Access the current configuration.
79
+ def config
80
+ CONFIG
81
+ end
82
+
83
+ # Configure global library behavior.
59
84
  #
60
- # Prefer using {OAuth2.configure} to mutate configuration.
85
+ # Yields the mutable configuration object so callers can update settings.
61
86
  #
62
- # @return [SnakyHash::SymbolKeyed]
63
- attr_reader :config
87
+ # @yieldparam [SnakyHash::SymbolKeyed] config the configuration object
88
+ # @return [void]
89
+ def configure
90
+ yield config
91
+ end
64
92
  end
65
-
66
- # Configure global library behavior.
67
- #
68
- # Yields the mutable configuration object so callers can update settings.
69
- #
70
- # @yieldparam [SnakyHash::SymbolKeyed] config the configuration object
71
- # @return [void]
72
- def configure
73
- yield @config
74
- end
75
- module_function :configure
76
93
  end
77
94
 
95
+ # Wire OAuth2::AUTH_SANITIZER's label provider to read from OAuth2.config so that
96
+ # FilteredAttributes-bearing objects and OAuth2::AUTH_SANITIZER::SanitizedLogger instances
97
+ # pick up OAuth2.config[:filtered_label] at their initialization time.
98
+ OAuth2::AUTH_SANITIZER.filtered_label_provider = -> { OAuth2.config[:filtered_label] }
99
+
78
100
  # Extend OAuth2::Version with VersionGem helpers to provide semantic version helpers.
79
101
  OAuth2::Version.class_eval do
80
102
  extend VersionGem::Basic
File without changes
File without changes
File without changes
data/sig/oauth2/error.rbs CHANGED
File without changes
@@ -1,6 +1,11 @@
1
1
  module OAuth2
2
2
  module FilteredAttributes
3
+ module InitializerMethods
4
+ def initialize: (*untyped args) { () -> untyped } -> untyped
5
+ end
6
+
3
7
  def self.included: (untyped) -> untyped
4
- def filtered_attributes: (*String) -> void
8
+ def filtered_attributes: (*(String | Symbol)) -> void
9
+ def thing_filter: () -> OAuth2::ThingFilter
5
10
  end
6
11
  end
File without changes
@@ -0,0 +1,32 @@
1
+ module OAuth2
2
+ class SanitizedLogger
3
+ def initialize: (untyped logger) -> void
4
+
5
+ def add: (untyped severity, ?untyped message, ?untyped progname) { () -> untyped } -> untyped
6
+ def <<: (String message) -> untyped
7
+ def debug: (?untyped progname) { () -> untyped } -> untyped
8
+ def info: (?untyped progname) { () -> untyped } -> untyped
9
+ def warn: (?untyped progname) { () -> untyped } -> untyped
10
+ def error: (?untyped progname) { () -> untyped } -> untyped
11
+ def fatal: (?untyped progname) { () -> untyped } -> untyped
12
+ def unknown: (?untyped progname) { () -> untyped } -> untyped
13
+ def close: () -> void
14
+ def formatter: () -> untyped
15
+ def formatter=: (untyped formatter) -> void
16
+ def level: () -> untyped
17
+ def level=: (untyped level) -> void
18
+ def progname: () -> untyped
19
+ def progname=: (untyped progname) -> void
20
+ def respond_to_missing?: (Symbol method_name, ?bool include_private) -> bool
21
+ def method_missing: (Symbol method_name, *untyped args) { () -> untyped } -> untyped
22
+
23
+ private
24
+
25
+ def log: (Symbol level, ?untyped progname) { () -> untyped } -> untyped
26
+ def sanitize: (untyped message) -> untyped
27
+ def thing_filter: () -> OAuth2::ThingFilter
28
+ def sanitize_authorization_header: (String message) -> String
29
+ def sanitize_json_pairs: (String message) -> String
30
+ def sanitize_form_and_query_pairs: (String message) -> String
31
+ end
32
+ end
File without changes
@@ -0,0 +1,10 @@
1
+ module OAuth2
2
+ class ThingFilter
3
+ attr_reader things: Array[String]
4
+ attr_reader label: String
5
+
6
+ def initialize: (Enumerable[untyped] things, label: String) -> void
7
+ def filtered?: (untyped thing_name) -> bool
8
+ def pattern_source: () -> String
9
+ end
10
+ end
File without changes
data/sig/oauth2.rbs CHANGED
File without changes
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.18
4
+ version: 2.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Boling
@@ -39,6 +39,26 @@ cert_chain:
39
39
  -----END CERTIFICATE-----
40
40
  date: 1980-01-02 00:00:00.000000000 Z
41
41
  dependencies:
42
+ - !ruby/object:Gem::Dependency
43
+ name: auth-sanitizer
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.1'
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 0.1.3
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "~>"
57
+ - !ruby/object:Gem::Version
58
+ version: '0.1'
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.3
42
62
  - !ruby/object:Gem::Dependency
43
63
  name: faraday
44
64
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +156,7 @@ dependencies:
136
156
  version: '2.0'
137
157
  - - ">="
138
158
  - !ruby/object:Gem::Version
139
- version: 2.0.3
159
+ version: 2.0.4
140
160
  type: :runtime
141
161
  prerelease: false
142
162
  version_requirements: !ruby/object:Gem::Requirement
@@ -146,7 +166,7 @@ dependencies:
146
166
  version: '2.0'
147
167
  - - ">="
148
168
  - !ruby/object:Gem::Version
149
- version: 2.0.3
169
+ version: 2.0.4
150
170
  - !ruby/object:Gem::Dependency
151
171
  name: version_gem
152
172
  requirement: !ruby/object:Gem::Requirement
@@ -227,28 +247,28 @@ dependencies:
227
247
  requirements:
228
248
  - - "~>"
229
249
  - !ruby/object:Gem::Version
230
- version: '1.1'
250
+ version: '2.0'
231
251
  type: :development
232
252
  prerelease: false
233
253
  version_requirements: !ruby/object:Gem::Requirement
234
254
  requirements:
235
255
  - - "~>"
236
256
  - !ruby/object:Gem::Version
237
- version: '1.1'
257
+ version: '2.0'
238
258
  - !ruby/object:Gem::Dependency
239
259
  name: bundler-audit
240
260
  requirement: !ruby/object:Gem::Requirement
241
261
  requirements:
242
262
  - - "~>"
243
263
  - !ruby/object:Gem::Version
244
- version: 0.9.2
264
+ version: 0.9.3
245
265
  type: :development
246
266
  prerelease: false
247
267
  version_requirements: !ruby/object:Gem::Requirement
248
268
  requirements:
249
269
  - - "~>"
250
270
  - !ruby/object:Gem::Version
251
- version: 0.9.2
271
+ version: 0.9.3
252
272
  - !ruby/object:Gem::Dependency
253
273
  name: rake
254
274
  requirement: !ruby/object:Gem::Requirement
@@ -290,6 +310,9 @@ dependencies:
290
310
  - - "~>"
291
311
  - !ruby/object:Gem::Version
292
312
  version: '3.0'
313
+ - - ">="
314
+ - !ruby/object:Gem::Version
315
+ version: 3.0.6
293
316
  type: :development
294
317
  prerelease: false
295
318
  version_requirements: !ruby/object:Gem::Requirement
@@ -297,6 +320,9 @@ dependencies:
297
320
  - - "~>"
298
321
  - !ruby/object:Gem::Version
299
322
  version: '3.0'
323
+ - - ">="
324
+ - !ruby/object:Gem::Version
325
+ version: 3.0.6
300
326
  - !ruby/object:Gem::Dependency
301
327
  name: kettle-test
302
328
  requirement: !ruby/object:Gem::Requirement
@@ -306,7 +332,7 @@ dependencies:
306
332
  version: '1.0'
307
333
  - - ">="
308
334
  - !ruby/object:Gem::Version
309
- version: 1.0.6
335
+ version: 1.0.10
310
336
  type: :development
311
337
  prerelease: false
312
338
  version_requirements: !ruby/object:Gem::Requirement
@@ -316,7 +342,7 @@ dependencies:
316
342
  version: '1.0'
317
343
  - - ">="
318
344
  - !ruby/object:Gem::Version
319
- version: 1.0.6
345
+ version: 1.0.10
320
346
  - !ruby/object:Gem::Dependency
321
347
  name: ruby-progressbar
322
348
  requirement: !ruby/object:Gem::Requirement
@@ -340,7 +366,7 @@ dependencies:
340
366
  version: '1.0'
341
367
  - - ">="
342
368
  - !ruby/object:Gem::Version
343
- version: 1.0.2
369
+ version: 1.0.3
344
370
  type: :development
345
371
  prerelease: false
346
372
  version_requirements: !ruby/object:Gem::Requirement
@@ -350,7 +376,7 @@ dependencies:
350
376
  version: '1.0'
351
377
  - - ">="
352
378
  - !ruby/object:Gem::Version
353
- version: 1.0.2
379
+ version: 1.0.3
354
380
  - !ruby/object:Gem::Dependency
355
381
  name: gitmoji-regex
356
382
  requirement: !ruby/object:Gem::Requirement
@@ -428,6 +454,7 @@ files:
428
454
  - THREAT_MODEL.md
429
455
  - lib/oauth2.rb
430
456
  - lib/oauth2/access_token.rb
457
+ - lib/oauth2/auth_sanitizer.rb
431
458
  - lib/oauth2/authenticator.rb
432
459
  - lib/oauth2/client.rb
433
460
  - lib/oauth2/error.rb
@@ -447,17 +474,19 @@ files:
447
474
  - sig/oauth2/error.rbs
448
475
  - sig/oauth2/filtered_attributes.rbs
449
476
  - sig/oauth2/response.rbs
477
+ - sig/oauth2/sanitized_logger.rbs
450
478
  - sig/oauth2/strategy.rbs
479
+ - sig/oauth2/thing_filter.rbs
451
480
  - sig/oauth2/version.rbs
452
481
  homepage: https://github.com/ruby-oauth/oauth2
453
482
  licenses:
454
483
  - MIT
455
484
  metadata:
456
485
  homepage_uri: https://oauth2.galtzo.com/
457
- source_code_uri: https://github.com/ruby-oauth/oauth2/tree/v2.0.18
458
- changelog_uri: https://github.com/ruby-oauth/oauth2/blob/v2.0.18/CHANGELOG.md
486
+ source_code_uri: https://github.com/ruby-oauth/oauth2/tree/v2.0.20
487
+ changelog_uri: https://github.com/ruby-oauth/oauth2/blob/v2.0.20/CHANGELOG.md
459
488
  bug_tracker_uri: https://github.com/ruby-oauth/oauth2/issues
460
- documentation_uri: https://www.rubydoc.info/gems/oauth2/2.0.18
489
+ documentation_uri: https://www.rubydoc.info/gems/oauth2/2.0.20
461
490
  mailing_list_uri: https://groups.google.com/g/oauth-ruby
462
491
  funding_uri: https://github.com/sponsors/pboling
463
492
  wiki_uri: https://gitlab.com/ruby-oauth/oauth2/-/wiki
@@ -466,11 +495,11 @@ metadata:
466
495
  rubygems_mfa_required: 'true'
467
496
  post_install_message: |2
468
497
 
469
- ---+++--- oauth2 v2.0.18 ---+++---
498
+ ---+++--- oauth2 v2.0.20 ---+++---
470
499
 
471
500
  (minor) ⚠️ BREAKING CHANGES ⚠️ when upgrading from < v2
472
501
  • Summary of breaking changes: https://gitlab.com/ruby-oauth/oauth2#what-is-new-for-v20
473
- • Changes in this patch: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.18/CHANGELOG.md#2015-2025-09-08
502
+ • Changes in this patch: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.20/CHANGELOG.md#2015-2025-09-08
474
503
 
475
504
  News:
476
505
  1. New documentation website, including for OAuth 2.1 and OIDC: https://oauth2.galtzo.com
@@ -513,7 +542,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
513
542
  - !ruby/object:Gem::Version
514
543
  version: '0'
515
544
  requirements: []
516
- rubygems_version: 3.7.2
545
+ rubygems_version: 4.0.11
517
546
  specification_version: 4
518
547
  summary: "\U0001F510 OAuth 2.0, 2.1 & OIDC Core Ruby implementation"
519
548
  test_files: []
metadata.gz.sig CHANGED
Binary file