oauth2 2.0.14 → 2.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CONTRIBUTING.md CHANGED
@@ -22,6 +22,35 @@ Follow these instructions:
22
22
  6. Make sure to add tests for it. This is important, so it doesn't break in a future release.
23
23
  7. Create new Pull Request.
24
24
 
25
+ ## Executables vs Rake tasks
26
+
27
+ Executables shipped by oauth2 can be used with or without generating the binstubs.
28
+ They will work when oauth2 is installed globally (i.e., `gem install oauth2`) and do not require that oauth2 be in your bundle.
29
+
30
+ - kettle-changelog
31
+ - kettle-commit-msg
32
+ - oauth2-setup
33
+ - kettle-dvcs
34
+ - kettle-pre-release
35
+ - kettle-readme-backers
36
+ - kettle-release
37
+
38
+ However, the rake tasks provided by oauth2 do require oauth2 to be added as a development dependency and loaded in your Rakefile.
39
+ See the full list of rake tasks in head of Rakefile
40
+
41
+ **Gemfile**
42
+ ```ruby
43
+ group :development do
44
+ gem "oauth2", require: false
45
+ end
46
+ ```
47
+
48
+ **Rakefile**
49
+ ```ruby
50
+ # Rakefile
51
+ require "oauth2"
52
+ ```
53
+
25
54
  ## Environment Variables for Local Development
26
55
 
27
56
  Below are the primary environment variables recognized by stone_checksums (and its integrated tools). Unless otherwise noted, set boolean values to the string "true" to enable.
@@ -89,9 +118,10 @@ bundle exec rake test
89
118
 
90
119
  ### Spec organization (required)
91
120
 
92
- - For each class or module under `lib/`, keep all of its unit tests in a single spec file under `spec/` that mirrors the path and file name (e.g., specs for `lib/oauth2/release_cli.rb` live in `spec/oauth2/release_cli_spec.rb`).
93
- - Do not create ad-hoc "_more" or split spec files for the same class/module. Consolidate all unit tests into the main spec file for that class/module.
94
- - Only integration scenarios that intentionally span multiple classes belong in `spec/integration/`.
121
+ - One spec file per class/module. For each class or module under `lib/`, keep all of its unit tests in a single spec file under `spec/` that mirrors the path and file name exactly: `lib/oauth2/release_cli.rb` -> `spec/oauth2/release_cli_spec.rb`.
122
+ - Never add a second spec file for the same class/module. Examples of disallowed names: `*_more_spec.rb`, `*_extra_spec.rb`, `*_status_spec.rb`, or any other suffix that still targets the same class. If you find yourself wanting a second file, merge those examples into the canonical spec file for that class/module.
123
+ - Exception: Integration specs that intentionally span multiple classes. Place these under `spec/integration/` (or a clearly named integration folder), and do not directly mirror a single class. Name them after the scenario, not a class.
124
+ - Migration note: If a duplicate spec file exists, move all examples into the canonical file and delete the duplicate. Do not leave stubs or empty files behind.
95
125
 
96
126
  ## Lint It
97
127
 
@@ -146,7 +176,9 @@ NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in th
146
176
 
147
177
  #### Automated process
148
178
 
149
- Run `bundle exec kettle-release`.
179
+ 1. Update version.rb to contian the correct version-to-be-released.
180
+ 2. Run `bundle exec kettle-changelog`.
181
+ 3. Run `bundle exec kettle-release`.
150
182
 
151
183
  #### Manual process
152
184
 
data/FUNDING.md CHANGED
@@ -18,11 +18,11 @@ Many paths lead to being a sponsor or a backer of this project. Are you on such
18
18
  [🖇sponsor]: https://github.com/sponsors/pboling
19
19
  [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
20
20
  [🖇polar]: https://polar.sh/pboling
21
- [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat
21
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
22
22
  [🖇kofi]: https://ko-fi.com/O5O86SNP4
23
23
  [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
24
24
  [🖇patreon]: https://patreon.com/galtzo
25
- [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat
25
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
26
26
  [🖇buyme]: https://www.buymeacoffee.com/pboling
27
27
  [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
28
28
  [🖇paypal]: https://www.paypal.com/paypalme/peterboling
data/README.md CHANGED
@@ -1,25 +1,25 @@
1
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]
2
2
 
3
- [🖼️oauth2-i]: https://logos.galtzo.com/assets/images/oauth/oauth2/avatar-192px.svg
4
- [🖼️oauth2]: https://github.com/ruby-oauth/oauth2
5
- [🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg
6
- [🖼️ruby-lang]: https://www.ruby-lang.org/
7
3
  [🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
8
4
  [🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN
5
+ [🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg
6
+ [🖼️ruby-lang]: https://www.ruby-lang.org/
7
+ [🖼️oauth2-i]: https://logos.galtzo.com/assets/images/oauth/oauth2/avatar-192px.svg
8
+ [🖼️oauth2]: https://github.com/ruby-oauth/oauth2
9
9
 
10
10
  # 🔐 OAuth 2.0 Authorization Framework
11
11
 
12
12
  ⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
13
13
 
14
- [![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] [![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] [![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 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]
14
+ [![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 Truffle Ruby][🚎9-t-wfi]][🚎9-t-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]
15
15
 
16
- If ☝️ `ci_badges.map(&:color).detect { it != "green"}` [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
16
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
17
17
 
18
18
  ---
19
19
 
20
- OTOH, if `ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
20
+ `if ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
21
21
 
22
- [![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 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]
22
+ [![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]
23
23
 
24
24
  ## 🌻 Synopsis
25
25
 
@@ -28,7 +28,7 @@ OAuth 2.0 focuses on client developer simplicity while providing specific author
28
28
  desktop applications, mobile phones, and living room devices.
29
29
  This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications.
30
30
 
31
- ### Quick Example
31
+ ### Quick Examples
32
32
 
33
33
  <details>
34
34
  <summary>Convert the following `curl` command into a token request using this gem...</summary>
@@ -61,6 +61,61 @@ NOTE: `header` - The content type specified in the `curl` is already the default
61
61
 
62
62
  </details>
63
63
 
64
+ <details>
65
+ <summary>Complete E2E single file script against [navikt/mock-oauth2-server](https://github.com/navikt/mock-oauth2-server)</summary>
66
+
67
+ - E2E example using the mock test server added in v2.0.11
68
+
69
+ ```console
70
+ docker compose -f docker-compose-ssl.yml up -d --wait
71
+ ruby examples/e2e.rb
72
+ # If your machine is slow or Docker pulls are cold, increase the wait:
73
+ E2E_WAIT_TIMEOUT=120 ruby examples/e2e.rb
74
+ # The mock server serves HTTP on 8080; the example points to http://localhost:8080 by default.
75
+ ```
76
+
77
+ The output should be something like this:
78
+
79
+ ```console
80
+ ➜ ruby examples/e2e.rb
81
+ Access token (truncated): eyJraWQiOiJkZWZhdWx0...
82
+ userinfo status: 200
83
+ userinfo body: {"sub" => "demo-sub", "aud" => ["demo-aud"], "nbf" => 1757816758000, "iss" => "http://localhost:8080/default", "exp" => 1757820358000, "iat" => 1757816758000, "jti" => "d63b97a7-ebe5-4dea-93e6-d542caba6104"}
84
+ E2E complete
85
+ ```
86
+
87
+ Make sure to shut down the mock server when you are done:
88
+
89
+ ```console
90
+ docker compose -f docker-compose-ssl.yml down
91
+ ```
92
+
93
+ Troubleshooting: validate connectivity to the mock server
94
+
95
+ - Check container status and port mapping:
96
+ - docker compose -f docker-compose-ssl.yml ps
97
+ - From the host, try the discovery URL directly (this is what the example uses by default):
98
+ - curl -v http://localhost:8080/default/.well-known/openid-configuration
99
+ - If that fails immediately, also try: curl -v --connect-timeout 2 http://127.0.0.1:8080/default/.well-known/openid-configuration
100
+ - From inside the container (to distinguish container vs host networking):
101
+ - docker exec -it oauth2-mock-oauth2-server-1 curl -v http://127.0.0.1:8080/default/.well-known/openid-configuration
102
+ - Simple TCP probe from the host:
103
+ - nc -vz localhost 8080 # or: ruby -rsocket -e 'TCPSocket.new("localhost",8080).close; puts "tcp ok"'
104
+ - Inspect which host port 8080 is bound to (should be 8080):
105
+ - docker inspect -f '{{ (index (index .NetworkSettings.Ports "8080/tcp") 0).HostPort }}' oauth2-mock-oauth2-server-1
106
+ - Look at server logs for readiness/errors:
107
+ - docker logs -n 200 oauth2-mock-oauth2-server-1
108
+ - On Linux, ensure nothing else is bound to 8080 and that firewall/SELinux aren’t blocking:
109
+ - ss -ltnp | grep :8080
110
+
111
+ Notes
112
+ - Discovery URL pattern is: http://localhost:8080/<realm>/.well-known/openid-configuration, where <realm> defaults to "default".
113
+ - You can change these with env vars when running the example:
114
+ - E2E_ISSUER_BASE (default: http://localhost:8080)
115
+ - E2E_REALM (default: default)
116
+
117
+ </details>
118
+
64
119
  If it seems like you are in the wrong place, you might try one of these:
65
120
 
66
121
  * [OAuth 2.0 Spec][oauth2-spec]
@@ -73,27 +128,29 @@ If it seems like you are in the wrong place, you might try one of these:
73
128
 
74
129
  ## 💡 Info you can shake a stick at
75
130
 
76
- | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
77
- |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
78
- | Works with JRuby | ![JRuby 9.1 Compat][💎jruby-9.1i] ![JRuby 9.2 Compat][💎jruby-9.2i] ![JRuby 9.3 Compat][💎jruby-9.3i] <br/> [![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] |
79
- | Works with Truffle Ruby | ![Truffle Ruby 22.3 Compat][💎truby-22.3i] ![Truffle Ruby 23.0 Compat][💎truby-23.0i] <br/> [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] |
80
- | 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] |
81
- | Works with MRI Ruby 2 | ![Ruby 2.2 Compat][💎ruby-2.2i] <br/> [![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] |
82
- | 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] |
83
- | Documentation | [![Discussion][⛳gg-discussions-img]][⛳gg-discussions] [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![Wiki][📜wiki-img]][📜wiki] |
84
- | 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] |
85
- | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
86
- | Support | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
87
- | Maintainer 🎖️ | [![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 Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
88
- | `...` 💖 | [![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] |
131
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
132
+ |-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
133
+ | Works with JRuby | ![JRuby 9.1 Compat][💎jruby-9.1i] ![JRuby 9.2 Compat][💎jruby-9.2i] ![JRuby 9.3 Compat][💎jruby-9.3i] <br/> [![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] |
134
+ | Works with Truffle Ruby | ![Truffle Ruby 22.3 Compat][💎truby-22.3i] ![Truffle Ruby 23.0 Compat][💎truby-23.0i] <br/> [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] |
135
+ | 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] |
136
+ | Works with MRI Ruby 2 | ![Ruby 2.2 Compat][💎ruby-2.2i] <br/> [![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] |
137
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Discussion][⛳gg-discussions-img]][⛳gg-discussions] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
138
+ | 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] |
139
+ | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![Wiki][📜wiki-img]][📜wiki] |
140
+ | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![Compatible with Apache Software Projects: Verified by SkyWalking Eyes][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
141
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
142
+ | Maintainer 🎖️ | [![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 Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
143
+ | `...` 💖 | [![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] |
89
144
 
90
145
  ### Compatibility
91
146
 
92
147
  * Operating Systems: Linux, MacOS, Windows
93
148
  * MRI Ruby @ v2.3, v2.4, v2.5, v2.6, v2.7, v3.0, v3.1, v3.2, v3.3, v3.4, HEAD
94
- * NOTE: This gem will still install on ruby v2.2, but vanilla GitHub Actions no longer supports testing against it, so YMMV.
95
- * JRuby @ v9.2, v9.3, v9.4, v10.0, HEAD
149
+ * NOTE: This gem may still _install_ and _run_ on ruby v2.2, but vanilla GitHub Actions no longer supports testing against it, so YMMV. Accept patches so long as they don't break the platforms that do run in CI.
150
+ * JRuby @ v9.4, v10.0, HEAD
151
+ * NOTE: This gem may still _install_ and _run_ on JRuby v9.2 and v9.3, but they are EOL, builds are flaky, and GitHub Actions [doesn't have][GHA-continue-on-error-ui] a proper [`allow-failures` feature][GHA-allow-failure], and until they do flaky EOL-platform builds get dropped, so YMMV. Accept patches so long as they don't break the platforms that do run in CI.
96
152
  * TruffleRuby @ v23.1, v24.1, HEAD
153
+ * NOTE: This gem may still _install_ and _run_ on Truffleruby v22.3 and v23.0, but they are EOL, builds are flaky, and GitHub Actions [doesn't have][GHA-continue-on-error-ui] a proper [`allow-failures` feature][GHA-allow-failure], and until they do flaky EOL-platform builds get dropped, so YMMV. Accept patches so long as they don't break the platforms that do run in CI.
97
154
  * gem `faraday` @ v0, v1, v2, HEAD ⏩️ [lostisland/faraday](https://github.com/lostisland/faraday)
98
155
  * gem `jwt` @ v1, v2, v3, HEAD ⏩️ [jwt/ruby-jwt](https://github.com/jwt/ruby-jwt)
99
156
  * gem `logger` @ v1.2, v1.5, v1.7, HEAD ⏩️ [ruby/logger](https://github.com/ruby/logger)
@@ -109,6 +166,9 @@ Also, where reasonable, tested against the runtime dependencies of those depende
109
166
 
110
167
  * gem `hashie` @ v0, v1, v2, v3, v4, v5, HEAD ⏩️ [hashie/hashie](https://github.com/hashie/hashie)
111
168
 
169
+ [GHA-continue-on-error-ui]: https://github.com/actions/runner/issues/2347#issuecomment-2653479732
170
+ [GHA-allow-failure]: https://github.com/orgs/community/discussions/15452
171
+
112
172
  #### Upgrading Runtime Gem Dependencies
113
173
 
114
174
  This project sits underneath a large portion of the authorization systems on the internet.
@@ -123,12 +183,12 @@ leading versions per each minor version of Ruby of all the runtime dependencies
123
183
 
124
184
  What does that mean specifically for the runtime dependencies?
125
185
 
126
- We have 100% test coverage of lines and branches, and this test suite runs across a large matrix
127
- covering the latest patch for each of the following minor versions:
186
+ We have 100% test coverage of lines and branches, and this test suite runs across a very large matrix.
187
+ It wouldn't be possible without appraisal2.
128
188
 
129
- | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 |
130
- |------------------------------------------------|--------------------------------------------------------------------------------------|
131
- | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2](https://github.com/appraisal-rb/appraisal2) ✨ |
189
+ | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
190
+ |------------------------------------------------|--------------------------------------------------------|
191
+ | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
132
192
 
133
193
  #### You should upgrade this gem with confidence\*.
134
194
 
@@ -138,7 +198,7 @@ covering the latest patch for each of the following minor versions:
138
198
  - You should upgrade the dependencies of this gem with confidence\*.
139
199
  - Please do upgrade, and then, when it goes smooth as butter [please sponsor me][🖇sponsor]. Thanks!
140
200
 
141
- [sv-pub-api]: #-is-platform-support-part-of-the-public-api
201
+ [sv-pub-api]: #-versioning
142
202
 
143
203
  \* MIT license; The only guarantees I make are for [enterprise support](#enterprise-support).
144
204
 
@@ -160,7 +220,7 @@ If you use a gem version of a core Ruby library it should work fine!
160
220
  ### Federated DVCS
161
221
 
162
222
  <details>
163
- <summary>Find this repo on other forges (Coming soon!)</summary>
223
+ <summary>Find this repo on other forges</summary>
164
224
 
165
225
  | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
166
226
  |-----------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
@@ -206,6 +266,10 @@ Alternatively:
206
266
 
207
267
  | Version | Release Date | CHANGELOG | README |
208
268
  |---------|--------------|---------------------------------------|---------------------------------|
269
+ | 2.0.17 | 2025-09-15 | [v2.0.17 CHANGELOG][2.0.17-changelog] | [v2.0.17 README][2.0.17-readme] |
270
+ | 2.0.16 | 2025-09-14 | [v2.0.16 CHANGELOG][2.0.16-changelog] | [v2.0.16 README][2.0.16-readme] |
271
+ | 2.0.15 | 2025-09-08 | [v2.0.15 CHANGELOG][2.0.15-changelog] | [v2.0.15 README][2.0.15-readme] |
272
+ | 2.0.14 | 2025-08-31 | [v2.0.14 CHANGELOG][2.0.14-changelog] | [v2.0.14 README][2.0.14-readme] |
209
273
  | 2.0.13 | 2025-08-30 | [v2.0.13 CHANGELOG][2.0.13-changelog] | [v2.0.13 README][2.0.13-readme] |
210
274
  | 2.0.12 | 2025-05-31 | [v2.0.12 CHANGELOG][2.0.12-changelog] | [v2.0.12 README][2.0.12-readme] |
211
275
  | 2.0.11 | 2025-05-23 | [v2.0.11 CHANGELOG][2.0.11-changelog] | [v2.0.11 README][2.0.11-readme] |
@@ -223,6 +287,10 @@ Alternatively:
223
287
 
224
288
  </details>
225
289
 
290
+ [2.0.17-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2017---2025-09-15
291
+ [2.0.16-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2016---2025-09-14
292
+ [2.0.15-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2015---2025-09-08
293
+ [2.0.14-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2014---2025-08-31
226
294
  [2.0.13-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2013---2025-08-30
227
295
  [2.0.12-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2012---2025-05-31
228
296
  [2.0.11-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2011---2025-05-23
@@ -238,6 +306,10 @@ Alternatively:
238
306
  [2.0.1-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#201---2022-06-22
239
307
  [2.0.0-changelog]: https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#200---2022-06-21
240
308
 
309
+ [2.0.17-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.17/README.md
310
+ [2.0.16-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.16/README.md
311
+ [2.0.15-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.15/README.md
312
+ [2.0.14-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.14/README.md
241
313
  [2.0.13-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.13/README.md
242
314
  [2.0.12-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.12/README.md
243
315
  [2.0.11-readme]: https://gitlab.com/ruby-oauth/oauth2/-/blob/v2.0.11/README.md
@@ -678,6 +750,18 @@ using various class methods including the standard new, `from_hash` (if you have
678
750
  a hash of the values), or `from_kvform` (if you have an
679
751
  `application/x-www-form-urlencoded` encoded string of the values).
680
752
 
753
+ Options (since v2.0.x unless noted):
754
+ - expires_latency (Integer | nil): Seconds to subtract from expires_in when computing #expired? to offset latency.
755
+ - token_name (String | Symbol | nil): When multiple token-like fields exist in responses, select the field name to use as the access token (since v2.0.10).
756
+ - mode (Symbol | Proc | Hash): Controls how the token is transmitted on requests made via this AccessToken instance.
757
+ - :header — Send as Authorization: Bearer <token> header (default and preferred by OAuth 2.1 draft guidance).
758
+ - :query — Send as access_token query parameter (discouraged in general, but required by some providers).
759
+ - Verb-dependent (since v2.0.15): Provide either:
760
+ - a Proc taking |verb| and returning :header or :query, or
761
+ - a Hash with verb symbols as keys, for example: {get: :query, post: :header, delete: :header}.
762
+
763
+ Note: Verb-dependent mode was added in v2.0.15 to support providers like Instagram that require query mode for GET and header mode for POST/DELETE.
764
+
681
765
  ### OAuth2::Error
682
766
 
683
767
  On 400+ status code responses, an `OAuth2::Error` will be raised. If it is a
@@ -847,6 +931,76 @@ Notes:
847
931
 
848
932
  </details>
849
933
 
934
+ ### Instagram API (verb‑dependent token mode)
935
+
936
+ Providers like Instagram require the access token to be sent differently depending on the HTTP verb:
937
+ - GET requests: token must be in the query string (?access_token=...)
938
+ - POST/DELETE requests: token must be in the Authorization header (Bearer ...)
939
+
940
+ 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.
941
+
942
+ Example: exchanging and refreshing long‑lived Instagram tokens, and making API calls
943
+
944
+ ```ruby
945
+ require "oauth2"
946
+
947
+ # NOTE: Users authenticate via Facebook Login to obtain a short‑lived user token (not shown here).
948
+ # See Facebook Login docs for obtaining the initial short‑lived token.
949
+
950
+ client = OAuth2::Client.new(nil, nil, site: "https://graph.instagram.com")
951
+
952
+ # Start with a short‑lived token you already obtained via Facebook Login
953
+ short_lived = OAuth2::AccessToken.new(
954
+ client,
955
+ ENV["IG_SHORT_LIVED_TOKEN"],
956
+ # Key part: verb‑dependent mode
957
+ mode: {get: :query, post: :header, delete: :header},
958
+ )
959
+
960
+ # 1) Exchange for a long‑lived token (Instagram requires GET with access_token in query)
961
+ # Endpoint: GET https://graph.instagram.com/access_token
962
+ # Params: grant_type=ig_exchange_token, client_secret=APP_SECRET
963
+ exchange = short_lived.get(
964
+ "/access_token",
965
+ params: {
966
+ grant_type: "ig_exchange_token",
967
+ client_secret: ENV["IG_APP_SECRET"],
968
+ # access_token param will be added automatically by the AccessToken (mode => :query for GET)
969
+ },
970
+ )
971
+ long_lived_token_value = exchange.parsed["access_token"]
972
+
973
+ long_lived = OAuth2::AccessToken.new(
974
+ client,
975
+ long_lived_token_value,
976
+ mode: {get: :query, post: :header, delete: :header},
977
+ )
978
+
979
+ # 2) Refresh the long‑lived token (Instagram uses GET with token in query)
980
+ # Endpoint: GET https://graph.instagram.com/refresh_access_token
981
+ refresh_resp = long_lived.get(
982
+ "/refresh_access_token",
983
+ params: {grant_type: "ig_refresh_token"},
984
+ )
985
+ long_lived = OAuth2::AccessToken.new(
986
+ client,
987
+ refresh_resp.parsed["access_token"],
988
+ mode: {get: :query, post: :header, delete: :header},
989
+ )
990
+
991
+ # 3) Typical API GET request (token in query automatically)
992
+ me = long_lived.get("/me", params: {fields: "id,username"}).parsed
993
+
994
+ # 4) Example POST (token sent via Bearer header automatically)
995
+ # Note: Replace the path/params with a real Instagram Graph API POST you need,
996
+ # such as publishing media via the Graph API endpoints.
997
+ # long_lived.post("/me/media", body: {image_url: "https://...", caption: "hello"})
998
+ ```
999
+
1000
+ Tips:
1001
+ - Avoid query‑string bearer tokens unless required by your provider. Instagram explicitly requires it for GET.
1002
+ - If you need a custom rule, you can pass a Proc for mode, e.g. mode: ->(verb) { verb == :get ? :query : :header }.
1003
+
850
1004
  ### Refresh Tokens
851
1005
 
852
1006
  When the server issues a refresh_token, you can refresh manually or implement an auto-refresh wrapper.
@@ -1175,6 +1329,8 @@ See [CONTRIBUTING.md][🤝contributing].
1175
1329
 
1176
1330
  ### Code Coverage
1177
1331
 
1332
+ [![Coverage Graph][🔑codecov-g]][🔑codecov]
1333
+
1178
1334
  [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls]
1179
1335
 
1180
1336
  [![QLTY Test Coverage][🔑qlty-covi]][🔑qlty-cov]
@@ -1279,7 +1435,7 @@ To join the community or get help 👇️ Join the Discord.
1279
1435
 
1280
1436
  [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
1281
1437
 
1282
- To say "thanks for maintaining such a great tool" ☝️ Join the Discord or 👇️ send money.
1438
+ To say "thanks!" ☝️ Join the Discord or 👇️ send money.
1283
1439
 
1284
1440
  [![Sponsor ruby-oauth/oauth2 on Open Source Collective][🖇osc-all-bottom-img]][🖇osc] 💌 [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay-img] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal-img]
1285
1441
 
@@ -1306,11 +1462,11 @@ Thanks for RTFM. ☺️
1306
1462
  [🖇sponsor]: https://github.com/sponsors/pboling
1307
1463
  [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
1308
1464
  [🖇polar]: https://polar.sh/pboling
1309
- [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat
1465
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
1310
1466
  [🖇kofi]: https://ko-fi.com/O5O86SNP4
1311
1467
  [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
1312
1468
  [🖇patreon]: https://patreon.com/galtzo
1313
- [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat
1469
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
1314
1470
  [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff
1315
1471
  [🖇buyme]: https://www.buymeacoffee.com/pboling
1316
1472
  [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
@@ -1319,7 +1475,9 @@ Thanks for RTFM. ☺️
1319
1475
  [🖇floss-funding.dev]: https://floss-funding.dev
1320
1476
  [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
1321
1477
  [✉️discord-invite]: https://discord.gg/3qme4XHNKN
1322
- [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge
1478
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
1479
+ [✉️ruby-friends-img]: https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white
1480
+ [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
1323
1481
 
1324
1482
  [⛳gg-discussions]: https://groups.google.com/g/oauth-ruby
1325
1483
  [⛳gg-discussions-img]: https://img.shields.io/badge/google-group-0093D0.svg?style=for-the-badge&logo=google&logoColor=orange
@@ -1342,7 +1500,7 @@ Thanks for RTFM. ☺️
1342
1500
  [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
1343
1501
  [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
1344
1502
  [💖🐘ruby-mast]: https://ruby.social/@galtzo
1345
- [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=flat&logo=mastodon&label=Ruby%20%40galtzo
1503
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
1346
1504
  [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
1347
1505
  [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
1348
1506
  [💖🌳linktree]: https://linktr.ee/galtzo
@@ -1412,14 +1570,16 @@ Thanks for RTFM. ☺️
1412
1570
  [🚎10-j-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/jruby.yml/badge.svg
1413
1571
  [🚎11-c-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/current.yml
1414
1572
  [🚎11-c-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/current.yml/badge.svg
1415
- [🚎12-crh-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/current-runtime-heads.yml
1416
- [🚎12-crh-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/current-runtime-heads.yml/badge.svg
1573
+ [🚎12-crh-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/dep-heads.yml
1574
+ [🚎12-crh-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/dep-heads.yml/badge.svg
1417
1575
  [🚎13-cbs-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/caboose.yml
1418
1576
  [🚎13-cbs-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/caboose.yml/badge.svg
1419
1577
  [🚎13-🔒️-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/locked_deps.yml
1420
1578
  [🚎13-🔒️-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/locked_deps.yml/badge.svg
1421
1579
  [🚎14-🔓️-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/unlocked_deps.yml
1422
1580
  [🚎14-🔓️-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/unlocked_deps.yml/badge.svg
1581
+ [🚎15-🪪-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/license-eye.yml
1582
+ [🚎15-🪪-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/license-eye.yml/badge.svg
1423
1583
  [💎ruby-2.2i]: https://img.shields.io/badge/Ruby-2.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white
1424
1584
  [💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
1425
1585
  [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
@@ -1467,15 +1627,17 @@ Thanks for RTFM. ☺️
1467
1627
  [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
1468
1628
  [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
1469
1629
  [📌gitmoji]:https://gitmoji.dev
1470
- [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square
1630
+ [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1471
1631
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1472
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.519-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1632
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.526-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1473
1633
  [🔐security]: SECURITY.md
1474
1634
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1475
1635
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
1476
1636
  [📄license]: LICENSE.txt
1477
1637
  [📄license-ref]: https://opensource.org/licenses/MIT
1478
1638
  [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg
1639
+ [📄license-compat]: https://dev.to/galtzo/how-to-check-license-compatibility-41h0
1640
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Compatible:_Category_A-%E2%9C%93-259D6C.svg?style=flat&logo=Apache
1479
1641
  [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
1480
1642
  [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
1481
1643
  [🚎yard-current]: http://rubydoc.info/gems/oauth2
@@ -1483,7 +1645,7 @@ Thanks for RTFM. ☺️
1483
1645
  [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
1484
1646
  [💎SHA_checksums]: https://gitlab.com/ruby-oauth/oauth2/-/tree/main/checksums
1485
1647
  [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
1486
- [💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
1648
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
1487
1649
  [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
1488
1650
  [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
1489
1651
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
@@ -1493,8 +1655,8 @@ Thanks for RTFM. ☺️
1493
1655
  rel="me" Social Proofs
1494
1656
  </summary>
1495
1657
 
1496
- <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>
1497
- <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>
1658
+ <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://ruby.social&style=social&label=Follow%20@galtzo%20on%20Ruby.social"></a>
1659
+ <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://floss.social&style=social&label=Follow%20@galtzo%20on%20Floss.social"></a>
1498
1660
 
1499
1661
  </details>
1500
1662
 
data/SECURITY.md CHANGED
@@ -2,15 +2,9 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported | Post-EOL / Enterprise |
6
- |----------|-----------|---------------------------------------|
7
- | 2.latest | ✅ | [Tidelift Subscription][tidelift-ref] |
8
- | 1.latest | ✅ | [Tidelift Subscription][tidelift-ref] |
9
- | <= 1 | ⛔ | ⛔ |
10
-
11
- ### EOL Policy
12
-
13
- Non-commercial support for the oldest version of Ruby (which itself is going EOL) will be dropped each year in April.
5
+ | Version | Supported |
6
+ |----------|-----------|
7
+ | 1.latest | ✅ |
14
8
 
15
9
  ## Security contact information
16
10
 
@@ -25,11 +19,3 @@ please consider sponsoring the project / maintainer @ https://liberapay.com/pbol
25
19
  or find other sponsorship links in the [README].
26
20
 
27
21
  [README]: README.md
28
-
29
- ## Enterprise Support
30
-
31
- Available as part of the Tidelift Subscription.
32
-
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]
34
-
35
- [tidelift-ref]: https://tidelift.com/subscription/pkg/rubygems-oauth2?utm_source=rubygems-oauth2&utm_medium=referral&utm_campaign=enterprise&utm_term=repo
@@ -132,9 +132,15 @@ You may need to set `snaky: false`. See inline documentation for more info.
132
132
  # @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire
133
133
  # @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire
134
134
  # @option opts [FixNum, String] :expires_latency (nil) the number of seconds by which AccessToken validity will be reduced to offset latency, @version 2.0+
135
- # @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value
136
- # one of :header, :body or :query
135
+ # @option opts [Symbol, Hash, or callable] :mode (:header) the transmission mode of the Access Token parameter value:
136
+ # either one of :header, :body or :query; or a Hash with verb symbols as keys mapping to one of these symbols
137
+ # (e.g., {get: :query, post: :header, delete: :header}); or a callable that accepts a request-verb parameter
138
+ # and returns one of these three symbols.
137
139
  # @option opts [String] :header_format ('Bearer %s') the string format to use for the Authorization header
140
+ #
141
+ # @example Verb-dependent Hash mode
142
+ # # Send token in query for GET, in header for POST/DELETE, in body for PUT/PATCH
143
+ # OAuth2::AccessToken.new(client, token, mode: {get: :query, post: :header, delete: :header, put: :body, patch: :body})
138
144
  # @option opts [String] :param_name ('access_token') the parameter name to use for transmission of the
139
145
  # Access Token value in :body or :query transmission mode
140
146
  # @option opts [String] :token_name (nil) the name of the response parameter that identifies the access token
@@ -324,7 +330,7 @@ You may need to set `snaky: false`. See inline documentation for more info.
324
330
  #
325
331
  # @see OAuth2::Client#request
326
332
  def request(verb, path, opts = {}, &block)
327
- configure_authentication!(opts)
333
+ configure_authentication!(opts, verb)
328
334
  @client.request(verb, path, opts, &block)
329
335
  end
330
336
 
@@ -370,8 +376,20 @@ You may need to set `snaky: false`. See inline documentation for more info.
370
376
 
371
377
  private
372
378
 
373
- def configure_authentication!(opts)
374
- case options[:mode]
379
+ def configure_authentication!(opts, verb)
380
+ mode_opt = options[:mode]
381
+ mode =
382
+ if mode_opt.respond_to?(:call)
383
+ mode_opt.call(verb)
384
+ elsif mode_opt.is_a?(Hash)
385
+ key = verb.to_sym
386
+ # Try symbol key first, then string key; default to :header when missing
387
+ mode_opt[key] || mode_opt[key.to_s] || :header
388
+ else
389
+ mode_opt
390
+ end
391
+
392
+ case mode
375
393
  when :header
376
394
  opts[:headers] ||= {}
377
395
  opts[:headers].merge!(headers)
@@ -389,7 +407,7 @@ You may need to set `snaky: false`. See inline documentation for more info.
389
407
  end
390
408
  # @todo support for multi-part (file uploads)
391
409
  else
392
- raise("invalid :mode option of #{options[:mode]}")
410
+ raise("invalid :mode option of #{mode}")
393
411
  end
394
412
  end
395
413
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OAuth2
4
4
  module Version
5
- VERSION = "2.0.14"
5
+ VERSION = "2.0.17"
6
6
  end
7
7
  end