oauth2 2.0.10 → 2.0.12

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: 74ad05aadb0f9e990bd0aec8907e7d60236d03d8eb4dd9c4c5c338f361d44181
4
- data.tar.gz: 2996484493c6d56af8ea4ef873c823c91e6ad15f3f3a63c3816ab1f760179327
3
+ metadata.gz: a3c3d9d7db53b8fd6bfda9314ac4f6ebde44a08d8f9544c909b055dd5d1a5c37
4
+ data.tar.gz: cfe4790fb04182fc2357d1015988f9b4bf77540f350a998a448fadb43c75d510
5
5
  SHA512:
6
- metadata.gz: 6dd801a4085ccb1c9928ae975cac3563bc28c0c01461659cc90f3090c9a09794c686b5475c4425d1becd95df1abea5e129876a3fcb6abc78f348ff4b738169c0
7
- data.tar.gz: 323321a6e9d5dcd8b53691fbdda4df2acc24d7eb7b03e788c028712b64590d387eabf1f6c2d68abfaeef49901073e9db80d09f0d5abce9434f1290b7edc34db4
6
+ metadata.gz: b66e35c72d4f4ba2e38cb3a2147bc5aca5c05a5675d04515b2927f0c3c687444348b309799383a960351d106a8fbc1fa6a6bba08e672cef22059d1d4c03cbc26
7
+ data.tar.gz: 55395528b41b5487eb5ef1f8ab2800028f63b51ef2d889d06d4e16237bc470d3cc8c7c9ec8ba8e895988665e6c9a9f5ad84e513de6dad66b276873eae85fbaad
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -12,7 +12,55 @@ and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2.
12
12
  ### Fixed
13
13
  ### Security
14
14
 
15
- ## [2.0.10] - 2025-05-16
15
+ ## [2.0.12] - 2025-05-31
16
+ - TAG: [v2.0.12][2.0.12t]
17
+ - Line Coverage: 100.0% (520 / 520)
18
+ - Branch Coverage: 100.0% (174 / 174)
19
+ - 80.00% documented
20
+ ### Added
21
+ - [gh652][gh652] - Support IETF rfc7515 JSON Web Signature - JWS by @mridang
22
+ - Support JWT `kid` for key discovery and management
23
+ - More Documentation by @pboling
24
+ - Documented Serialization Extensions
25
+ - Added Gatzo.com FLOSS logo by @Aboling0, CC BY-SA 4.0
26
+ - Documentation site @ https://oauth2.galtzo.com now complete
27
+ ### Changed
28
+ - Updates to gemspec (email, funding url, post install message)
29
+ ### Deprecated
30
+ ### Removed
31
+ ### Fixed
32
+ - Documentation Typos by @pboling
33
+ ### Security
34
+
35
+ [gh652]: https://github.com/oauth-xx/oauth2/pull/652
36
+
37
+ ## [2.0.11] - 2025-05-23
38
+ - TAG: [v2.0.11][2.0.11t]
39
+ - COVERAGE: 100.00% -- 518/518 lines in 14 files
40
+ - BRANCH COVERAGE: 100.00% -- 172/172 branches in 14 files
41
+ - 80.00% documented
42
+ ### Added
43
+ - [gh651](https://github.com/oauth-xx/oauth2/pull/651) - `:snaky_hash_klass` option (@pboling)
44
+ - More documentation
45
+ - Codeberg as ethical mirror (@pboling)
46
+ - https://codeberg.org/oauth-xx/oauth2
47
+ - Don't check for cert if SKIP_GEM_SIGNING is set (@pboling)
48
+ - All runtime deps, including oauth-xx sibling gems, are now tested against HEAD (@pboling)
49
+ - YARD config, GFM compatible with relative file links (@pboling)
50
+ - Documentation site on GitHub Pages (@pboling)
51
+ - [oauth2.galtzo.com](https://oauth2.galtzo.com)
52
+ - [!649](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/649) - Test compatibility with all key minor versions of Hashie v0, v1, v2, v3, v4, v5, HEAD (@pboling)
53
+ - [gh651](https://github.com/oauth-xx/oauth2/pull/651) - Mock OAuth2 server for testing (@pboling)
54
+ - https://github.com/navikt/mock-oauth2-server
55
+ ### Changed
56
+ - [gh651](https://github.com/oauth-xx/oauth2/pull/651) - Upgraded to snaky_hash v2.0.3 (@pboling)
57
+ - Provides solution for serialization issues
58
+ - Updated `spec.homepage_uri` in gemspec to GitHub Pages YARD documentation site (@pboling)
59
+ ### Fixed
60
+ - [gh650](https://github.com/oauth-xx/oauth2/pull/650) - Regression in return type of `OAuth2::Response#parsed` (@pboling)
61
+ - Incorrect documentation related to silencing warnings (@pboling)
62
+
63
+ ## [2.0.10] - 2025-05-17
16
64
  - TAG: [v2.0.10][2.0.10t]
17
65
  - COVERAGE: 100.00% -- 518/518 lines in 14 files
18
66
  - BRANCH COVERAGE: 100.00% -- 170/170 branches in 14 files
@@ -369,8 +417,12 @@ and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2.
369
417
 
370
418
  [gemfiles/readme]: gemfiles/README.md
371
419
 
372
- [Unreleased]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.0.10...HEAD
373
- [2.0.10]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.09....v2.0.10
420
+ [Unreleased]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.0.12...HEAD
421
+ [2.0.12]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.0.11...v2.0.12
422
+ [2.0.12t]: https://gitlab.com/oauth-xx/oauth2/-/tags/v2.0.12
423
+ [2.0.11]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.0.10...v2.0.11
424
+ [2.0.11t]: https://gitlab.com/oauth-xx/oauth2/-/tags/v2.0.11
425
+ [2.0.10]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.0.9...v2.0.10
374
426
  [2.0.10t]: https://gitlab.com/oauth-xx/oauth2/-/tags/v2.0.10
375
427
  [2.0.9]: https://gitlab.com/oauth-xx/oauth2/-/compare/v2.0.8...v2.0.9
376
428
  [2.0.9t]: https://gitlab.com/oauth-xx/oauth2/-/tags/v2.0.9
data/CODE_OF_CONDUCT.md CHANGED
File without changes
data/CONTRIBUTING.md CHANGED
@@ -96,7 +96,7 @@ NOTE: To build without signing the gem you must set `SKIP_GEM_SIGNING` to some v
96
96
 
97
97
  ### To release a new version:
98
98
 
99
- 1. Run `bin/setup && bin/rake` as a tests, coverage, & linting sanity check
99
+ 1. Run `bin/setup && bin/rake` as a "test, coverage, & linting" sanity check
100
100
  2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes
101
101
  3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock`
102
102
  4. Run `git commit -am "🔖 Prepare release v<VERSION>"` to commit the changes
@@ -114,7 +114,7 @@ NOTE: To build without signing the gem you must set `SKIP_GEM_SIGNING` to some v
114
114
  11. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr])
115
115
  to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums`
116
116
  [gem][💎stone_checksums].
117
- - Checksums will be committed automatically by the script, but not pushed
117
+ - Checksums will be committed automatically by the script but not pushed
118
118
  12. Run `bundle exec rake release` which will create a git tag for the version,
119
119
  push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems]
120
120
 
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
1
  <p align="center">
2
+ <a href="https://discord.gg/3qme4XHNKN" target="_blank" rel="noopener">
3
+ <img width="124px" src="https://github.com/oauth-xx/oauth2/raw/main/docs/images/logo/galtzo-floss-logos-original.svg?raw=true" alt="Galtzo.com Logo by Aboling0, CC BY-SA 4.0">
4
+ </a>
2
5
  <a href="http://oauth.net/2/" target="_blank" rel="noopener">
3
6
  <img src="https://github.com/oauth-xx/oauth2/raw/main/docs/images/logo/oauth2-logo-124px.png?raw=true" alt="OAuth 2.0 Logo by Chris Messina, CC BY-SA 3.0">
4
7
  </a>
@@ -9,49 +12,28 @@
9
12
 
10
13
  ## 🔐 OAuth2
11
14
 
12
- [![Version][👽versioni]][👽version]
13
- [![License: MIT][📄license-img]][📄license-ref]
14
- [![Downloads Rank][👽dl-ranki]][👽dl-rank]
15
- [![Open Source Helpers][👽oss-helpi]][👽oss-help]
16
- [![Depfu][🔑depfui♻️]][🔑depfu]
17
- [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls]
18
- [![QLTY Test Coverage][🔑cc-covi♻️]][🔑cc-cov]
19
- [![Maintainability][🔑cc-mnti♻️]][🔑cc-mnt]
20
- [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf]
21
- [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf]
22
- [![CI Current][🚎11-c-wfi]][🚎11-c-wf]
23
- [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf]
24
- [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf]
25
- [![CI Supported][🚎6-s-wfi]][🚎6-s-wf]
26
- [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf]
27
- [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf]
28
- [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf]
29
- [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf]
30
- [![CI Style][🚎5-st-wfi]][🚎5-st-wf]
15
+ [![Version][👽versioni]][👽version] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![Depfu][🔑depfui♻️]][🔑depfu] [![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 Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-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 Caboose is an absolute WAGON][🚎13-cbs-wfi]][🚎13-cbs-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL]
31
16
 
32
17
  ---
33
18
 
34
- [![Liberapay Patrons][⛳liberapay-img]][⛳liberapay]
35
- [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor]
36
- [![Buy me a coffee][🖇buyme-small-img]][🖇buyme]
37
- [![Donate on Polar][🖇polar-img]][🖇polar]
38
- [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi]
39
- [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon]
19
+ [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon]
40
20
 
41
21
  OAuth 2.0 is the industry-standard protocol for authorization.
42
22
  OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications,
43
23
  desktop applications, mobile phones, and living room devices.
44
24
  This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications.
45
25
 
46
- | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
47
- |-----------------------------------------------|----------------|--------|-----|------|----------------|-------------|
48
- | 🧪 [oauth-xx/oauth2 on GitLab][📜src-gl] | The Truth | 💚 | 💚 | 💚 | 🏀 Tiny Matrix | ➖ |
49
- | 🐙 [oauth-xx/oauth2 on GitHub][📜src-gh] | A Dirty Mirror | 💚 | 💚 | ➖ | 💯 Full Matrix | ➖ |
50
- | 🤼 [OAuth Ruby Google Group][⛳gg-discussions] | "Active" | | ➖ | | ➖ | 💚 |
26
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
27
+ |-----------------------------------------------|-------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
28
+ | 🧪 [oauth-xx/oauth2 on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ |
29
+ | 🧊 [oauth-xx/oauth2 on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
30
+ | 🐙 [oauth-xx/oauth2 on GitHub][📜src-gh] | A Dirty Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | ➖ |
31
+ | 🤼 [OAuth Ruby Google Group][⛳gg-discussions] | "Active" | ➖ | ➖ | ➖ | ➖ | [💚][⛳gg-discussions] |
32
+ | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
51
33
 
52
34
  ### Upgrading Runtime Gem Dependencies
53
35
 
54
- This project sits underneath a large portion of the authentication systems on the internet.
36
+ This project sits underneath a large portion of the authorization systems on the internet.
55
37
  According to GitHub's project tracking, which I believe only reports on public projects,
56
38
  [100,000+ projects](https://github.com/oauth-xx/oauth2/network/dependents), and
57
39
  [500+ packages](https://github.com/oauth-xx/oauth2/network/dependents?dependent_type=PACKAGE) depend on this project.
@@ -69,27 +51,30 @@ covering the latest patch for each of the following minor versions:
69
51
  * MRI Ruby @ v2.3, v2.4, v2.5, v2.6, v2.7, v3.0, v3.1, v3.2, v3.3, v3.4, HEAD
70
52
  * NOTE: This gem will still install on ruby v2.2, but vanilla GitHub Actions no longer supports testing against it, so YMMV.
71
53
  * JRuby @ v9.2, v9.3, v9.4, v10.0, HEAD
72
- * TruffleRuby @ v23.1, v23.2, HEAD
73
- * gem `faraday` @ v0, v1, v2, HEAD
74
- * gem `jwt` @ v1, v2, v3, HEAD
75
- * gem `logger` @ v1.2, v1.5, v1.7, HEAD
76
- * gem `multi_xml` @ v0.5, v0.6, v0.7, HEAD
77
- * gem `rack` @ v1.2, v1.6, v2, v3, HEAD
54
+ * TruffleRuby @ v23.1, v24.1, HEAD
55
+ * gem `faraday` @ v0, v1, v2, HEAD ⏩️ [lostisland/faraday](https://github.com/lostisland/faraday)
56
+ * gem `jwt` @ v1, v2, v3, HEAD ⏩️ [jwt/ruby-jwt](https://github.com/jwt/ruby-jwt)
57
+ * gem `logger` @ v1.2, v1.5, v1.7, HEAD ⏩️ [ruby/logger](https://github.com/ruby/logger)
58
+ * gem `multi_xml` @ v0.5, v0.6, v0.7, HEAD ⏩️ [sferik/multi_xml](https://github.com/sferik/multi_xml)
59
+ * gem `rack` @ v1.2, v1.6, v2, v3, HEAD ⏩️ [rack/rack](https://github.com/rack/rack)
60
+ * gem `snaky_hash` @ v2, HEAD ⏩️ [oauth-xx/snaky_hash](https://gitlab.com/oauth-xx/snaky_hash)
61
+ * gem `version_gem` @ v1, HEAD ⏩️ [oauth-xx/version_gem](https://gitlab.com/oauth-xx/version_gem)
62
+
63
+ The last two were extracted from this gem. They are part of the `oauth-xx` org,
64
+ and are developed in tight collaboration with this gem.
65
+
66
+ Also, where reasonable, tested against the runtime dependencies of those dependencies:
67
+
68
+ * gem `hashie` @ v0, v1, v2, v3, v4, v5, HEAD ⏩️ [hashie/hashie](https://github.com/hashie/hashie)
69
+
70
+ #### You should upgrade this gem with confidence\*.
78
71
 
79
72
  - This gem follows a _strict & correct_ (according to the maintainer of SemVer; [more info][sv-pub-api]) interpretation of SemVer.
80
73
  - Dropping support for **any** of the runtime dependency versions above will be a major version bump.
81
74
  - If you aren't on one of the minor versions above, make getting there a priority.
82
- - You should upgrade this gem with confidence\*.
83
75
  - You should upgrade the dependencies of this gem with confidence\*.
84
76
  - Please do upgrade, and then, when it goes smooth as butter [please sponsor me][🖇sponsor]. Thanks!
85
77
 
86
- If you are thinking, "that list is missing two runtime dependencies", you are correct!
87
- Both of them were extracted from this gem. They are part of the `oauth-xx` org,
88
- and are developed in tight collaboration with this gem, so not much more needs to be said about them.
89
-
90
- * gem `snaky_hash` - https://gitlab.com/oauth-xx/snaky_hash
91
- * gem `version_gem` - https://gitlab.com/oauth-xx/version_gem
92
-
93
78
  [sv-pub-api]: #-is-platform-support-part-of-the-public-api
94
79
 
95
80
  \* MIT license; I am unable to make guarantees.
@@ -158,30 +143,33 @@ One of these might be what you are looking for:
158
143
 
159
144
  ## 💡 Info you can shake a stick at
160
145
 
161
- | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
162
- |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
163
- | Works with JRuby | [![JRuby 9.2 Compat][💎jruby-9.2i]][🚎10-j-wf] [![JRuby 9.3 Compat][💎jruby-9.3i]][🚎10-j-wf] [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] |
164
- | Works with Truffle Ruby | [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] [![Truffle Ruby HEAD Compat][💎truby-headi]][🚎3-hd-wf] |
165
- | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] |
166
- | Works with MRI Ruby 2 | [![Ruby 2.3 Compat][💎ruby-2.3i]][🚎1-an-wf] [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎1-an-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] |
167
- | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
168
- | Documentation | [![Discussion][⛳gg-discussions-img]][⛳gg-discussions] [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![HEAD on RubyDoc.info][📜docs-head-rd-img]][🚎yard-head] [![BDFL Blog][🚂bdfl-blog-img]][🚂bdfl-blog] [![Wiki][📜wiki-img]][📜wiki] |
169
- | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Enforced Code Style][💎rlts-img]][💎rlts] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![FOSSA][🏘fossa-img]][🏘fossa] |
170
- | Expert 1:1 Support | [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] `or` [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
171
- | Enterprise Support | [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]<br/>💡Subscribe for support guarantees covering _all_ FLOSS dependencies!<br/>💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]!<br/>💡Tidelift pays maintainers to maintain the software you depend on!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers! |
172
- | Comrade BDFL 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
173
- | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
146
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
147
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
148
+ | Works with JRuby | [![JRuby 9.2 Compat][💎jruby-9.2i]][🚎10-j-wf] [![JRuby 9.3 Compat][💎jruby-9.3i]][🚎10-j-wf] [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] |
149
+ | Works with Truffle Ruby | [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] [![Truffle Ruby HEAD Compat][💎truby-headi]][🚎3-hd-wf] |
150
+ | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] |
151
+ | Works with MRI Ruby 2 | [![Ruby 2.3 Compat][💎ruby-2.3i]][🚎13-cbs-wf] [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎1-an-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] |
152
+ | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
153
+ | Documentation | [![Discussion][⛳gg-discussions-img]][⛳gg-discussions] [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![HEAD on RubyDoc.info][📜docs-head-rd-img]][🚎yard-head] [![BDFL Blog][🚂bdfl-blog-img]][🚂bdfl-blog] [![Wiki][📜wiki-img]][📜wiki] |
154
+ | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
155
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] |
156
+ | Support | [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
157
+ | Enterprise Support | [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]<br/>💡Subscribe for support guarantees covering _all_ FLOSS dependencies!<br/>💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]!<br/>💡Tidelift pays maintainers to maintain the software you depend on!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers! |
158
+ | Comrade BDFL 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
159
+ | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
174
160
 
175
161
  ## 🚀 Release Documentation
176
162
 
177
163
  ### Version 2.0.x
178
164
 
179
165
  <details>
180
- <summary>2.0.x CHANGELOGs and READMEs</summary>
166
+ <summary>2.0.x CHANGELOG and README</summary>
181
167
 
182
168
  | Version | Release Date | CHANGELOG | README |
183
169
  |---------|--------------|---------------------------------------|---------------------------------|
184
- | 2.0.10 | 2025-05-16 | [v2.0.10 CHANGELOG][2.0.10-changelog] | [v2.0.10 README][2.0.10-readme] |
170
+ | 2.0.12 | 2025-05-31 | [v2.0.12 CHANGELOG][2.0.12-changelog] | [v2.0.12 README][2.0.12-readme] |
171
+ | 2.0.11 | 2025-05-23 | [v2.0.11 CHANGELOG][2.0.11-changelog] | [v2.0.11 README][2.0.11-readme] |
172
+ | 2.0.10 | 2025-05-17 | [v2.0.10 CHANGELOG][2.0.10-changelog] | [v2.0.10 README][2.0.10-readme] |
185
173
  | 2.0.9 | 2022-09-16 | [v2.0.9 CHANGELOG][2.0.9-changelog] | [v2.0.9 README][2.0.9-readme] |
186
174
  | 2.0.8 | 2022-09-01 | [v2.0.8 CHANGELOG][2.0.8-changelog] | [v2.0.8 README][2.0.8-readme] |
187
175
  | 2.0.7 | 2022-08-22 | [v2.0.7 CHANGELOG][2.0.7-changelog] | [v2.0.7 README][2.0.7-readme] |
@@ -194,7 +182,9 @@ One of these might be what you are looking for:
194
182
  | 2.0.0 | 2022-06-21 | [v2.0.0 CHANGELOG][2.0.0-changelog] | [v2.0.0 README][2.0.0-readme] |
195
183
  </details>
196
184
 
197
- [2.0.10-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2010---2025-05-16
185
+ [2.0.12-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2012---2025-05-31
186
+ [2.0.11-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2011---2025-05-23
187
+ [2.0.10-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2010---2025-05-17
198
188
  [2.0.9-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#209---2022-09-16
199
189
  [2.0.8-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#208---2022-09-01
200
190
  [2.0.7-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#207---2022-08-22
@@ -206,6 +196,8 @@ One of these might be what you are looking for:
206
196
  [2.0.1-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#201---2022-06-22
207
197
  [2.0.0-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#200---2022-06-21
208
198
 
199
+ [2.0.12-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.12/README.md
200
+ [2.0.11-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.11/README.md
209
201
  [2.0.10-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.10/README.md
210
202
  [2.0.9-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.9/README.md
211
203
  [2.0.8-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.8/README.md
@@ -304,7 +296,7 @@ by following the instructions below.
304
296
  Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:
305
297
 
306
298
  ```shell
307
- gem cert --add <(curl -Ls https://raw.github.com/kettle-rb/oauth2/main/certs/pboling.pem)
299
+ gem cert --add <(curl -Ls https://raw.github.com/oauth-xx/oauth2/main/certs/pboling.pem)
308
300
  ```
309
301
 
310
302
  You only need to do that once. Then proceed to install with:
@@ -342,27 +334,30 @@ For more see [SECURITY.md][🔐security].
342
334
 
343
335
  ## What is new for v2.0?
344
336
 
345
- - Officially support Ruby versions >= 2.7
346
- - Unofficially support Ruby versions >= 2.5
347
- - Incidentally support Ruby versions >= 2.2
337
+ - Works with Ruby versions >= 2.2
348
338
  - Drop support for the expired MAC Draft (all versions)
349
- - Support IETF rfc7523 JWT Bearer Tokens
350
- - Support IETF rfc7231 Relative Location in Redirect
351
- - Support IETF rfc6749 Don't set oauth params when nil
339
+ - Support IETF rfc7515 JSON Web Signature - JWS (since v2.0.12)
340
+ - Support JWT `kid` for key discovery and management
341
+ - Support IETF rfc7523 JWT Bearer Tokens (since v2.0.0)
342
+ - Support IETF rfc7231 Relative Location in Redirect (since v2.0.0)
343
+ - Support IETF rfc6749 Don't set oauth params when nil (since v2.0.0)
344
+ - Support IETF rfc7009 Token Revocation (since v2.0.10)
352
345
  - Support [OIDC 1.0 Private Key JWT](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication); based on the OAuth JWT assertion specification [(RFC 7523)](https://tools.ietf.org/html/rfc7523)
353
346
  - Support new formats, including from [jsonapi.org](http://jsonapi.org/format/): `application/vdn.api+json`, `application/vnd.collection+json`, `application/hal+json`, `application/problem+json`
354
- - Adds new option to `OAuth2::Client#get_token`:
347
+ - Adds option to `OAuth2::Client#get_token`:
355
348
  - `:access_token_class` (`AccessToken`); user specified class to use for all calls to `get_token`
356
- - Adds new option to `OAuth2::AccessToken#initialize`:
349
+ - Adds option to `OAuth2::AccessToken#initialize`:
357
350
  - `:expires_latency` (`nil`); number of seconds by which AccessToken validity will be reduced to offset latency
358
351
  - By default, keys are transformed to snake case.
359
- - Original keys will still work as previously, in most scenarios, thanks to `rash_alt` gem.
352
+ - Original keys will still work as previously, in most scenarios, thanks to [snaky_hash][snaky_hash] gem.
360
353
  - However, this is a _breaking_ change if you rely on `response.parsed.to_h` to retain the original case, and the original wasn't snake case, as the keys in the result will be snake case.
361
354
  - As of version 2.0.4 you can turn key transformation off with the `snaky: false` option.
362
355
  - By default, the `:auth_scheme` is now `:basic_auth` (instead of `:request_body`)
363
356
  - Third-party strategies and gems may need to be updated if a provider was requiring client id/secret in the request body
364
357
  - [... A lot more](https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md#200-2022-06-21-tag)
365
358
 
359
+ [snaky_hash]: https://gitlab.com/oauth-xx/snaky_hash
360
+
366
361
  ## Compatibility
367
362
 
368
363
  Targeted ruby compatibility is non-EOL versions of Ruby, currently 3.2, 3.3, and 3.4.
@@ -377,7 +372,7 @@ This gem is tested against MRI, JRuby, and Truffleruby.
377
372
  Each of those has varying versions that target a specific version of MRI Ruby.
378
373
  This gem should work in the just-listed Ruby engines according to the targeted MRI compatibility in the table below.
379
374
  If you would like to add support for additional engines,
380
- see `gemfiles/README.md`, then submit a PR to the correct maintenance branch as according to the table below.
375
+ see [gemfiles/README.md](gemfiles/README.md), then submit a PR to the correct maintenance branch as according to the table below.
381
376
  </details>
382
377
 
383
378
  <details>
@@ -404,25 +399,25 @@ of a major release, support for that Ruby version may be dropped.
404
399
  | 3️⃣ | older | N/A | Best of luck to you! | Please upgrade! | |
405
400
 
406
401
  NOTE: The 1.4 series will only receive critical security updates.
407
- See [SECURITY.md][🚎sec-pol]
402
+ See [SECURITY.md][🔐security].
408
403
 
409
- ## Usage Examples
404
+ ## 🔧 Basic Usage
410
405
 
411
406
  ### Global Configuration
412
407
 
413
- If you started seeing this warning, but everything is working fine, you can now silence it.
414
- ```log
415
- OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key
416
- ```
408
+ You can turn on additional warnings.
417
409
 
418
410
  ```ruby
419
411
  OAuth2.configure do |config|
420
- config.silence_extra_tokens_warning = true # default: false
421
- config.silence_no_tokens_warning = true # default: false, if you want to also silence warnings about no tokens
412
+ # Turn on a warning like:
413
+ # OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key
414
+ config.silence_extra_tokens_warning = false # default: true
415
+ # Set to true if you want to also show warnings about no tokens
416
+ config.silence_no_tokens_warning = false # default: true,
422
417
  end
423
418
  ```
424
419
 
425
- This comes from ambiguity in the spec about which token is the right token.
420
+ The "extra tokens" problem comes from ambiguity in the spec about which token is the right token.
426
421
  Some OAuth 2.0 standards legitimately have multiple tokens.
427
422
  You may need to subclass `OAuth2::AccessToken`, or write your own custom alternative to it, and pass it in.
428
423
  Specify your custom class with the `access_token_class` option.
@@ -491,9 +486,98 @@ response.parsed.access_token # => "aaaaaaaa"
491
486
  response.parsed[:access_token] # => "aaaaaaaa"
492
487
  response.parsed.additional_data # => "additional"
493
488
  response.parsed[:additional_data] # => "additional"
494
- response.parsed.class.name # => OAuth2::SnakyHash (subclass of Hashie::Mash::Rash, from `rash_alt` gem)
489
+ response.parsed.class.name # => SnakyHash::StringKeyed (from snaky_hash gem)
490
+ ```
491
+
492
+ #### Serialization
493
+
494
+ As of v2.0.11, if you need to serialize the parsed result, you can!
495
+
496
+ There are two ways to do this, globally, or discretely. The discrete way is recommended.
497
+
498
+ 1. Globally configure `SnakyHash::StringKeyed` to use the serializer. Put this in your code somewhere reasonable (like an initializer for Rails):
499
+
500
+ ```ruby
501
+ SnakyHash::StringKeyed.class_eval do
502
+ extend SnakyHash::Serializer
503
+ end
504
+ ```
505
+
506
+ 2. Discretely configure a custom Snaky Hash class to use the serializer:
507
+
508
+ ```ruby
509
+ class MySnakyHash < SnakyHash::StringKeyed
510
+ # Give this hash class `dump` and `load` abilities!
511
+ extend SnakyHash::Serializer
512
+ end
513
+
514
+ # And tell your client to use the custom class in each call:
515
+ client = OAuth2::Client.new("client_id", "client_secret", site: "https://example.org/oauth2")
516
+ token = client.get_token({snaky_hash_klass: MySnakyHash})
517
+ ```
518
+
519
+ ##### Serialization Extensions
520
+
521
+ There are a few hacks you may need in your class to support Ruby < 2.4.2 or < 2.6.
522
+ They are likely not needed if you are on a newer Ruby.
523
+ See `response_spec.rb` if you need to study the hacks for older Rubies.
524
+
525
+ ```ruby
526
+ class MySnakyHash < SnakyHash::StringKeyed
527
+ # Give this hash class `dump` and `load` abilities!
528
+ extend SnakyHash::Serializer
529
+
530
+ #### Serialization Extentions
531
+ #
532
+ # Act on the non-hash values (including the values of hashes) as they are dumped to JSON
533
+ # In other words, this retains nested hashes, and only the deepest leaf nodes become bananas.
534
+ # WARNING: This is a silly example!
535
+ dump_value_extensions.add(:to_fruit) do |value|
536
+ "banana" # => Make values "banana" on dump
537
+ end
538
+
539
+ # Act on the non-hash values (including the values of hashes) as they are loaded from the JSON dump
540
+ # In other words, this retains nested hashes, and only the deepest leaf nodes become ***.
541
+ # WARNING: This is a silly example!
542
+ load_value_extensions.add(:to_stars) do |value|
543
+ "***" # Turn dumped bananas into *** when they are loaded
544
+ end
545
+
546
+ # Act on the entire hash as it is prepared for dumping to JSON
547
+ # WARNING: This is a silly example!
548
+ dump_hash_extensions.add(:to_cheese) do |value|
549
+ if value.is_a?(Hash)
550
+ value.transform_keys do |key|
551
+ split = key.split("_")
552
+ first_word = split[0]
553
+ key.sub(first_word, "cheese")
554
+ end
555
+ else
556
+ value
557
+ end
558
+ end
559
+
560
+ # Act on the entire hash as it is loaded from the JSON dump
561
+ # WARNING: This is a silly example!
562
+ load_hash_extensions.add(:to_pizza) do |value|
563
+ if value.is_a?(Hash)
564
+ res = klass.new
565
+ value.keys.each_with_object(res) do |key, result|
566
+ split = key.split("_")
567
+ last_word = split[-1]
568
+ new_key = key.sub(last_word, "pizza")
569
+ result[new_key] = value[key]
570
+ end
571
+ res
572
+ else
573
+ value
574
+ end
575
+ end
576
+ end
495
577
  ```
496
578
 
579
+ See `response_spec.rb`, or the [oauth-xx/snaky_hash](https://gitlab.com/oauth-xx/snaky_hash) gem for more ideas.
580
+
497
581
  #### What if I hate snakes and/or indifference?
498
582
 
499
583
  ```ruby
@@ -506,9 +590,9 @@ response.parsed.class.name # => Hash (just, regular old Hash)
506
590
  ```
507
591
 
508
592
  <details>
509
- <summary>Debugging</summary>
593
+ <summary>Debugging & Logging</summary>
510
594
 
511
- Set an environment variable, however you would [normally do that](https://github.com/bkeepers/dotenv).
595
+ Set an environment variable as per usual (e.g. with [dotenv](https://github.com/bkeepers/dotenv)).
512
596
 
513
597
  ```ruby
514
598
  # will log both request and response, including bodies
@@ -529,27 +613,27 @@ client = OAuth2::Client.new(
529
613
  ```
530
614
  </details>
531
615
 
532
- ## OAuth2::Response
616
+ ### OAuth2::Response
533
617
 
534
618
  The `AccessToken` methods `#get`, `#post`, `#put` and `#delete` and the generic `#request`
535
619
  will return an instance of the #OAuth2::Response class.
536
620
 
537
621
  This instance contains a `#parsed` method that will parse the response body and
538
- return a Hash-like [`OAuth2::SnakyHash`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/snaky_hash.rb) if the `Content-Type` is `application/x-www-form-urlencoded` or if
622
+ return a Hash-like [`SnakyHash::StringKeyed`](https://gitlab.com/oauth-xx/snaky_hash/-/blob/main/lib/snaky_hash/string_keyed.rb) if the `Content-Type` is `application/x-www-form-urlencoded` or if
539
623
  the body is a JSON object. It will return an Array if the body is a JSON
540
624
  array. Otherwise, it will return the original body string.
541
625
 
542
626
  The original response body, headers, and status can be accessed via their
543
627
  respective methods.
544
628
 
545
- ## OAuth2::AccessToken
629
+ ### OAuth2::AccessToken
546
630
 
547
631
  If you have an existing Access Token for a user, you can initialize an instance
548
632
  using various class methods including the standard new, `from_hash` (if you have
549
633
  a hash of the values), or `from_kvform` (if you have an
550
634
  `application/x-www-form-urlencoded` encoded string of the values).
551
635
 
552
- ## OAuth2::Error
636
+ ### OAuth2::Error
553
637
 
554
638
  On 400+ status code responses, an `OAuth2::Error` will be raised. If it is a
555
639
  standard OAuth2 error response, the body will be parsed and `#code` and `#description` will contain the values provided from the error and
@@ -561,9 +645,9 @@ option on initialization of the client. In this case the `OAuth2::Response`
561
645
  instance will be returned as usual and on 400+ status code responses, the
562
646
  Response instance will contain the `OAuth2::Error` instance.
563
647
 
564
- ## Authorization Grants
648
+ ### Authorization Grants
565
649
 
566
- Currently the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
650
+ Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
567
651
  authentication grant types have helper strategy classes that simplify client
568
652
  use. They are available via the [`#auth_code`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
569
653
  [`#implicit`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
@@ -610,10 +694,6 @@ access = client.auth_code.get_token("code_value", redirect_uri: "http://localhos
610
694
  You can always use the `#request` method on the `OAuth2::Client` instance to make
611
695
  requests for tokens for any Authentication grant type.
612
696
 
613
- ### 🚀 Release Instructions
614
-
615
- See [CONTRIBUTING.md][🤝contributing].
616
-
617
697
  ## 🔐 Security
618
698
 
619
699
  See [SECURITY.md][🔐security].
@@ -621,18 +701,21 @@ See [SECURITY.md][🔐security].
621
701
  ## 🤝 Contributing
622
702
 
623
703
  If you need some ideas of where to help, you could work on adding more code coverage,
624
- or if it is already 💯 (see [below](#code-coverage)) check TODOs (see [below](#todos)),
625
- or check [issues][🤝issues], or [PRs][🤝pulls],
704
+ or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues], or [PRs][🤝gh-pulls],
626
705
  or use the gem and think about how it could be better.
627
706
 
628
707
  We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
629
708
 
630
709
  See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
631
710
 
711
+ ### 🚀 Release Instructions
712
+
713
+ See [CONTRIBUTING.md][🤝contributing].
714
+
632
715
  ### Code Coverage
633
716
 
634
717
  [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls]
635
- [![QLTY Test Coverage][🔑cc-covi♻️]][🔑cc-cov]
718
+ [![QLTY Test Coverage][🔑qlty-covi♻️]][🔑qlty-cov]
636
719
 
637
720
  ### 🪇 Code of Conduct
638
721
 
@@ -700,20 +783,15 @@ The gem is available as open source under the terms of
700
783
  the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref].
701
784
  See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer].
702
785
 
703
- [![FOSSA Status][fossa2-img])][fossa2]
704
-
705
- [fossa2]: https://app.fossa.io/projects/git%2Bgithub.com%2Foauth-xx%2Foauth2?ref=badge_large
706
- [fossa2-img]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Foauth-xx%2Foauth2.svg?type=large
707
-
708
786
  ### © Copyright
709
787
 
710
788
  <ul>
711
789
  <li>
712
790
  2017 - 2025 Peter H. Boling, of
713
- <a href="https://railsbling.com">
714
- RailsBling.com
791
+ <a href="https://discord.gg/3qme4XHNKN">
792
+ Galtzo.com
715
793
  <picture>
716
- <img alt="Rails Bling" height="20" src="https://railsbling.com/images/logos/RailsBling-TrainLogo.svg" />
794
+ <img src="https://github.com/oauth-xx/oauth2/raw/main/docs/images/logo/galtzo-floss-logos-wordless.svg?raw=true" alt="Galtzo.com Logo by Aboling0, CC BY-SA 4.0" height="20">
717
795
  </picture>
718
796
  </a>, and oauth2 contributors
719
797
  </li>
@@ -734,7 +812,7 @@ or one of the others at the head of this README.
734
812
  [![Buy me a latte][🖇buyme-img]][🖇buyme]
735
813
 
736
814
  [⛳gg-discussions]: https://groups.google.com/g/oauth-ruby
737
- [⛳gg-discussions-img]: https://img.shields.io/badge/google-group-purple.svg?style=flat
815
+ [⛳gg-discussions-img]: https://img.shields.io/badge/google-group-0093D0.svg?style=for-the-badge&logo=google&logoColor=orange
738
816
 
739
817
  [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
740
818
  [⛳️gem-namespace]: https://github.com/oauth-xx/oauth2
@@ -781,7 +859,7 @@ or one of the others at the head of this README.
781
859
  [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green
782
860
  [📜src-gh]: https://github.com/oauth-xx/oauth2
783
861
  [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
784
- [📜docs-head-rd-img]: https://img.shields.io/badge/RubyDoc-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
862
+ [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
785
863
  [📜wiki]: https://gitlab.com/oauth-xx/oauth2/-/wikis/home
786
864
  [📜wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=Wiki&logoColor=white
787
865
  [👽dl-rank]: https://rubygems.org/gems/oauth2
@@ -790,10 +868,10 @@ or one of the others at the head of this README.
790
868
  [👽oss-helpi]: https://www.codetriage.com/oauth-xx/oauth2/badges/users.svg
791
869
  [👽version]: https://rubygems.org/gems/oauth2
792
870
  [👽versioni]: https://img.shields.io/gem/v/oauth2.svg
793
- [🔑cc-mnt]: https://qlty.sh/gh/oauth-xx/projects/oauth2
794
- [🔑cc-mnti♻️]: https://qlty.sh/badges/d3370c2c-8791-4202-9759-76f527f76005/maintainability.svg
795
- [🔑cc-cov]: https://qlty.sh/gh/oauth-xx/projects/oauth2
796
- [🔑cc-covi♻️]: https://qlty.sh/badges/d3370c2c-8791-4202-9759-76f527f76005/test_coverage.svg
871
+ [🔑qlty-mnt]: https://qlty.sh/gh/oauth-xx/projects/oauth2
872
+ [🔑qlty-mnti♻️]: https://qlty.sh/badges/d3370c2c-8791-4202-9759-76f527f76005/maintainability.svg
873
+ [🔑qlty-cov]: https://qlty.sh/gh/oauth-xx/projects/oauth2
874
+ [🔑qlty-covi♻️]: https://qlty.sh/badges/d3370c2c-8791-4202-9759-76f527f76005/test_coverage.svg
797
875
  [🔑codecov]: https://codecov.io/gh/oauth-xx/oauth2
798
876
  [🔑codecovi♻️]: https://codecov.io/gh/oauth-xx/oauth2/graph/badge.svg?token=bNqSzNiuo2
799
877
  [🔑coveralls]: https://coveralls.io/github/oauth-xx/oauth2?branch=main
@@ -826,6 +904,8 @@ or one of the others at the head of this README.
826
904
  [🚎11-c-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/current.yml/badge.svg
827
905
  [🚎12-crh-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/current-runtime-heads.yml
828
906
  [🚎12-crh-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/current-runtime-heads.yml/badge.svg
907
+ [🚎13-cbs-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/caboose.yml
908
+ [🚎13-cbs-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/caboose.yml/badge.svg
829
909
  [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay
830
910
  [⛳liberapay]: https://liberapay.com/pboling/donate
831
911
  [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
@@ -861,8 +941,13 @@ or one of the others at the head of this README.
861
941
  [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red
862
942
  [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green
863
943
  [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue
864
- [🤝issues]: https://github.com/oauth-xx/oauth2/issues
865
- [🤝pulls]: https://github.com/oauth-xx/oauth2/pulls
944
+ [🤝gh-issues]: https://github.com/oauth-xx/oauth2/issues
945
+ [🤝gh-pulls]: https://github.com/oauth-xx/oauth2/pulls
946
+ [🤝gl-issues]: https://gitlab.com/oauth-xx/oauth2/-/issues
947
+ [🤝gl-pulls]: https://gitlab.com/oauth-xx/oauth2/-/merge_requests
948
+ [🤝cb-issues]: https://codeberg.org/oauth-xx/oauth2/issues
949
+ [🤝cb-pulls]: https://codeberg.org/oauth-xx/oauth2/pulls
950
+ [🤝cb-donate]: https://donate.codeberg.org/
866
951
  [🤝contributing]: CONTRIBUTING.md
867
952
  [🔑codecov-g♻️]: https://codecov.io/gh/oauth-xx/oauth2/graphs/tree.svg?token=bNqSzNiuo2
868
953
  [🖐contrib-rocks]: https://contrib.rocks
@@ -870,36 +955,36 @@ or one of the others at the head of this README.
870
955
  [🖐contributors-img]: https://contrib.rocks/image?repo=oauth-xx/oauth2
871
956
  [🚎contributors-gl]: https://gitlab.com/oauth-xx/oauth2/-/graphs/main
872
957
  [🪇conduct]: CODE_OF_CONDUCT.md
873
- [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-4baaaa.svg
958
+ [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
874
959
  [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
875
960
  [📌semver]: https://semver.org/spec/v2.0.0.html
876
- [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-FFDD67.svg?style=flat
961
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
877
962
  [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
878
963
  [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
879
964
  [📌changelog]: CHANGELOG.md
880
965
  [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
881
- [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat
966
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
882
967
  [📌gitmoji]:https://gitmoji.dev
883
- [📌gitmoji-img]:https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square
968
+ [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square
884
969
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
885
970
  [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.518-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
886
971
  [🔐security]: SECURITY.md
887
- [🔐security-img]: https://img.shields.io/badge/security-policy-brightgreen.svg?style=flat
972
+ [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
888
973
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
889
974
  [📄license]: LICENSE.txt
890
975
  [📄license-ref]: https://opensource.org/licenses/MIT
891
- [📄license-img]: https://img.shields.io/badge/License-MIT-green.svg
976
+ [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg
892
977
  [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
893
- [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-brightgreen.svg?style=flat
978
+ [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
894
979
  [🚎yard-current]: http://rubydoc.info/gems/oauth2
895
- [🚎yard-head]: https://rubydoc.info/github/oauth-xx/oauth2/main
980
+ [🚎yard-head]: https://oauth2.galtzo.com
896
981
  [💎stone_checksums]: https://github.com/pboling/stone_checksums
897
982
  [💎SHA_checksums]: https://gitlab.com/oauth-xx/oauth2/-/tree/main/checksums
898
983
  [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
899
- [💎rlts-img]: https://img.shields.io/badge/code_style-rubocop--lts-brightgreen.svg?plastic&logo=ruby&logoColor=white
900
- [🏘fossa]: https://app.fossa.io/projects/git%2Bgithub.com%2Foauth-xx%2Foauth2?ref=badge_shield
901
- [🏘fossa-img]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Foauth-xx%2Foauth2.svg?type=shield
984
+ [💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
902
985
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
986
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
987
+ [✉️discord-invite-img]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge
903
988
 
904
989
  <details>
905
990
  <summary>
@@ -909,14 +994,3 @@ or one of the others at the head of this README.
909
994
  <a rel="me" alt="Follow me on Ruby.social" href="https://ruby.social/@galtzo"><img src="https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=social&label=Follow%20%40galtzo%20on%20Ruby.social"></a>
910
995
  <a rel="me" alt="Follow me on FLOSS.social" href="https://floss.social/@galtzo"><img src="https://img.shields.io/mastodon/follow/110304921404405715?domain=https%3A%2F%2Ffloss.social&style=social&label=Follow%20%40galtzo%20on%20Floss.social"></a>
911
996
  </details>
912
-
913
- <details>
914
- <summary>Deprecated Badges</summary>
915
-
916
- CodeCov currently fails to parse the coverage upload.
917
-
918
- [![CodeCov Test Coverage][🔑codecovi♻️]][🔑codecov]
919
-
920
- [![Coverage Graph][🔑codecov-g♻️]][🔑codecov]
921
-
922
- </details>
data/SECURITY.md CHANGED
@@ -2,25 +2,34 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported | EOL | Post-EOL / Enterprise |
6
- |----------|-----------|---------|---------------------------------------|
7
- | 2.latest | ✅ | 04/2026 | [Tidelift Subscription][tidelift-ref] |
8
- | 1.latest | ✅ | 10/2025 | [Tidelift Subscription][tidelift-ref] |
9
- | <= 1 | ⛔ | ⛔ | ⛔ |
5
+ | Version | Supported | Post-EOL / Enterprise |
6
+ |----------|-----------|---------------------------------------|
7
+ | 2.latest | ✅ | [Tidelift Subscription][tidelift-ref] |
8
+ | 1.latest | ✅ | [Tidelift Subscription][tidelift-ref] |
9
+ | <= 1 | ⛔ | ⛔ |
10
10
 
11
11
  ### EOL Policy
12
12
 
13
13
  Non-commercial support for the oldest version of Ruby (which itself is going EOL) will be dropped each year in April.
14
14
 
15
- ## Reporting a Vulnerability
15
+ ## Security contact information
16
16
 
17
- To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security).
17
+ To report a security vulnerability, please use the
18
+ [Tidelift security contact](https://tidelift.com/security).
18
19
  Tidelift will coordinate the fix and disclosure.
19
20
 
20
- ## OAuth2 for Enterprise
21
+ ## Additional Support
22
+
23
+ If you are interested in support for versions older than the latest release,
24
+ please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
25
+ or find other sponsorship links in the [README].
26
+
27
+ [README]: README.md
28
+
29
+ ## Enterprise Support
21
30
 
22
31
  Available as part of the Tidelift Subscription.
23
32
 
24
- The maintainers of oauth2 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
+ The maintainers of this library 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]
25
34
 
26
35
  [tidelift-ref]: https://tidelift.com/subscription/pkg/rubygems-oauth2?utm_source=rubygems-oauth2&utm_medium=referral&utm_campaign=enterprise&utm_term=repo
@@ -1,5 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :nocov:
4
+ begin
5
+ # The first version of hashie that has a version file was 1.1.0
6
+ # The first version of hashie that required the version file at runtime was 3.2.0
7
+ # If it has already been loaded then this is very low cost, as Kernel.require uses maintains a cache
8
+ # If this it hasn't this will work to get it loaded, and then we will be able to use
9
+ # defined?(Hashie::Version)
10
+ # as a test.
11
+ # TODO: get rid this mess when we drop Hashie < 3.2, as Hashie will self-load its version then
12
+ require "hashie/version"
13
+ rescue LoadError
14
+ nil
15
+ end
16
+ # :nocov:
17
+
3
18
  module OAuth2
4
19
  class AccessToken # rubocop:disable Metrics/ClassLength
5
20
  TOKEN_KEYS_STR = %w[access_token id_token token accessToken idToken].freeze
@@ -54,7 +69,16 @@ module OAuth2
54
69
  extra_tokens_warning(supported_keys, t_key)
55
70
  t_key
56
71
  end
57
- token = fresh.delete(key) || ""
72
+ # :nocov:
73
+ # TODO: Get rid of this branching logic when dropping Hashie < v3.2
74
+ token = if !defined?(Hashie::VERSION) # i.e. <= "1.1.0"; the first Hashie to ship with a VERSION constant
75
+ warn("snaky_hash and oauth2 will drop support for Hashie v0 in the next major version. Please upgrade to a modern Hashie.")
76
+ # There is a bug in Hashie v0, which is accounts for.
77
+ fresh.delete(key) || fresh[key] || ""
78
+ else
79
+ fresh.delete(key) || ""
80
+ end
81
+ # :nocov:
58
82
  new(client, token, fresh)
59
83
  end
60
84
 
data/lib/oauth2/client.rb CHANGED
@@ -19,7 +19,7 @@ module OAuth2
19
19
  # The OAuth2::Client class
20
20
  class Client # rubocop:disable Metrics/ClassLength
21
21
  RESERVED_REQ_KEYS = %w[body headers params redirect_count].freeze
22
- RESERVED_PARAM_KEYS = (RESERVED_REQ_KEYS + %w[parse snaky token_method]).freeze
22
+ RESERVED_PARAM_KEYS = (RESERVED_REQ_KEYS + %w[parse snaky snaky_hash_klass token_method]).freeze
23
23
 
24
24
  include FilteredAttributes
25
25
 
@@ -342,14 +342,26 @@ module OAuth2
342
342
 
343
343
  private
344
344
 
345
- # A generic token request options parser
345
+ # Processes request parameters and transforms them into request options
346
+ #
347
+ # @param [Hash] params the request parameters to process
348
+ # @option params [Symbol] :parse (:automatic) parsing strategy for the response
349
+ # @option params [Boolean] :snaky (true) whether to convert response keys to snake_case
350
+ # @option params [Class] :snaky_hash_klass (SnakyHash::StringKeyed) class to use for snake_case hash conversion
351
+ # @option params [Symbol] :token_method (:post) HTTP method to use for token request
352
+ # @option params [Hash] :headers Additional HTTP headers for the request
353
+ #
354
+ # @return [Hash] the processed request options
355
+ #
356
+ # @api private
346
357
  def params_to_req_opts(params)
347
- parse, snaky, token_method, params, headers = parse_snaky_params_headers(params)
358
+ parse, snaky, snaky_hash_klass, token_method, params, headers = parse_snaky_params_headers(params)
348
359
  req_opts = {
349
360
  raise_errors: options[:raise_errors],
350
361
  token_method: token_method || options[:token_method],
351
362
  parse: parse,
352
363
  snaky: snaky,
364
+ snaky_hash_klass: snaky_hash_klass,
353
365
  }
354
366
  if req_opts[:token_method] == :post
355
367
  # NOTE: If proliferation of request types continues, we should implement a parser solution for Request,
@@ -369,19 +381,22 @@ module OAuth2
369
381
  req_opts
370
382
  end
371
383
 
372
- # Processes and transforms the input parameters for OAuth requests
384
+ # Processes and transforms parameters for OAuth requests
373
385
  #
374
386
  # @param [Hash] params the input parameters to process
375
- # @option params [Symbol, nil] :parse (:automatic) parsing strategy for the response
387
+ # @option params [Symbol] :parse (:automatic) parsing strategy for the response
376
388
  # @option params [Boolean] :snaky (true) whether to convert response keys to snake_case
389
+ # @option params [Class] :snaky_hash_klass (SnakyHash::StringKeyed) class to use for snake_case hash conversion
390
+ # @option params [Symbol] :token_method overrides the default token method for this request
377
391
  # @option params [Hash] :headers HTTP headers for the request
378
392
  #
379
- # @return [Array<(Symbol, Boolean, Hash, Hash)>] Returns an array containing:
380
- # - [Symbol, nil] parse strategy
381
- # - [Boolean] snaky flag for response key transformation
382
- # - [Symbol, nil] token_method overrides options[:token_method] for a request
383
- # - [Hash] processed parameters
384
- # - [Hash] HTTP headers
393
+ # @return [Array<(Symbol, Boolean, Class, Symbol, Hash, Hash)>] Returns an array containing:
394
+ # - parse strategy (Symbol)
395
+ # - snaky flag for response key transformation (Boolean)
396
+ # - hash class for snake_case conversion (Class)
397
+ # - token method override (Symbol, nil)
398
+ # - processed parameters (Hash)
399
+ # - HTTP headers (Hash)
385
400
  #
386
401
  # @api private
387
402
  def parse_snaky_params_headers(params)
@@ -394,11 +409,12 @@ module OAuth2
394
409
  end.to_h
395
410
  parse = params.key?(:parse) ? params.delete(:parse) : Response::DEFAULT_OPTIONS[:parse]
396
411
  snaky = params.key?(:snaky) ? params.delete(:snaky) : Response::DEFAULT_OPTIONS[:snaky]
412
+ snaky_hash_klass = params.key?(:snaky_hash_klass) ? params.delete(:snaky_hash_klass) : Response::DEFAULT_OPTIONS[:snaky_hash_klass]
397
413
  token_method = params.delete(:token_method) if params.key?(:token_method)
398
414
  params = authenticator.apply(params)
399
415
  # authenticator may add :headers, and we separate them from params here
400
416
  headers = params.delete(:headers) || {}
401
- [parse, snaky, token_method, params, headers]
417
+ [parse, snaky, snaky_hash_klass, token_method, params, headers]
402
418
  end
403
419
 
404
420
  # Executes an HTTP request with error handling and response processing
@@ -5,23 +5,39 @@ require "multi_xml"
5
5
  require "rack"
6
6
 
7
7
  module OAuth2
8
- # OAuth2::Response class
8
+ # The Response class handles HTTP responses in the OAuth2 gem, providing methods
9
+ # to access and parse response data in various formats.
10
+ #
11
+ # @since 1.0.0
9
12
  class Response
13
+ # Default configuration options for Response instances
14
+ #
15
+ # @return [Hash] The default options hash
10
16
  DEFAULT_OPTIONS = {
11
17
  parse: :automatic,
12
18
  snaky: true,
19
+ snaky_hash_klass: SnakyHash::StringKeyed,
13
20
  }.freeze
21
+
22
+ # @return [Faraday::Response] The raw Faraday response object
14
23
  attr_reader :response
24
+
25
+ # @return [Hash] The options hash for this instance
15
26
  attr_accessor :options
16
27
 
17
- # Procs that, when called, will parse a response body according
18
- # to the specified format.
28
+ # @private
29
+ # Storage for response body parser procedures
30
+ #
31
+ # @return [Hash<Symbol, Proc>] Hash of parser procs keyed by format symbol
19
32
  @@parsers = {
20
33
  query: ->(body) { Rack::Utils.parse_query(body) },
21
34
  text: ->(body) { body },
22
35
  }
23
36
 
24
- # Content type assignments for various potential HTTP content types.
37
+ # @private
38
+ # Maps content types to parser symbols
39
+ #
40
+ # @return [Hash<String, Symbol>] Hash of content types mapped to parser symbols
25
41
  @@content_types = {
26
42
  "application/x-www-form-urlencoded" => :query,
27
43
  "text/plain" => :text,
@@ -29,9 +45,11 @@ module OAuth2
29
45
 
30
46
  # Adds a new content type parser.
31
47
  #
32
- # @param [Symbol] key A descriptive symbol key such as :json or :query.
33
- # @param [Array] mime_types One or more mime types to which this parser applies.
34
- # @yield [String] A block returning parsed content.
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]
35
53
  def self.register_parser(key, mime_types, &block)
36
54
  key = key.to_sym
37
55
  @@parsers[key] = block
@@ -43,38 +61,48 @@ module OAuth2
43
61
  # Initializes a Response instance
44
62
  #
45
63
  # @param [Faraday::Response] response The Faraday response instance
46
- # @param [Symbol] parse (:automatic) how to parse the response body. one of :query (for x-www-form-urlencoded),
47
- # :json, or :automatic (determined by Content-Type response header)
48
- # @param [true, false] snaky (true) Convert @parsed to a snake-case,
49
- # indifferent-access SnakyHash::StringKeyed, which is a subclass of Hashie::Mash (from hashie gem)?
50
- # @param [Hash] options all other options for initializing the instance
51
- def initialize(response, parse: :automatic, snaky: true, **options)
64
+ # @param [Symbol] parse (:automatic) How to parse the response body
65
+ # @param [Boolean] snaky (true) Whether to convert parsed response to snake_case using SnakyHash
66
+ # @param [Class, nil] snaky_hash_klass (nil) Custom class for snake_case hash conversion
67
+ # @param [Hash] options Additional options for the response
68
+ # @option options [Symbol] :parse (:automatic) Parse strategy (:query, :json, or :automatic)
69
+ # @option options [Boolean] :snaky (true) Enable/disable snake_case conversion
70
+ # @option options [Class] :snaky_hash_klass (SnakyHash::StringKeyed) Class to use for hash conversion
71
+ # @return [OAuth2::Response] The new Response instance
72
+ def initialize(response, parse: :automatic, snaky: true, snaky_hash_klass: nil, **options)
52
73
  @response = response
53
74
  @options = {
54
75
  parse: parse,
55
76
  snaky: snaky,
77
+ snaky_hash_klass: snaky_hash_klass,
56
78
  }.merge(options)
57
79
  end
58
80
 
59
81
  # The HTTP response headers
82
+ #
83
+ # @return [Hash] The response headers
60
84
  def headers
61
85
  response.headers
62
86
  end
63
87
 
64
88
  # The HTTP response status code
89
+ #
90
+ # @return [Integer] The response status code
65
91
  def status
66
92
  response.status
67
93
  end
68
94
 
69
95
  # The HTTP response body
96
+ #
97
+ # @return [String] The response body or empty string if nil
70
98
  def body
71
99
  response.body || ""
72
100
  end
73
101
 
74
- # The {#response} {#body} as parsed by {#parser}.
102
+ # The parsed response body
75
103
  #
76
- # @return [Object] As returned by {#parser} if it is #call-able.
77
- # @return [nil] If the {#parser} is not #call-able.
104
+ # @return [Object, SnakyHash::StringKeyed] The parsed response body
105
+ # @return [nil] If no parser is available
78
106
  def parsed
79
107
  return @parsed if defined?(@parsed)
80
108
 
@@ -91,36 +119,36 @@ module OAuth2
91
119
  end
92
120
 
93
121
  if options[:snaky] && @parsed.is_a?(Hash)
94
- parsed = SnakyHash::StringKeyed.new(@parsed)
95
- @parsed = parsed.to_h
122
+ hash_klass = options[:snaky_hash_klass] || DEFAULT_OPTIONS[:snaky_hash_klass]
123
+ @parsed = hash_klass[@parsed]
96
124
  end
97
125
 
98
126
  @parsed
99
127
  end
100
128
 
101
- # Attempts to determine the content type of the response.
129
+ # Determines the content type of the response
130
+ #
131
+ # @return [String, nil] The content type or nil if headers are not present
102
132
  def content_type
103
133
  return unless response.headers
104
134
 
105
135
  ((response.headers.values_at("content-type", "Content-Type").compact.first || "").split(";").first || "").strip.downcase
106
136
  end
107
137
 
108
- # Determines the parser (a Proc or other Object which responds to #call)
109
- # that will be passed the {#body} (and optional {#response}) to supply
110
- # {#parsed}.
138
+ # Determines the parser to be used for the response body
111
139
  #
112
- # The parser can be supplied as the +:parse+ option in the form of a Proc
113
- # (or other Object responding to #call) or a Symbol. In the latter case,
114
- # the actual parser will be looked up in {@@parsers} by the supplied Symbol.
140
+ # @note The parser can be supplied as the +:parse+ option in the form of a Proc
141
+ # (or other Object responding to #call) or a Symbol. In the latter case,
142
+ # the actual parser will be looked up in {@@parsers} by the supplied Symbol.
115
143
  #
116
- # If no +:parse+ option is supplied, the lookup Symbol will be determined
117
- # by looking up {#content_type} in {@@content_types}.
144
+ # @note If no +:parse+ option is supplied, the lookup Symbol will be determined
145
+ # by looking up {#content_type} in {@@content_types}.
118
146
  #
119
- # If {#parser} is a Proc, it will be called with no arguments, just
120
- # {#body}, or {#body} and {#response}, depending on the Proc's arity.
147
+ # @note If {#parser} is a Proc, it will be called with no arguments, just
148
+ # {#body}, or {#body} and {#response}, depending on the Proc's arity.
121
149
  #
122
- # @return [Proc, #call] If a parser was found.
123
- # @return [nil] If no parser was found.
150
+ # @return [Proc, #call] The parser proc or callable object
151
+ # @return [nil] If no suitable parser is found
124
152
  def parser
125
153
  return @parser if defined?(@parser)
126
154
 
@@ -136,12 +164,16 @@ module OAuth2
136
164
  end
137
165
  end
138
166
 
167
+ # Register XML parser
168
+ # @api private
139
169
  OAuth2::Response.register_parser(:xml, ["text/xml", "application/rss+xml", "application/rdf+xml", "application/atom+xml", "application/xml"]) do |body|
140
170
  next body unless body.respond_to?(:to_str)
141
171
 
142
172
  MultiXml.parse(body)
143
173
  end
144
174
 
175
+ # Register JSON parser
176
+ # @api private
145
177
  OAuth2::Response.register_parser(:json, ["application/json", "text/javascript", "application/hal+json", "application/vnd.collection+json", "application/vnd.api+json", "application/problem+json"]) do |body|
146
178
  next body unless body.respond_to?(:to_str)
147
179
 
@@ -95,7 +95,10 @@ module OAuth2
95
95
  def build_assertion(claims, encoding_opts)
96
96
  raise ArgumentError.new(message: "Please provide an encoding_opts hash with :algorithm and :key") if !encoding_opts.is_a?(Hash) || (%i[algorithm key] - encoding_opts.keys).any?
97
97
 
98
- JWT.encode(claims, encoding_opts[:key], encoding_opts[:algorithm])
98
+ headers = {}
99
+ headers[:kid] = encoding_opts[:kid] if encoding_opts.key?(:kid)
100
+
101
+ JWT.encode(claims, encoding_opts[:key], encoding_opts[:algorithm], headers)
99
102
  end
100
103
  end
101
104
  end
File without changes
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OAuth2
4
4
  module Version
5
- VERSION = "2.0.10"
5
+ VERSION = "2.0.12"
6
6
  end
7
7
  end
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.10
4
+ version: 2.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Boling
@@ -37,7 +37,7 @@ cert_chain:
37
37
  DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
38
38
  L9nRqA==
39
39
  -----END CERTIFICATE-----
40
- date: 2025-05-17 00:00:00.000000000 Z
40
+ date: 2025-05-31 00:00:00.000000000 Z
41
41
  dependencies:
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: faraday
@@ -134,6 +134,9 @@ dependencies:
134
134
  - - "~>"
135
135
  - !ruby/object:Gem::Version
136
136
  version: '2.0'
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 2.0.3
137
140
  type: :runtime
138
141
  prerelease: false
139
142
  version_requirements: !ruby/object:Gem::Requirement
@@ -141,6 +144,9 @@ dependencies:
141
144
  - - "~>"
142
145
  - !ruby/object:Gem::Version
143
146
  version: '2.0'
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: 2.0.3
144
150
  - !ruby/object:Gem::Dependency
145
151
  name: version_gem
146
152
  requirement: !ruby/object:Gem::Requirement
@@ -359,8 +365,7 @@ dependencies:
359
365
  version: '1.0'
360
366
  description: Ruby wrapper for the OAuth 2.0 protocol
361
367
  email:
362
- - peter.boling@gmail.com
363
- - oauth-ruby@googlegroups.com
368
+ - floss@galtzo.com
364
369
  executables: []
365
370
  extensions: []
366
371
  extra_rdoc_files:
@@ -395,39 +400,34 @@ homepage: https://github.com/oauth-xx/oauth2
395
400
  licenses:
396
401
  - MIT
397
402
  metadata:
398
- homepage_uri: https://gitlab.com/oauth-xx/oauth2
399
- source_code_uri: https://gitlab.com/oauth-xx/oauth2/-/tree/v2.0.10
400
- changelog_uri: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.10/CHANGELOG.md
403
+ homepage_uri: https://oauth2.galtzo.com/
404
+ source_code_uri: https://github.com/oauth-xx/oauth2/releases/tag//v2.0.12
405
+ changelog_uri: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.12/CHANGELOG.md
401
406
  bug_tracker_uri: https://gitlab.com/oauth-xx/oauth2/-/issues
402
- documentation_uri: https://www.rubydoc.info/gems/oauth2/2.0.10
407
+ documentation_uri: https://www.rubydoc.info/gems/oauth2/2.0.12
403
408
  wiki_uri: https://gitlab.com/oauth-xx/oauth2/-/wiki
404
409
  mailing_list_uri: https://groups.google.com/g/oauth-ruby
410
+ funding_uri: https://github.com/sponsors/pboling
405
411
  news_uri: https://www.railsbling.com/tags/oauth2
406
- funding_uri: https://liberapay.com/pboling
407
412
  rubygems_mfa_required: 'true'
408
413
  post_install_message: |2
409
414
 
410
- You have installed oauth2 version 2.0.10, congratulations!
415
+ ---+++ oauth2 v2.0.12 +++---
411
416
 
412
- There are BREAKING changes if you are upgrading from < v2, but most will not encounter them, and updating your code should be easy!
417
+ There are BREAKING CHANGES when upgrading from < v2
418
+ Most will not encounter them, and updating your code should be easy!
413
419
  Please see:
414
420
  • https://gitlab.com/oauth-xx/oauth2/-/blob/main/SECURITY.md
415
- • https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.10/CHANGELOG.md#200-2022-06-21-tag
421
+ • https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.12/CHANGELOG.md#200-2022-06-21-tag
416
422
  • Summary of most important breaking changes: https://gitlab.com/oauth-xx/oauth2#what-is-new-for-v20
417
423
 
418
- There are BUGFIXES in v2.0.10, which depending on how you relied on them instead of reporting and fixing them, may be BREAKING for you.
419
- For more information please see:
420
- https://railsbling.com/tags/oauth2
421
-
422
- Important News:
423
- 1. Google Group is "active" (again)!
424
- • https://groups.google.com/g/oauth-ruby/c/QA_dtrXWXaE
425
- 2. Non-commercial support for the 2.x series will end by April, 2026. Please make a plan to upgrade to the next version prior to that date.
424
+ News:
425
+ 1. New documentation website: https://oauth2.galtzo.com
426
+ 2. Discord for discussion and support: https://discord.gg/3qme4XHNKN
427
+ 3. Non-commercial support for the 2.x series will end by April, 2026. Please make a plan to upgrade to the next version prior to that date.
426
428
  Support will be dropped for Ruby 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1 and any other Ruby versions which will also have reached EOL by then.
427
- 3. Gem releases are now cryptographically signed with a 20-year cert, with checksums by stone_checksums.
428
- 4. I need your support.
429
-
430
- If you are sentient, please consider a donation as I move toward supporting myself with Open Source work:
429
+ 4. Gem releases are now cryptographically signed with a 20-year cert, with checksums by stone_checksums.
430
+ 5. Please consider supporting this project, and my other open source work, with one of the following methods:
431
431
  • https://liberapay.com/pboling
432
432
  • https://ko-fi.com/pboling
433
433
  • https://www.buymeacoffee.com/pboling
@@ -444,7 +444,12 @@ rdoc_options:
444
444
  - "--title"
445
445
  - oauth2 - OAuth 2.0 Core Ruby implementation
446
446
  - "--main"
447
+ - CHANGELOG.md
448
+ - CODE_OF_CONDUCT.md
449
+ - CONTRIBUTING.md
450
+ - LICENSE.txt
447
451
  - README.md
452
+ - SECURITY.md
448
453
  - "--line-numbers"
449
454
  - "--inline-source"
450
455
  - "--quiet"
metadata.gz.sig CHANGED
Binary file