oauth2 2.0.11 → 2.0.13

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/README.md CHANGED
@@ -1,39 +1,72 @@
1
- <p align="center">
2
- <a href="http://oauth.net/2/" target="_blank" rel="noopener">
3
- <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
- </a>
5
- <a href="https://www.ruby-lang.org/" target="_blank" rel="noopener">
6
- <img width="124px" src="https://github.com/oauth-xx/oauth2/raw/main/docs/images/logo/ruby-logo-198px.svg?raw=true" alt="Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5">
7
- </a>
8
- </p>
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]
9
2
 
10
- ## 🔐 OAuth2
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
+ [🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
8
+ [🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN
11
9
 
12
- [![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]
10
+ # 🔐 OAuth 2.0 Authorization Framework
11
+
12
+ ⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
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]
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].
13
17
 
14
18
  ---
15
19
 
16
- [![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]
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.
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]
23
+
24
+ ## 🌻 Synopsis
17
25
 
18
26
  OAuth 2.0 is the industry-standard protocol for authorization.
19
27
  OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications,
20
28
  desktop applications, mobile phones, and living room devices.
21
29
  This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications.
22
30
 
23
- | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
24
- |-----------------------------------------------|-------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
25
- | 🧪 [oauth-xx/oauth2 on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ |
26
- | 🧊 [oauth-xx/oauth2 on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | ➖ | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
27
- | 🐙 [oauth-xx/oauth2 on GitHub][📜src-gh] | A Dirty Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | ➖ |
28
- | 🤼 [OAuth Ruby Google Group][⛳gg-discussions] | "Active" | ➖ | ➖ | ➖ | ➖ | [💚][⛳gg-discussions] |
29
- | 🎮️ [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] |
31
+ ### Quick Example
32
+
33
+ <details>
34
+ <summary>Convert the following `curl` command into a token request using this gem...</summary>
35
+
36
+ ```shell
37
+ curl --request POST \
38
+ --url 'https://login.microsoftonline.com/REDMOND_REDACTED/oauth2/token' \
39
+ --header 'content-type: application/x-www-form-urlencoded' \
40
+ --data grant_type=client_credentials \
41
+ --data client_id=REDMOND_CLIENT_ID \
42
+ --data client_secret=REDMOND_CLIENT_SECRET \
43
+ --data resource=REDMOND_RESOURCE_UUID
44
+ ```
45
+
46
+ NOTE: In the ruby version below, certain params are passed to the `get_token` call, instead of the client creation.
47
+
48
+ ```ruby
49
+ OAuth2::Client.new(
50
+ "REDMOND_CLIENT_ID", # client_id
51
+ "REDMOND_CLIENT_SECRET", # client_secret
52
+ auth_scheme: :request_body, # Other modes are supported: :basic_auth, :tls_client_auth, :private_key_jwt
53
+ token_url: "oauth2/token", # relative path, except with leading `/`, then absolute path
54
+ site: "https://login.microsoftonline.com/REDMOND_REDACTED",
55
+ ). # The base path for token_url when it is relative
56
+ client_credentials. # There are many other types to choose from!
57
+ get_token(resource: "REDMOND_RESOURCE_UUID")
58
+ ```
59
+
60
+ NOTE: `header` - The content type specified in the `curl` is already the default!
61
+
62
+ </details>
30
63
 
31
64
  ### Upgrading Runtime Gem Dependencies
32
65
 
33
66
  This project sits underneath a large portion of the authorization systems on the internet.
34
67
  According to GitHub's project tracking, which I believe only reports on public projects,
35
- [100,000+ projects](https://github.com/oauth-xx/oauth2/network/dependents), and
36
- [500+ packages](https://github.com/oauth-xx/oauth2/network/dependents?dependent_type=PACKAGE) depend on this project.
68
+ [100,000+ projects](https://github.com/ruby-oauth/oauth2/network/dependents), and
69
+ [500+ packages](https://github.com/ruby-oauth/oauth2/network/dependents?dependent_type=PACKAGE) depend on this project.
37
70
 
38
71
  That means it is painful for the Ruby community when this gem forces updates to its runtime dependencies.
39
72
 
@@ -45,19 +78,24 @@ What does that mean specifically for the runtime dependencies?
45
78
  We have 100% test coverage of lines and branches, and this test suite runs across a large matrix
46
79
  covering the latest patch for each of the following minor versions:
47
80
 
81
+ | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 |
82
+ |------------------------------------------------|--------------------------------------------------------------------------------------|
83
+ | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2](https://github.com/appraisal-rb/appraisal2) ✨ |
84
+
85
+ * Operating Systems: Linux, MacOS, Windows
48
86
  * MRI Ruby @ v2.3, v2.4, v2.5, v2.6, v2.7, v3.0, v3.1, v3.2, v3.3, v3.4, HEAD
49
87
  * NOTE: This gem will still install on ruby v2.2, but vanilla GitHub Actions no longer supports testing against it, so YMMV.
50
88
  * JRuby @ v9.2, v9.3, v9.4, v10.0, HEAD
51
- * TruffleRuby @ v23.1, v23.2, HEAD
89
+ * TruffleRuby @ v23.1, v24.1, HEAD
52
90
  * gem `faraday` @ v0, v1, v2, HEAD ⏩️ [lostisland/faraday](https://github.com/lostisland/faraday)
53
- * gem `jwt` @ v1, v2, v3, HEAD ⏩️ [lostisland/faraday](https://github.com/lostisland/faraday)
54
- * gem `logger` @ v1.2, v1.5, v1.7, HEAD ⏩️ [jwt/ruby-jwt](https://github.com/jwt/ruby-jwt)
91
+ * gem `jwt` @ v1, v2, v3, HEAD ⏩️ [jwt/ruby-jwt](https://github.com/jwt/ruby-jwt)
92
+ * gem `logger` @ v1.2, v1.5, v1.7, HEAD ⏩️ [ruby/logger](https://github.com/ruby/logger)
55
93
  * gem `multi_xml` @ v0.5, v0.6, v0.7, HEAD ⏩️ [sferik/multi_xml](https://github.com/sferik/multi_xml)
56
94
  * gem `rack` @ v1.2, v1.6, v2, v3, HEAD ⏩️ [rack/rack](https://github.com/rack/rack)
57
- * gem `snaky_hash` @v2, HEAD ⏩️ [oauth-xx/snaky_hash](https://gitlab.com/oauth-xx/snaky_hash)
58
- * gem `version_gem` - @v1, HEAD ⏩️ [oauth-xx/version_gem](https://gitlab.com/oauth-xx/version_gem)
95
+ * gem `snaky_hash` @ v2, HEAD ⏩️ [ruby-oauth/snaky_hash](https://gitlab.com/ruby-oauth/snaky_hash)
96
+ * gem `version_gem` @ v1, HEAD ⏩️ [ruby-oauth/version_gem](https://gitlab.com/ruby-oauth/version_gem)
59
97
 
60
- The last two were extracted from this gem. They are part of the `oauth-xx` org,
98
+ The last two were extracted from this gem. They are part of the `ruby-oauth` org,
61
99
  and are developed in tight collaboration with this gem.
62
100
 
63
101
  Also, where reasonable, tested against the runtime dependencies of those dependencies:
@@ -74,13 +112,7 @@ Also, where reasonable, tested against the runtime dependencies of those depende
74
112
 
75
113
  [sv-pub-api]: #-is-platform-support-part-of-the-public-api
76
114
 
77
- \* MIT license; I am unable to make guarantees.
78
-
79
- | 🚚 Test matrix brought to you by | 🔎 appraisal++ |
80
- |----------------------------------|-------------------------------------------------------------------------|
81
- | Adds back support for old Rubies | ✨ [appraisal PR #250](https://github.com/thoughtbot/appraisal/pull/250) |
82
- | Adds support for `eval_gemfile` | ✨ [appraisal PR #248](https://github.com/thoughtbot/appraisal/pull/248) |
83
- | Please review | my PRs! |
115
+ \* MIT license; The only guarantees I make are for [enterprise support](#enterprise-support).
84
116
 
85
117
  <details>
86
118
  <summary>Standard Library Dependencies</summary>
@@ -93,209 +125,112 @@ The various versions of each are tested via the Ruby test matrix, along with wha
93
125
  * time
94
126
  * logger (removed from stdlib in Ruby 3.5 so added as runtime dependency in v2.0.10)
95
127
 
96
- If you use a gem version it should work fine!
128
+ If you use a gem version of a core Ruby library it should work fine!
97
129
 
98
130
  </details>
99
131
 
100
- ### Quick Usage Example for AI and Copy / Pasting
101
-
102
- Convert the following `curl` command into a token request using this gem...
103
-
104
- ```shell
105
- curl --request POST \
106
- --url 'https://login.microsoftonline.com/REDMOND_REDACTED/oauth2/token' \
107
- --header 'content-type: application/x-www-form-urlencoded' \
108
- --data grant_type=client_credentials \
109
- --data client_id=REDMOND_CLIENT_ID \
110
- --data client_secret=REDMOND_CLIENT_SECRET \
111
- --data resource=REDMOND_RESOURCE_UUID
112
- ```
113
-
114
- NOTE: In the ruby version below, certain params are passed to the `get_token` call, instead of the client creation.
115
-
116
- ```ruby
117
- OAuth2::Client.new(
118
- "REDMOND_CLIENT_ID", # client_id
119
- "REDMOND_CLIENT_SECRET", # client_secret
120
- auth_scheme: :request_body, # Other modes are supported: :basic_auth, :tls_client_auth, :private_key_jwt
121
- token_url: "oauth2/token", # relative path, except with leading `/`, then absolute path
122
- site: "https://login.microsoftonline.com/REDMOND_REDACTED",
123
- ). # The base path for token_url when it is relative
124
- client_credentials. # There are many other types to choose from!
125
- get_token(resource: "REDMOND_RESOURCE_UUID")
126
- ```
127
-
128
- NOTE: `header` - The content type specified in the `curl` is already the default!
129
-
130
- If any of the above makes you uncomfortable, you may be in the wrong place.
131
- One of these might be what you are looking for:
132
+ If it seems like you are in the wrong place, you might try one of these:
132
133
 
133
134
  * [OAuth 2.0 Spec][oauth2-spec]
134
135
  * [doorkeeper gem][doorkeeper-gem] for OAuth 2.0 server/provider implementation.
135
136
  * [oauth sibling gem][sibling-gem] for OAuth 1.0 implementations in Ruby.
136
137
 
137
138
  [oauth2-spec]: https://oauth.net/2/
138
- [sibling-gem]: https://gitlab.com/oauth-xx/oauth
139
+ [sibling-gem]: https://gitlab.com/ruby-oauth/oauth
139
140
  [doorkeeper-gem]: https://github.com/doorkeeper-gem/doorkeeper
140
141
 
141
142
  ## 💡 Info you can shake a stick at
142
143
 
143
- | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
144
- |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
145
- | 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] |
146
- | 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] |
147
- | 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] |
148
- | 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] |
149
- | 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] |
150
- | 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] |
151
- | 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] |
152
- | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] |
153
- | 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] |
154
- | 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! |
155
- | 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] |
156
- | `...` 💖 | [![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] |
157
-
158
- ## 🚀 Release Documentation
159
-
160
- ### Version 2.0.x
144
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
145
+ |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
146
+ | 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] |
147
+ | 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] |
148
+ | 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] |
149
+ | 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] |
150
+ | 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] |
151
+ | 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] |
152
+ | 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] |
153
+ | 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] |
154
+ | 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] |
155
+ | 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] |
156
+ | `...` 💖 | [![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] |
161
157
 
162
- <details>
163
- <summary>2.0.x CHANGELOGs and READMEs</summary>
164
-
165
- | Version | Release Date | CHANGELOG | README |
166
- |---------|--------------|---------------------------------------|---------------------------------|
167
- | 2.0.11 | 2025-05-23 | [v2.0.11 CHANGELOG][2.0.11-changelog] | [v2.0.10 README][2.0.11-readme] |
168
- | 2.0.10 | 2025-05-17 | [v2.0.10 CHANGELOG][2.0.10-changelog] | [v2.0.10 README][2.0.10-readme] |
169
- | 2.0.9 | 2022-09-16 | [v2.0.9 CHANGELOG][2.0.9-changelog] | [v2.0.9 README][2.0.9-readme] |
170
- | 2.0.8 | 2022-09-01 | [v2.0.8 CHANGELOG][2.0.8-changelog] | [v2.0.8 README][2.0.8-readme] |
171
- | 2.0.7 | 2022-08-22 | [v2.0.7 CHANGELOG][2.0.7-changelog] | [v2.0.7 README][2.0.7-readme] |
172
- | 2.0.6 | 2022-07-13 | [v2.0.6 CHANGELOG][2.0.6-changelog] | [v2.0.6 README][2.0.6-readme] |
173
- | 2.0.5 | 2022-07-07 | [v2.0.5 CHANGELOG][2.0.5-changelog] | [v2.0.5 README][2.0.5-readme] |
174
- | 2.0.4 | 2022-07-01 | [v2.0.4 CHANGELOG][2.0.4-changelog] | [v2.0.4 README][2.0.4-readme] |
175
- | 2.0.3 | 2022-06-28 | [v2.0.3 CHANGELOG][2.0.3-changelog] | [v2.0.3 README][2.0.3-readme] |
176
- | 2.0.2 | 2022-06-24 | [v2.0.2 CHANGELOG][2.0.2-changelog] | [v2.0.2 README][2.0.2-readme] |
177
- | 2.0.1 | 2022-06-22 | [v2.0.1 CHANGELOG][2.0.1-changelog] | [v2.0.1 README][2.0.1-readme] |
178
- | 2.0.0 | 2022-06-21 | [v2.0.0 CHANGELOG][2.0.0-changelog] | [v2.0.0 README][2.0.0-readme] |
179
- </details>
158
+ ### Compatibility
180
159
 
181
- [2.0.11-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2011---2025-05-23
182
- [2.0.10-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#2010---2025-05-17
183
- [2.0.9-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#209---2022-09-16
184
- [2.0.8-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#208---2022-09-01
185
- [2.0.7-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#207---2022-08-22
186
- [2.0.6-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#206---2022-07-13
187
- [2.0.5-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#205---2022-07-07
188
- [2.0.4-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#204---2022-07-01
189
- [2.0.3-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#203---2022-06-28
190
- [2.0.2-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#202---2022-06-24
191
- [2.0.1-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#201---2022-06-22
192
- [2.0.0-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#200---2022-06-21
193
-
194
- [2.0.10-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.11/README.md
195
- [2.0.10-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.10/README.md
196
- [2.0.9-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.9/README.md
197
- [2.0.8-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.8/README.md
198
- [2.0.7-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.7/README.md
199
- [2.0.6-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.6/README.md
200
- [2.0.5-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.5/README.md
201
- [2.0.4-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.4/README.md
202
- [2.0.3-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.3/README.md
203
- [2.0.2-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.2/README.md
204
- [2.0.1-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.1/README.md
205
- [2.0.0-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v2.0.0/README.md
206
-
207
- ### Older Releases
160
+ Compatible with Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby.
208
161
 
209
- <details>
210
- <summary>1.4.x CHANGELOGs and READMEs</summary>
211
-
212
- | Version | Release Date | CHANGELOG | README |
213
- |---------|--------------|---------------------------------------|---------------------------------|
214
- | 1.4.11 | Sep 16, 2022 | [v1.4.11 CHANGELOG][1.4.11-changelog] | [v1.4.11 README][1.4.11-readme] |
215
- | 1.4.10 | Jul 1, 2022 | [v1.4.10 CHANGELOG][1.4.10-changelog] | [v1.4.10 README][1.4.10-readme] |
216
- | 1.4.9 | Feb 20, 2022 | [v1.4.9 CHANGELOG][1.4.9-changelog] | [v1.4.9 README][1.4.9-readme] |
217
- | 1.4.8 | Feb 18, 2022 | [v1.4.8 CHANGELOG][1.4.8-changelog] | [v1.4.8 README][1.4.8-readme] |
218
- | 1.4.7 | Mar 19, 2021 | [v1.4.7 CHANGELOG][1.4.7-changelog] | [v1.4.7 README][1.4.7-readme] |
219
- | 1.4.6 | Mar 19, 2021 | [v1.4.6 CHANGELOG][1.4.6-changelog] | [v1.4.6 README][1.4.6-readme] |
220
- | 1.4.5 | Mar 18, 2021 | [v1.4.5 CHANGELOG][1.4.5-changelog] | [v1.4.5 README][1.4.5-readme] |
221
- | 1.4.4 | Feb 12, 2020 | [v1.4.4 CHANGELOG][1.4.4-changelog] | [v1.4.4 README][1.4.4-readme] |
222
- | 1.4.3 | Jan 29, 2020 | [v1.4.3 CHANGELOG][1.4.3-changelog] | [v1.4.3 README][1.4.3-readme] |
223
- | 1.4.2 | Oct 1, 2019 | [v1.4.2 CHANGELOG][1.4.2-changelog] | [v1.4.2 README][1.4.2-readme] |
224
- | 1.4.1 | Oct 13, 2018 | [v1.4.1 CHANGELOG][1.4.1-changelog] | [v1.4.1 README][1.4.1-readme] |
225
- | 1.4.0 | Jun 9, 2017 | [v1.4.0 CHANGELOG][1.4.0-changelog] | [v1.4.0 README][1.4.0-readme] |
226
- </details>
162
+ | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 |
163
+ |------------------------------------------------|-------------------------------------------------------------------------------------|
164
+ | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
227
165
 
228
- [1.4.11-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#1411---2022-09-16
229
- [1.4.10-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#1410---2022-07-01
230
- [1.4.9-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#149---2022-02-20
231
- [1.4.8-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#148---2022-02-18
232
- [1.4.7-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#147---2021-03-19
233
- [1.4.6-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#146---2021-03-19
234
- [1.4.5-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#145---2021-03-18
235
- [1.4.4-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#144---2020-02-12
236
- [1.4.3-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#143---2020-01-29
237
- [1.4.2-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#142---2019-10-01
238
- [1.4.1-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#141---2018-10-13
239
- [1.4.0-changelog]: https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md?ref_type=heads#140---2017-06-09
240
-
241
- [1.4.11-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.11/README.md
242
- [1.4.10-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.10/README.md
243
- [1.4.9-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.9/README.md
244
- [1.4.8-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.8/README.md
245
- [1.4.7-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.7/README.md
246
- [1.4.6-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.6/README.md
247
- [1.4.5-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.5/README.md
248
- [1.4.4-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.4/README.md
249
- [1.4.3-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.3/README.md
250
- [1.4.2-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.2/README.md
251
- [1.4.1-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.1/README.md
252
- [1.4.0-readme]: https://gitlab.com/oauth-xx/oauth2/-/blob/v1.4.0/README.md
166
+ ### Federated DVCS
253
167
 
254
168
  <details>
255
- <summary>1.3.x Readmes</summary>
169
+ <summary>Find this repo on other forges (Coming soon!)</summary>
170
+
171
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
172
+ |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
173
+ | 🧪 [ruby-oauth/oauth2 on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ |
174
+ | 🧊 [ruby-oauth/oauth2 on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
175
+ | 🐙 [ruby-oauth/oauth2 on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | [💚][gh-discussions] |
176
+ | 🤼 [OAuth Ruby Google Group][⛳gg-discussions] | "Active" | ➖ | ➖ | ➖ | ➖ | [💚][⛳gg-discussions] |
177
+ | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
256
178
 
257
- | Version | Release Date | Readme |
258
- |----------|--------------|----------------------------------------------------------|
259
- | 1.3.1 | Mar 3, 2017 | https://gitlab.com/oauth-xx/oauth2/-/blob/v1.3.1/README.md |
260
- | 1.3.0 | Dec 27, 2016 | https://gitlab.com/oauth-xx/oauth2/-/blob/v1.3.0/README.md |
261
179
  </details>
262
180
 
181
+ [gh-discussions]: https://github.com/ruby-oauth/oauth2/discussions
182
+
183
+ ### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/oauth2)](https://tidelift.com/subscription/pkg/rubygems-oauth2?utm_source=rubygems-oauth2&utm_medium=referral&utm_campaign=readme)
184
+
263
185
  <details>
264
- <summary>&le;= 1.2.x Readmes (2016 and before)</summary>
265
-
266
- | Version | Release Date | Readme |
267
- |----------|--------------|----------------------------------------------------------|
268
- | 1.2.0 | Jun 30, 2016 | https://gitlab.com/oauth-xx/oauth2/-/blob/v1.2.0/README.md |
269
- | 1.1.0 | Jan 30, 2016 | https://gitlab.com/oauth-xx/oauth2/-/blob/v1.1.0/README.md |
270
- | 1.0.0 | May 23, 2014 | https://gitlab.com/oauth-xx/oauth2/-/blob/v1.0.0/README.md |
271
- | < 1.0.0 | Find here | https://gitlab.com/oauth-xx/oauth2/-/tags |
186
+ <summary>Need enterprise-level guarantees?</summary>
187
+
188
+ [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
189
+
190
+ - 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies
191
+ - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
192
+ - 💡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
193
+
194
+ Alternatively:
195
+
196
+ - [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
197
+ - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
198
+ - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
199
+
272
200
  </details>
273
201
 
274
202
  ## ✨ Installation
275
203
 
276
204
  Install the gem and add to the application's Gemfile by executing:
277
205
 
278
- $ bundle add oauth2
206
+ ```console
207
+ bundle add oauth2
208
+ ```
279
209
 
280
210
  If bundler is not being used to manage dependencies, install the gem by executing:
281
211
 
282
- $ gem install oauth2
212
+ ```console
213
+ gem install oauth2
214
+ ```
283
215
 
284
216
  ### 🔒 Secure Installation
285
217
 
286
- `oauth2` is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by
218
+ <details>
219
+ <summary>For Medium or High Security Installations</summary>
220
+
221
+ This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by
287
222
  [stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with
288
223
  by following the instructions below.
289
224
 
290
225
  Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:
291
226
 
292
- ```shell
293
- gem cert --add <(curl -Ls https://raw.github.com/oauth-xx/oauth2/main/certs/pboling.pem)
227
+ ```console
228
+ gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem)
294
229
  ```
295
230
 
296
231
  You only need to do that once. Then proceed to install with:
297
232
 
298
- ```shell
233
+ ```console
299
234
  gem install oauth2 -P MediumSecurity
300
235
  ```
301
236
 
@@ -305,12 +240,14 @@ This is necessary because not all of `oauth2`’s dependencies are signed, so we
305
240
 
306
241
  If you want to up your security game full-time:
307
242
 
308
- ```shell
243
+ ```console
309
244
  bundle config set --global trust-policy MediumSecurity
310
245
  ```
311
246
 
312
247
  NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine.
313
248
 
249
+ </details>
250
+
314
251
  ## OAuth2 for Enterprise
315
252
 
316
253
  Available as part of the Tidelift Subscription.
@@ -330,10 +267,12 @@ For more see [SECURITY.md][🔐security].
330
267
 
331
268
  - Works with Ruby versions >= 2.2
332
269
  - Drop support for the expired MAC Draft (all versions)
333
- - Support IETF rfc7523 JWT Bearer Tokens
334
- - Support IETF rfc7231 Relative Location in Redirect
335
- - Support IETF rfc6749 Don't set oauth params when nil
336
- - Support IETF rfc7009 Token Revocation (since v2.0.10)
270
+ - Support IETF rfc7515 JSON Web Signature - JWS (since v2.0.12)
271
+ - Support JWT `kid` for key discovery and management
272
+ - Support IETF rfc7523 JWT Bearer Tokens (since v2.0.0)
273
+ - Support IETF rfc7231 Relative Location in Redirect (since v2.0.0)
274
+ - Support IETF rfc6749 Don't set oauth params when nil (since v2.0.0)
275
+ - Support IETF rfc7009 Token Revocation (since v2.0.10, updated in v2.0.13 to support revocation via URL-encoded parameters)
337
276
  - 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)
338
277
  - 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`
339
278
  - Adds option to `OAuth2::Client#get_token`:
@@ -341,14 +280,14 @@ For more see [SECURITY.md][🔐security].
341
280
  - Adds option to `OAuth2::AccessToken#initialize`:
342
281
  - `:expires_latency` (`nil`); number of seconds by which AccessToken validity will be reduced to offset latency
343
282
  - By default, keys are transformed to snake case.
344
- - Original keys will still work as previously, in most scenarios, thanks to [snaky_hash][snaky_hash] gem.
345
- - 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.
346
- - As of version 2.0.4 you can turn key transformation off with the `snaky: false` option.
283
+ - Original keys will still work as previously, in most scenarios, thanks to [snaky_hash][snaky_hash] gem.
284
+ - 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.
285
+ - As of version 2.0.4 you can turn key transformation off with the `snaky: false` option.
347
286
  - By default, the `:auth_scheme` is now `:basic_auth` (instead of `:request_body`)
348
- - Third-party strategies and gems may need to be updated if a provider was requiring client id/secret in the request body
349
- - [... A lot more](https://gitlab.com/oauth-xx/oauth2/-/blob/main/CHANGELOG.md#200-2022-06-21-tag)
287
+ - Third-party strategies and gems may need to be updated if a provider was requiring client id/secret in the request body
288
+ - [... A lot more](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/CHANGELOG.md#200-2022-06-21-tag)
350
289
 
351
- [snaky_hash]: https://gitlab.com/oauth-xx/snaky_hash
290
+ [snaky_hash]: https://gitlab.com/ruby-oauth/snaky_hash
352
291
 
353
292
  ## Compatibility
354
293
 
@@ -364,7 +303,7 @@ This gem is tested against MRI, JRuby, and Truffleruby.
364
303
  Each of those has varying versions that target a specific version of MRI Ruby.
365
304
  This gem should work in the just-listed Ruby engines according to the targeted MRI compatibility in the table below.
366
305
  If you would like to add support for additional engines,
367
- see [gemfiles/README.md](gemfiles/README.md), then submit a PR to the correct maintenance branch as according to the table below.
306
+ see [gemfiles/README.md](gemfiles/README.md), then submit a PR to the correct maintenance branch as according to the table below.
368
307
  </details>
369
308
 
370
309
  <details>
@@ -393,9 +332,7 @@ of a major release, support for that Ruby version may be dropped.
393
332
  NOTE: The 1.4 series will only receive critical security updates.
394
333
  See [SECURITY.md][🔐security].
395
334
 
396
- ## 🔧 Basic Usage
397
-
398
- ### Global Configuration
335
+ ## ⚙️ Configuration
399
336
 
400
337
  You can turn on additional warnings.
401
338
 
@@ -422,6 +359,8 @@ You'll likely need to do some source diving.
422
359
  This gem has 100% test coverage for lines and branches, so the specs are a great place to look for ideas.
423
360
  If you have time and energy please contribute to the documentation!
424
361
 
362
+ ## 🔧 Basic Usage
363
+
425
364
  ### `authorize_url` and `token_url` are on site root (Just Works!)
426
365
 
427
366
  ```ruby
@@ -485,9 +424,11 @@ response.parsed.class.name # => SnakyHash::StringKeyed (from snaky_hash g
485
424
 
486
425
  As of v2.0.11, if you need to serialize the parsed result, you can!
487
426
 
488
- There are two ways to do this, and the second option recommended.
427
+ There are two ways to do this, globally, or discretely. The discrete way is recommended.
489
428
 
490
- 1. Globally configure `SnakyHash::StringKeyed` to use the serializer. Put this in your code somewhere reasonable (like an initializer for Rails):
429
+ ##### Global Serialization Config
430
+
431
+ Globally configure `SnakyHash::StringKeyed` to use the serializer. Put this in your code somewhere reasonable (like an initializer for Rails).
491
432
 
492
433
  ```ruby
493
434
  SnakyHash::StringKeyed.class_eval do
@@ -495,6 +436,84 @@ SnakyHash::StringKeyed.class_eval do
495
436
  end
496
437
  ```
497
438
 
439
+ ##### Discrete Serialization Config
440
+
441
+ Discretely configure a custom Snaky Hash class to use the serializer.
442
+
443
+ ```ruby
444
+ class MySnakyHash < SnakyHash::StringKeyed
445
+ # Give this hash class `dump` and `load` abilities!
446
+ extend SnakyHash::Serializer
447
+ end
448
+
449
+ # And tell your client to use the custom class in each call:
450
+ client = OAuth2::Client.new("client_id", "client_secret", site: "https://example.org/oauth2")
451
+ token = client.get_token({snaky_hash_klass: MySnakyHash})
452
+ ```
453
+
454
+ ##### Serialization Extensions
455
+
456
+ These extensions work regardless of whether you used the global or discrete config above.
457
+
458
+ There are a few hacks you may need in your class to support Ruby < 2.4.2 or < 2.6.
459
+ They are likely not needed if you are on a newer Ruby.
460
+ See [response_spec.rb](https://github.com/ruby-oauth/oauth2/blob/main/spec/oauth2/response_spec.rb) if you need to study the hacks for older Rubies.
461
+
462
+ ```ruby
463
+ class MySnakyHash < SnakyHash::StringKeyed
464
+ # Give this hash class `dump` and `load` abilities!
465
+ extend SnakyHash::Serializer
466
+
467
+ #### Serialization Extentions
468
+ #
469
+ # Act on the non-hash values (including the values of hashes) as they are dumped to JSON
470
+ # In other words, this retains nested hashes, and only the deepest leaf nodes become bananas.
471
+ # WARNING: This is a silly example!
472
+ dump_value_extensions.add(:to_fruit) do |value|
473
+ "banana" # => Make values "banana" on dump
474
+ end
475
+
476
+ # Act on the non-hash values (including the values of hashes) as they are loaded from the JSON dump
477
+ # In other words, this retains nested hashes, and only the deepest leaf nodes become ***.
478
+ # WARNING: This is a silly example!
479
+ load_value_extensions.add(:to_stars) do |value|
480
+ "***" # Turn dumped bananas into *** when they are loaded
481
+ end
482
+
483
+ # Act on the entire hash as it is prepared for dumping to JSON
484
+ # WARNING: This is a silly example!
485
+ dump_hash_extensions.add(:to_cheese) do |value|
486
+ if value.is_a?(Hash)
487
+ value.transform_keys do |key|
488
+ split = key.split("_")
489
+ first_word = split[0]
490
+ key.sub(first_word, "cheese")
491
+ end
492
+ else
493
+ value
494
+ end
495
+ end
496
+
497
+ # Act on the entire hash as it is loaded from the JSON dump
498
+ # WARNING: This is a silly example!
499
+ load_hash_extensions.add(:to_pizza) do |value|
500
+ if value.is_a?(Hash)
501
+ res = klass.new
502
+ value.keys.each_with_object(res) do |key, result|
503
+ split = key.split("_")
504
+ last_word = split[-1]
505
+ new_key = key.sub(last_word, "pizza")
506
+ result[new_key] = value[key]
507
+ end
508
+ res
509
+ else
510
+ value
511
+ end
512
+ end
513
+ end
514
+ ```
515
+
516
+ See [response_spec.rb](https://github.com/ruby-oauth/oauth2/blob/main/spec/oauth2/response_spec.rb), or the [ruby-oauth/snaky_hash](https://gitlab.com/ruby-oauth/snaky_hash) gem for more ideas.
498
517
 
499
518
  #### What if I hate snakes and/or indifference?
500
519
 
@@ -537,7 +556,7 @@ The `AccessToken` methods `#get`, `#post`, `#put` and `#delete` and the generic
537
556
  will return an instance of the #OAuth2::Response class.
538
557
 
539
558
  This instance contains a `#parsed` method that will parse the response body and
540
- 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
559
+ return a Hash-like [`SnakyHash::StringKeyed`](https://gitlab.com/ruby-oauth/snaky_hash/-/blob/main/lib/snaky_hash/string_keyed.rb) if the `Content-Type` is `application/x-www-form-urlencoded` or if
541
560
  the body is a JSON object. It will return an Array if the body is a JSON
542
561
  array. Otherwise, it will return the original body string.
543
562
 
@@ -567,11 +586,11 @@ Response instance will contain the `OAuth2::Error` instance.
567
586
 
568
587
  Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
569
588
  authentication grant types have helper strategy classes that simplify client
570
- use. They are available via the [`#auth_code`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
571
- [`#implicit`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
572
- [`#password`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/password.rb),
573
- [`#client_credentials`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/client_credentials.rb), and
574
- [`#assertion`](https://gitlab.com/oauth-xx/oauth2/-/blob/main/lib/oauth2/strategy/assertion.rb) methods respectively.
589
+ use. They are available via the [`#auth_code`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
590
+ [`#implicit`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
591
+ [`#password`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/password.rb),
592
+ [`#client_credentials`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/client_credentials.rb), and
593
+ [`#assertion`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/assertion.rb) methods respectively.
575
594
 
576
595
  These aren't full examples, but demonstrative of the differences between usage for each strategy.
577
596
  ```ruby
@@ -612,9 +631,259 @@ access = client.auth_code.get_token("code_value", redirect_uri: "http://localhos
612
631
  You can always use the `#request` method on the `OAuth2::Client` instance to make
613
632
  requests for tokens for any Authentication grant type.
614
633
 
615
- ### 🚀 Release Instructions
634
+ ## 📘 Comprehensive Usage
616
635
 
617
- See [CONTRIBUTING.md][🤝contributing].
636
+ ### Common Flows (end-to-end)
637
+
638
+ - Authorization Code (server-side web app):
639
+
640
+ ```ruby
641
+ require "oauth2"
642
+ client = OAuth2::Client.new(
643
+ ENV["CLIENT_ID"],
644
+ ENV["CLIENT_SECRET"],
645
+ site: "https://provider.example.com",
646
+ redirect_uri: "https://my.app.example.com/oauth/callback",
647
+ )
648
+
649
+ # Step 1: redirect user to consent
650
+ state = SecureRandom.hex(16)
651
+ auth_url = client.auth_code.authorize_url(scope: "openid profile email", state: state)
652
+ # redirect_to auth_url
653
+
654
+ # Step 2: handle the callback
655
+ # params[:code], params[:state]
656
+ raise "state mismatch" unless params[:state] == state
657
+ access = client.auth_code.get_token(params[:code])
658
+
659
+ # Step 3: call APIs
660
+ profile = access.get("/api/v1/me").parsed
661
+ ```
662
+
663
+ - Client Credentials (machine-to-machine):
664
+
665
+ ```ruby
666
+ client = OAuth2::Client.new(ENV["CLIENT_ID"], ENV["CLIENT_SECRET"], site: "https://provider.example.com")
667
+ access = client.client_credentials.get_token(audience: "https://api.example.com")
668
+ resp = access.get("/v1/things")
669
+ ```
670
+
671
+ - Resource Owner Password (legacy; avoid when possible):
672
+
673
+ ```ruby
674
+ access = client.password.get_token("jdoe", "s3cret", scope: "read")
675
+ ```
676
+
677
+ ### Refresh Tokens
678
+
679
+ When the server issues a refresh_token, you can refresh manually or implement an auto-refresh wrapper.
680
+
681
+ - Manual refresh:
682
+
683
+ ```ruby
684
+ if access.expired?
685
+ access = access.refresh
686
+ end
687
+ ```
688
+
689
+ - Auto-refresh wrapper pattern:
690
+
691
+ ```ruby
692
+ class AutoRefreshingToken
693
+ def initialize(token_provider, store: nil)
694
+ @token = token_provider
695
+ @store = store # e.g., something that responds to read/write for token data
696
+ end
697
+
698
+ def with(&blk)
699
+ tok = ensure_fresh!
700
+ blk ? blk.call(tok) : tok
701
+ rescue OAuth2::Error => e
702
+ # If a 401 suggests token invalidation, try one refresh and retry once
703
+ if e.response && e.response.status == 401 && @token.refresh_token
704
+ @token = @token.refresh
705
+ @store.write(@token.to_hash) if @store
706
+ retry
707
+ end
708
+ raise
709
+ end
710
+
711
+ private
712
+
713
+ def ensure_fresh!
714
+ if @token.expired? && @token.refresh_token
715
+ @token = @token.refresh
716
+ @store.write(@token.to_hash) if @store
717
+ end
718
+ @token
719
+ end
720
+ end
721
+
722
+ # usage
723
+ keeper = AutoRefreshingToken.new(access)
724
+ keeper.with { |tok| tok.get("/v1/protected") }
725
+ ```
726
+
727
+ Persist the token across processes using `AccessToken#to_hash` and `AccessToken.from_hash(client, hash)`.
728
+
729
+ ### Token Revocation (RFC 7009)
730
+
731
+ You can revoke either the access token or the refresh token.
732
+
733
+ ```ruby
734
+ # Revoke the current access token
735
+ access.revoke(token_type_hint: :access_token)
736
+
737
+ # Or explicitly revoke the refresh token (often also invalidates associated access tokens)
738
+ access.revoke(token_type_hint: :refresh_token)
739
+ ```
740
+
741
+ ### Client Configuration Tips
742
+
743
+ - Authentication schemes for the token request:
744
+
745
+ ```ruby
746
+ OAuth2::Client.new(
747
+ id,
748
+ secret,
749
+ site: "https://provider.example.com",
750
+ auth_scheme: :basic_auth, # default. Alternatives: :request_body, :tls_client_auth, :private_key_jwt
751
+ )
752
+ ```
753
+
754
+ - Faraday connection, timeouts, proxy, custom adapter/middleware:
755
+
756
+ ```ruby
757
+ client = OAuth2::Client.new(
758
+ id,
759
+ secret,
760
+ site: "https://provider.example.com",
761
+ connection_opts: {
762
+ request: {open_timeout: 5, timeout: 15},
763
+ proxy: ENV["HTTPS_PROXY"],
764
+ ssl: {verify: true},
765
+ },
766
+ ) do |faraday|
767
+ faraday.request(:url_encoded)
768
+ # faraday.response :logger, Logger.new($stdout) # see OAUTH_DEBUG below
769
+ faraday.adapter(:net_http_persistent) # or any Faraday adapter you need
770
+ end
771
+ ```
772
+
773
+ - Redirection: The library follows up to `max_redirects` (default 5). You can override per-client via `options[:max_redirects]`.
774
+
775
+ ### Handling Responses and Errors
776
+
777
+ - Parsing:
778
+
779
+ ```ruby
780
+ resp = access.get("/v1/thing")
781
+ resp.status # Integer
782
+ resp.headers # Hash
783
+ resp.body # String
784
+ resp.parsed # SnakyHash::StringKeyed or Array when JSON array
785
+ ```
786
+
787
+ - Error handling:
788
+
789
+ ```ruby
790
+ begin
791
+ access.get("/v1/forbidden")
792
+ rescue OAuth2::Error => e
793
+ e.code # OAuth2 error code (when present)
794
+ e.description # OAuth2 error description (when present)
795
+ e.response # OAuth2::Response (full access to status/headers/body)
796
+ end
797
+ ```
798
+
799
+ - Disable raising on 4xx/5xx to inspect the response yourself:
800
+
801
+ ```ruby
802
+ client = OAuth2::Client.new(id, secret, site: site, raise_errors: false)
803
+ res = client.request(:get, "/v1/maybe-errors")
804
+ if res.status == 429
805
+ sleep res.headers["retry-after"].to_i
806
+ end
807
+ ```
808
+
809
+ ### Making Raw Token Requests
810
+
811
+ If a provider requires non-standard parameters or headers, you can call `client.get_token` directly:
812
+
813
+ ```ruby
814
+ access = client.get_token({
815
+ grant_type: "client_credentials",
816
+ audience: "https://api.example.com",
817
+ headers: {"X-Custom" => "value"},
818
+ parse: :json, # override parsing
819
+ })
820
+ ```
821
+
822
+ ### OpenID Connect (OIDC) Notes
823
+
824
+ - If the token response includes an `id_token` (a JWT), this gem surfaces it but does not validate the signature. Use a JWT library and your provider's JWKs to verify it.
825
+ - For private_key_jwt client authentication, provide `auth_scheme: :private_key_jwt` and ensure your key configuration matches the provider requirements.
826
+
827
+ ### Debugging
828
+
829
+ - Set environment variable `OAUTH_DEBUG=true` to enable verbose Faraday logging (uses the client-provided logger).
830
+ - To mirror a working curl request, ensure you set the same auth scheme, params, and content type. The Quick Example at the top shows a curl-to-ruby translation.
831
+
832
+ ---
833
+
834
+ ## 🦷 FLOSS Funding
835
+
836
+ While ruby-oauth tools are free software and will always be, the project would benefit immensely from some funding.
837
+ Raising a monthly budget of... "dollars" would make the project more sustainable.
838
+
839
+ We welcome both individual and corporate sponsors! We also offer a
840
+ wide array of funding channels to account for your preferences
841
+ (although currently [Open Collective][🖇osc] is our preferred funding platform).
842
+
843
+ **If you're working in a company that's making significant use of ruby-oauth tools we'd
844
+ appreciate it if you suggest to your company to become a ruby-oauth sponsor.**
845
+
846
+ You can support the development of ruby-oauth tools via
847
+ [GitHub Sponsors][🖇sponsor],
848
+ [Liberapay][⛳liberapay],
849
+ [PayPal][🖇paypal],
850
+ [Open Collective][🖇osc]
851
+ and [Tidelift][🏙️entsup-tidelift].
852
+
853
+ | 📍 NOTE |
854
+ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
855
+ | If doing a sponsorship in the form of donation is problematic for your company <br/> from an accounting standpoint, we'd recommend the use of Tidelift, <br/> where you can get a support-like subscription instead. |
856
+
857
+ ### Open Collective for Individuals
858
+
859
+ <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
860
+ No backers yet. Be the first!
861
+ <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
862
+
863
+ Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/ruby-oauth#backer)]
864
+
865
+ ### Open Collective for Organizations
866
+
867
+ <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
868
+ No sponsors yet. Be the first!
869
+ <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
870
+
871
+ Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/ruby-oauth#sponsor)]
872
+
873
+ ### Another way to support open-source
874
+
875
+ > How wonderful it is that nobody need wait a single moment before starting to improve the world.<br/>
876
+ >—Anne Frank
877
+
878
+ I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).
879
+
880
+ If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
881
+
882
+ I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
883
+
884
+ **[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
885
+
886
+ [![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]
618
887
 
619
888
  ## 🔐 Security
620
889
 
@@ -623,22 +892,27 @@ See [SECURITY.md][🔐security].
623
892
  ## 🤝 Contributing
624
893
 
625
894
  If you need some ideas of where to help, you could work on adding more code coverage,
626
- or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues], or [PRs][🤝gh-pulls],
895
+ or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues][🤝gh-issues], or [PRs][🤝gh-pulls],
627
896
  or use the gem and think about how it could be better.
628
897
 
629
898
  We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
630
899
 
631
900
  See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
632
901
 
902
+ ### 🚀 Release Instructions
903
+
904
+ See [CONTRIBUTING.md][🤝contributing].
905
+
633
906
  ### Code Coverage
634
907
 
635
908
  [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls]
636
- [![QLTY Test Coverage][🔑qlty-covi♻️]][🔑qlty-cov]
909
+
910
+ [![QLTY Test Coverage][🔑qlty-covi]][🔑qlty-cov]
637
911
 
638
912
  ### 🪇 Code of Conduct
639
913
 
640
- Everyone interacting in this project's codebases, issue trackers,
641
- chat rooms and mailing lists is expected to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct].
914
+ Everyone interacting with this project's codebases, issue trackers,
915
+ chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct].
642
916
 
643
917
  ## 🌈 Contributors
644
918
 
@@ -646,18 +920,21 @@ chat rooms and mailing lists is expected to follow the [![Contributor Covenant 2
646
920
 
647
921
  Made with [contributors-img][🖐contrib-rocks].
648
922
 
649
- Also see GitLab Contributors: [https://gitlab.com/oauth-xx/oauth2/-/graphs/main][🚎contributors-gl]
923
+ Also see GitLab Contributors: [https://gitlab.com/ruby-oauth/oauth2/-/graphs/main][🚎contributors-gl]
650
924
 
651
- ## ⭐️ Star History
925
+ <details>
926
+ <summary>⭐️ Star History</summary>
652
927
 
653
- <a href="https://star-history.com/#oauth-xx/oauth2&Date">
928
+ <a href="https://star-history.com/#ruby-oauth/oauth2&Date">
654
929
  <picture>
655
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=oauth-xx/oauth2&type=Date&theme=dark" />
656
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=oauth-xx/oauth2&type=Date" />
657
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=oauth-xx/oauth2&type=Date" />
930
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=ruby-oauth/oauth2&type=Date&theme=dark" />
931
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=ruby-oauth/oauth2&type=Date" />
932
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=ruby-oauth/oauth2&type=Date" />
658
933
  </picture>
659
934
  </a>
660
935
 
936
+ </details>
937
+
661
938
  ## 📌 Versioning
662
939
 
663
940
  This Library adheres to [![Semantic Versioning 2.0.0][📌semver-img]][📌semver].
@@ -666,34 +943,35 @@ Specifically, if a minor or patch version is released that breaks backward compa
666
943
  a new version should be immediately released that restores compatibility.
667
944
  Breaking changes to the public API will only be introduced with new major versions.
668
945
 
669
- ### 📌 Is "Platform Support" part of the public API?
946
+ > dropping support for a platform is both obviously and objectively a breaking change <br/>
947
+ >—Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716][📌semver-breaking]
670
948
 
671
- Yes. But I'm obligated to include notes...
949
+ I understand that policy doesn't work universally ("exceptions to every rule!"),
950
+ but it is the policy here.
951
+ As such, in many cases it is good to specify a dependency on this library using
952
+ the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
672
953
 
673
- SemVer should, but doesn't explicitly, say that dropping support for specific Platforms
674
- is a *breaking change* to an API.
675
- It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless.
954
+ For example:
955
+
956
+ ```ruby
957
+ spec.add_dependency("oauth2", "~> 2.0")
958
+ ```
676
959
 
677
- > dropping support for a platform is both obviously and objectively a breaking change
960
+ <details>
961
+ <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
678
962
 
679
- - Jordan Harband (@ljharb, maintainer of SemVer) [in SemVer issue 716][📌semver-breaking]
963
+ SemVer should, IMO, but doesn't explicitly, say that dropping support for specific Platforms
964
+ is a *breaking change* to an API.
965
+ It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless.
680
966
 
681
967
  To get a better understanding of how SemVer is intended to work over a project's lifetime,
682
968
  read this article from the creator of SemVer:
683
969
 
684
970
  - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
685
971
 
686
- As a result of this policy, and the interpretive lens used by the maintainer,
687
- you can (and should) specify a dependency on these libraries using
688
- the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
689
-
690
- For example:
691
-
692
- ```ruby
693
- spec.add_dependency("oauth2", "~> 2.0")
694
- ```
972
+ </details>
695
973
 
696
- See [CHANGELOG.md][📌changelog] for list of releases.
974
+ See [CHANGELOG.md][📌changelog] for a list of releases.
697
975
 
698
976
  ## 📄 License
699
977
 
@@ -705,45 +983,91 @@ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright
705
983
 
706
984
  <ul>
707
985
  <li>
708
- 2017 - 2025 Peter H. Boling, of
709
- <a href="https://railsbling.com">
710
- RailsBling.com
986
+ Copyright (c) 2017–2025 Peter H. Boling, of
987
+ <a href="https://discord.gg/3qme4XHNKN">
988
+ Galtzo.com
711
989
  <picture>
712
- <img alt="Rails Bling" height="20" src="https://railsbling.com/images/logos/RailsBling-TrainLogo.svg" />
990
+ <img src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px-blank.svg" alt="Galtzo.com Logo (Wordless) by Aboling0, CC BY-SA 4.0" width="24">
713
991
  </picture>
714
- </a>, and oauth2 contributors
992
+ </a>, and oauth2 contributors.
715
993
  </li>
716
994
  <li>
717
- Copyright (c) 2011 - 2013 Michael Bleigh and Intridea, Inc.
995
+ Copyright (c) 2011-2013 Michael Bleigh and Intridea, Inc.
718
996
  </li>
719
997
  </ul>
720
998
 
721
- ## 🤑 One more thing
999
+ ## 🤑 A request for help
1000
+
1001
+ Maintainers have teeth and need to pay their dentists.
1002
+ After getting laid off in an RIF in March and filled with many dozens of rejections,
1003
+ I'm now spending ~60+ hours a week building open source tools.
1004
+ I'm hoping to be able to pay for my kids' health insurance this month,
1005
+ so if you value the work I am doing, I need your support.
1006
+ Please consider sponsoring me or the project.
1007
+
1008
+ To join the community or get help 👇️ Join the Discord.
1009
+
1010
+ [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
1011
+
1012
+ To say "thanks for maintaining such a great tool" ☝️ Join the Discord or 👇️ send money.
1013
+
1014
+ [![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]
722
1015
 
723
- You made it to the bottom of the page,
724
- so perhaps you'll indulge me for another 20 seconds.
725
- I maintain many dozens of gems, including this one,
726
- because I want Ruby to be a great place for people to solve problems, big and small.
727
- Please consider supporting my efforts via the giant yellow link below,
728
- or one of the others at the head of this README.
1016
+ ### Please give the project a star ⭐ ♥.
729
1017
 
730
- [![Buy me a latte][🖇buyme-img]][🖇buyme]
1018
+ Thanks for RTFM. ☺️
1019
+
1020
+ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
1021
+ [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611
1022
+ [⛳liberapay]: https://liberapay.com/pboling/donate
1023
+ [🖇osc-all-img]: https://img.shields.io/opencollective/all/ruby-oauth
1024
+ [🖇osc-sponsors-img]: https://img.shields.io/opencollective/sponsors/ruby-oauth
1025
+ [🖇osc-backers-img]: https://img.shields.io/opencollective/backers/ruby-oauth
1026
+ [🖇osc-backers]: https://opencollective.com/ruby-oauth#backer
1027
+ [🖇osc-backers-i]: https://opencollective.com/ruby-oauth/backers/badge.svg?style=flat
1028
+ [🖇osc-sponsors]: https://opencollective.com/ruby-oauth#sponsor
1029
+ [🖇osc-sponsors-i]: https://opencollective.com/ruby-oauth/sponsors/badge.svg?style=flat
1030
+ [🖇osc-all-bottom-img]: https://img.shields.io/opencollective/all/ruby-oauth?style=for-the-badge
1031
+ [🖇osc-sponsors-bottom-img]: https://img.shields.io/opencollective/sponsors/ruby-oauth?style=for-the-badge
1032
+ [🖇osc-backers-bottom-img]: https://img.shields.io/opencollective/backers/ruby-oauth?style=for-the-badge
1033
+ [🖇osc]: https://opencollective.com/ruby-oauth
1034
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
1035
+ [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github
1036
+ [🖇sponsor]: https://github.com/sponsors/pboling
1037
+ [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
1038
+ [🖇polar]: https://polar.sh/pboling
1039
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat
1040
+ [🖇kofi]: https://ko-fi.com/O5O86SNP4
1041
+ [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
1042
+ [🖇patreon]: https://patreon.com/galtzo
1043
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat
1044
+ [🖇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
1045
+ [🖇buyme]: https://www.buymeacoffee.com/pboling
1046
+ [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
1047
+ [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A
1048
+ [🖇paypal]: https://www.paypal.com/paypalme/peterboling
1049
+ [🖇floss-funding.dev]: https://floss-funding.dev
1050
+ [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
1051
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
1052
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge
731
1053
 
732
1054
  [⛳gg-discussions]: https://groups.google.com/g/oauth-ruby
733
1055
  [⛳gg-discussions-img]: https://img.shields.io/badge/google-group-0093D0.svg?style=for-the-badge&logo=google&logoColor=orange
734
1056
 
735
1057
  [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
736
- [⛳️gem-namespace]: https://github.com/oauth-xx/oauth2
737
- [⛳️namespace-img]: https://img.shields.io/badge/namespace-OAuth2-brightgreen.svg?style=flat&logo=ruby&logoColor=white
1058
+ [⛳️gem-namespace]: https://github.com/ruby-oauth/oauth2
1059
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-OAuth2-3C2D2D.svg?style=square&logo=ruby&logoColor=white
738
1060
  [⛳️gem-name]: https://rubygems.org/gems/oauth2
739
- [⛳️name-img]: https://img.shields.io/badge/name-oauth2-brightgreen.svg?style=flat&logo=rubygems&logoColor=red
740
- [🚂bdfl-blog]: http://www.railsbling.com/tags/oauth2
741
- [🚂bdfl-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
742
- [🚂bdfl-contact]: http://www.railsbling.com/contact
743
- [🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
1061
+ [⛳️name-img]: https://img.shields.io/badge/name-oauth2-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
1062
+ [⛳️tag-img]: https://img.shields.io/github/tag/ruby-oauth/oauth2.svg
1063
+ [⛳️tag]: http://github.com/ruby-oauth/oauth2/releases
1064
+ [🚂maint-blog]: http://www.railsbling.com/tags/oauth2
1065
+ [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
1066
+ [🚂maint-contact]: http://www.railsbling.com/contact
1067
+ [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
744
1068
  [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
745
1069
  [💖🖇linkedin-img]: https://img.shields.io/badge/PeterBoling-LinkedIn-0B66C2?style=flat&logo=newjapanprowrestling
746
- [💖✌️wellfound]: https://angel.co/u/peter-boling
1070
+ [💖✌️wellfound]: https://wellfound.com/u/peter-boling/u/peter-boling
747
1071
  [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
748
1072
  [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
749
1073
  [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
@@ -765,78 +1089,68 @@ or one of the others at the head of this README.
765
1089
  [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white
766
1090
  [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
767
1091
  [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white
768
- [🏙️entsup-tidelift]: https://tidelift.com/subscription
1092
+ [🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-oauth2?utm_source=rubygems-oauth2&utm_medium=referral&utm_campaign=readme
769
1093
  [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white
770
1094
  [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar
771
1095
  [💁🏼‍♂️peterboling]: http://www.peterboling.com
772
1096
  [🚂railsbling]: http://www.railsbling.com
773
1097
  [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
774
- [📜src-gl]: https://gitlab.com/oauth-xx/oauth2/
1098
+ [📜src-gl]: https://gitlab.com/ruby-oauth/oauth2/
775
1099
  [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
776
- [📜src-cb]: https://codeberg.org/oauth-xx/oauth2
1100
+ [📜src-cb]: https://codeberg.org/ruby-oauth/oauth2
777
1101
  [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green
778
- [📜src-gh]: https://github.com/oauth-xx/oauth2
1102
+ [📜src-gh]: https://github.com/ruby-oauth/oauth2
779
1103
  [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
780
1104
  [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
781
- [📜wiki]: https://gitlab.com/oauth-xx/oauth2/-/wikis/home
1105
+ [📜wiki]: https://gitlab.com/ruby-oauth/oauth2/-/wikis/home
782
1106
  [📜wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=Wiki&logoColor=white
783
1107
  [👽dl-rank]: https://rubygems.org/gems/oauth2
784
1108
  [👽dl-ranki]: https://img.shields.io/gem/rd/oauth2.svg
785
- [👽oss-help]: https://www.codetriage.com/oauth-xx/oauth2
786
- [👽oss-helpi]: https://www.codetriage.com/oauth-xx/oauth2/badges/users.svg
1109
+ [👽oss-help]: https://www.codetriage.com/ruby-oauth/oauth2
1110
+ [👽oss-helpi]: https://www.codetriage.com/ruby-oauth/oauth2/badges/users.svg
787
1111
  [👽version]: https://rubygems.org/gems/oauth2
788
1112
  [👽versioni]: https://img.shields.io/gem/v/oauth2.svg
789
- [🔑qlty-mnt]: https://qlty.sh/gh/oauth-xx/projects/oauth2
790
- [🔑qlty-mnti♻️]: https://qlty.sh/badges/d3370c2c-8791-4202-9759-76f527f76005/maintainability.svg
791
- [🔑qlty-cov]: https://qlty.sh/gh/oauth-xx/projects/oauth2
792
- [🔑qlty-covi♻️]: https://qlty.sh/badges/d3370c2c-8791-4202-9759-76f527f76005/test_coverage.svg
793
- [🔑codecov]: https://codecov.io/gh/oauth-xx/oauth2
794
- [🔑codecovi♻️]: https://codecov.io/gh/oauth-xx/oauth2/graph/badge.svg?token=bNqSzNiuo2
795
- [🔑coveralls]: https://coveralls.io/github/oauth-xx/oauth2?branch=main
796
- [🔑coveralls-img]: https://coveralls.io/repos/github/oauth-xx/oauth2/badge.svg?branch=main
797
- [🔑depfu]: https://depfu.com/github/oauth-xx/oauth2?project_id=5884
798
- [🔑depfui♻️]: https://badges.depfu.com/badges/6d34dc1ba682bbdf9ae2a97848241743/count.svg
799
- [🖐codeQL]: https://github.com/oauth-xx/oauth2/security/code-scanning
800
- [🖐codeQL-img]: https://github.com/oauth-xx/oauth2/actions/workflows/codeql-analysis.yml/badge.svg
801
- [🚎1-an-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/ancient.yml
802
- [🚎1-an-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/ancient.yml/badge.svg
803
- [🚎2-cov-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/coverage.yml
804
- [🚎2-cov-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/coverage.yml/badge.svg
805
- [🚎3-hd-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/heads.yml
806
- [🚎3-hd-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/heads.yml/badge.svg
807
- [🚎4-lg-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/legacy.yml
808
- [🚎4-lg-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/legacy.yml/badge.svg
809
- [🚎5-st-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/style.yml
810
- [🚎5-st-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/style.yml/badge.svg
811
- [🚎6-s-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/supported.yml
812
- [🚎6-s-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/supported.yml/badge.svg
813
- [🚎7-us-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/unsupported.yml
814
- [🚎7-us-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/unsupported.yml/badge.svg
815
- [🚎8-ho-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/hoary.yml
816
- [🚎8-ho-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/hoary.yml/badge.svg
817
- [🚎9-t-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/truffle.yml
818
- [🚎9-t-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/truffle.yml/badge.svg
819
- [🚎10-j-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/jruby.yml
820
- [🚎10-j-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/jruby.yml/badge.svg
821
- [🚎11-c-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/current.yml
822
- [🚎11-c-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/current.yml/badge.svg
823
- [🚎12-crh-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/current-runtime-heads.yml
824
- [🚎12-crh-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/current-runtime-heads.yml/badge.svg
825
- [🚎13-cbs-wf]: https://github.com/oauth-xx/oauth2/actions/workflows/caboose.yml
826
- [🚎13-cbs-wfi]: https://github.com/oauth-xx/oauth2/actions/workflows/caboose.yml/badge.svg
827
- [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay
828
- [⛳liberapay]: https://liberapay.com/pboling/donate
829
- [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
830
- [🖇sponsor]: https://github.com/sponsors/pboling
831
- [🖇polar-img]: https://img.shields.io/badge/polar-donate-yellow.svg
832
- [🖇polar]: https://polar.sh/pboling
833
- [🖇kofi-img]: https://img.shields.io/badge/a_more_different_coffee-✓-yellow.svg
834
- [🖇kofi]: https://ko-fi.com/O5O86SNP4
835
- [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-yellow.svg
836
- [🖇patreon]: https://patreon.com/galtzo
837
- [🖇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
838
- [🖇buyme]: https://www.buymeacoffee.com/pboling
839
- [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-yellow.svg?style=flat
1113
+ [🔑qlty-mnt]: https://qlty.sh/gh/ruby-oauth/projects/oauth2
1114
+ [🔑qlty-mnti]: https://qlty.sh/gh/ruby-oauth/projects/oauth2/maintainability.svg
1115
+ [🔑qlty-cov]: https://qlty.sh/gh/ruby-oauth/projects/oauth2/metrics/code?sort=coverageRating
1116
+ [🔑qlty-covi]: https://qlty.sh/gh/ruby-oauth/projects/oauth2/coverage.svg
1117
+ [🔑codecov]: https://codecov.io/gh/ruby-oauth/oauth2
1118
+ [🔑codecovi]: https://codecov.io/gh/ruby-oauth/oauth2/graph/badge.svg
1119
+ [🔑coveralls]: https://coveralls.io/github/ruby-oauth/oauth2?branch=main
1120
+ [🔑coveralls-img]: https://coveralls.io/repos/github/ruby-oauth/oauth2/badge.svg?branch=main
1121
+ [🖐codeQL]: https://github.com/ruby-oauth/oauth2/security/code-scanning
1122
+ [🖐codeQL-img]: https://github.com/ruby-oauth/oauth2/actions/workflows/codeql-analysis.yml/badge.svg
1123
+ [🚎1-an-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/ancient.yml
1124
+ [🚎1-an-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/ancient.yml/badge.svg
1125
+ [🚎2-cov-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/coverage.yml
1126
+ [🚎2-cov-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/coverage.yml/badge.svg
1127
+ [🚎3-hd-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/heads.yml
1128
+ [🚎3-hd-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/heads.yml/badge.svg
1129
+ [🚎4-lg-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/legacy.yml
1130
+ [🚎4-lg-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/legacy.yml/badge.svg
1131
+ [🚎5-st-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/style.yml
1132
+ [🚎5-st-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/style.yml/badge.svg
1133
+ [🚎6-s-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/supported.yml
1134
+ [🚎6-s-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/supported.yml/badge.svg
1135
+ [🚎7-us-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/unsupported.yml
1136
+ [🚎7-us-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/unsupported.yml/badge.svg
1137
+ [🚎8-ho-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/hoary.yml
1138
+ [🚎8-ho-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/hoary.yml/badge.svg
1139
+ [🚎9-t-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/truffle.yml
1140
+ [🚎9-t-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/truffle.yml/badge.svg
1141
+ [🚎10-j-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/jruby.yml
1142
+ [🚎10-j-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/jruby.yml/badge.svg
1143
+ [🚎11-c-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/current.yml
1144
+ [🚎11-c-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/current.yml/badge.svg
1145
+ [🚎12-crh-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/current-runtime-heads.yml
1146
+ [🚎12-crh-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/current-runtime-heads.yml/badge.svg
1147
+ [🚎13-cbs-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/caboose.yml
1148
+ [🚎13-cbs-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/caboose.yml/badge.svg
1149
+ [🚎13-🔒️-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/locked_deps.yml
1150
+ [🚎13-🔒️-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/locked_deps.yml/badge.svg
1151
+ [🚎14-🔓️-wf]: https://github.com/ruby-oauth/oauth2/actions/workflows/unlocked_deps.yml
1152
+ [🚎14-🔓️-wfi]: https://github.com/ruby-oauth/oauth2/actions/workflows/unlocked_deps.yml/badge.svg
1153
+ [💎ruby-2.2i]: https://img.shields.io/badge/Ruby-2.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white
840
1154
  [💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
841
1155
  [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
842
1156
  [💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
@@ -848,30 +1162,30 @@ or one of the others at the head of this README.
848
1162
  [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white
849
1163
  [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
850
1164
  [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue
851
- [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
852
- [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
1165
+ [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink
1166
+ [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink
853
1167
  [💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
854
1168
  [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green
855
1169
  [💎truby-headi]: https://img.shields.io/badge/Truffle_Ruby-HEAD-34BCB1?style=for-the-badge&logo=ruby&logoColor=blue
856
- [💎jruby-9.1i]: https://img.shields.io/badge/JRuby-9.1-FBE742?style=for-the-badge&logo=ruby&logoColor=red
857
- [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2-FBE742?style=for-the-badge&logo=ruby&logoColor=red
858
- [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red
1170
+ [💎jruby-9.1i]: https://img.shields.io/badge/JRuby-9.1_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red
1171
+ [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red
1172
+ [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red
859
1173
  [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red
860
1174
  [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green
861
1175
  [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue
862
- [🤝gh-issues]: https://github.com/oauth-xx/oauth2/issues
863
- [🤝gh-pulls]: https://github.com/oauth-xx/oauth2/pulls
864
- [🤝gl-issues]: https://gitlab.com/oauth-xx/oauth2/-/issues
865
- [🤝gl-pulls]: https://gitlab.com/oauth-xx/oauth2/-/merge_requests
866
- [🤝cb-issues]: https://codeberg.org/oauth-xx/oauth2/issues
867
- [🤝cb-pulls]: https://codeberg.org/oauth-xx/oauth2/pulls
1176
+ [🤝gh-issues]: https://github.com/ruby-oauth/oauth2/issues
1177
+ [🤝gh-pulls]: https://github.com/ruby-oauth/oauth2/pulls
1178
+ [🤝gl-issues]: https://gitlab.com/ruby-oauth/oauth2/-/issues
1179
+ [🤝gl-pulls]: https://gitlab.com/ruby-oauth/oauth2/-/merge_requests
1180
+ [🤝cb-issues]: https://codeberg.org/ruby-oauth/oauth2/issues
1181
+ [🤝cb-pulls]: https://codeberg.org/ruby-oauth/oauth2/pulls
868
1182
  [🤝cb-donate]: https://donate.codeberg.org/
869
1183
  [🤝contributing]: CONTRIBUTING.md
870
- [🔑codecov-g♻️]: https://codecov.io/gh/oauth-xx/oauth2/graphs/tree.svg?token=bNqSzNiuo2
1184
+ [🔑codecov-g]: https://codecov.io/gh/ruby-oauth/oauth2/graphs/tree.svg
871
1185
  [🖐contrib-rocks]: https://contrib.rocks
872
- [🖐contributors]: https://github.com/oauth-xx/oauth2/graphs/contributors
873
- [🖐contributors-img]: https://contrib.rocks/image?repo=oauth-xx/oauth2
874
- [🚎contributors-gl]: https://gitlab.com/oauth-xx/oauth2/-/graphs/main
1186
+ [🖐contributors]: https://github.com/ruby-oauth/oauth2/graphs/contributors
1187
+ [🖐contributors-img]: https://contrib.rocks/image?repo=ruby-oauth/oauth2
1188
+ [🚎contributors-gl]: https://gitlab.com/ruby-oauth/oauth2/-/graphs/main
875
1189
  [🪇conduct]: CODE_OF_CONDUCT.md
876
1190
  [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
877
1191
  [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
@@ -885,7 +1199,7 @@ or one of the others at the head of this README.
885
1199
  [📌gitmoji]:https://gitmoji.dev
886
1200
  [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square
887
1201
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
888
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.518-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1202
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.519-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
889
1203
  [🔐security]: SECURITY.md
890
1204
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
891
1205
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -896,13 +1210,13 @@ or one of the others at the head of this README.
896
1210
  [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
897
1211
  [🚎yard-current]: http://rubydoc.info/gems/oauth2
898
1212
  [🚎yard-head]: https://oauth2.galtzo.com
899
- [💎stone_checksums]: https://github.com/pboling/stone_checksums
900
- [💎SHA_checksums]: https://gitlab.com/oauth-xx/oauth2/-/tree/main/checksums
1213
+ [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
1214
+ [💎SHA_checksums]: https://gitlab.com/ruby-oauth/oauth2/-/tree/main/checksums
901
1215
  [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
902
1216
  [💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
1217
+ [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
1218
+ [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
903
1219
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
904
- [✉️discord-invite]: https://discord.gg/3qme4XHNKN
905
- [✉️discord-invite-img]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge
906
1220
 
907
1221
  <details>
908
1222
  <summary>
@@ -911,15 +1225,14 @@ or one of the others at the head of this README.
911
1225
 
912
1226
  <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>
913
1227
  <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>
914
- </details>
915
1228
 
916
- <details>
917
- <summary>Deprecated Badges</summary>
1229
+ </details>
918
1230
 
919
- CodeCov currently fails to parse the coverage upload.
920
1231
 
921
- [![CodeCov Test Coverage][🔑codecovi♻️]][🔑codecov]
1232
+ <details>
1233
+ <summary>Broken badges</summary>
922
1234
 
923
- [![Coverage Graph][🔑codecov-g♻️]][🔑codecov]
1235
+ [![Coverage Graph][🔑codecov-g]][🔑codecov]
1236
+ [![CodeCov Test Coverage][🔑codecovi]][🔑codecov]
924
1237
 
925
- </details>
1238
+ </details>