Skip to content

Commit d81a98b

Browse files
authored
Merge pull request #699 from ruby-oauth/feat/docs
Feat/docs
2 parents b055461 + d04aa72 commit d81a98b

43 files changed

Lines changed: 329 additions & 231 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2017-2025 Peter H. Boling, of Galtzo.com, and oauth2 contributors
3+
Copyright (c) 2017-2026 Peter H. Boling, of Galtzo.com, and oauth2 contributors
44
Copyright (c) 2011-2013 Michael Bleigh and Intridea, Inc.
55

66
Permission is hereby granted, free of charge, to any person obtaining a copy

README.md

Lines changed: 72 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
# 🔐 OAuth 2.0 Authorization Framework
1111

12-
⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
13-
1412
[![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
1513

1614
`if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
@@ -31,10 +29,10 @@ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-ta
3129
## 🌻 Synopsis
3230

3331
OAuth 2.0 is the industry-standard protocol for authorization.
34-
OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications,
35-
desktop applications, mobile phones, and living room devices.
3632
This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications.
3733

34+
⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
35+
3836
### Quick Examples
3937

4038
<details markdown="1">
@@ -53,13 +51,14 @@ curl --request POST \
5351
NOTE: In the ruby version below, certain params are passed to the `get_token` call, instead of the client creation.
5452

5553
```ruby
56-
OAuth2::Client.new(
54+
client = OAuth2::Client.new(
5755
"REDMOND_CLIENT_ID", # client_id
5856
"REDMOND_CLIENT_SECRET", # client_secret
5957
auth_scheme: :request_body, # Other modes are supported: :basic_auth, :tls_client_auth, :private_key_jwt
6058
token_url: "oauth2/token", # relative path, except with leading `/`, then absolute path
6159
site: "https://login.microsoftonline.com/REDMOND_REDACTED",
62-
). # The base path for token_url when it is relative
60+
)
61+
client.
6362
client_credentials. # There are many other types to choose from!
6463
get_token(resource: "REDMOND_RESOURCE_UUID")
6564
```
@@ -322,32 +321,30 @@ See [SECURITY.md][🔐security] and [IRP.md][🔐irp].
322321

323322
## ⚙️ Configuration
324323

325-
You can turn on additional warnings.
324+
Global settings for the library:
326325

327326
```ruby
328327
OAuth2.configure do |config|
329-
# Turn on a warning like:
330-
# OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key
331328
config.silence_extra_tokens_warning = false # default: true
332-
# Set to true if you want to also show warnings about no tokens
333-
config.silence_no_tokens_warning = false # default: true,
329+
config.silence_no_tokens_warning = false # default: true
334330
end
335331
```
336332

337-
The "extra tokens" problem comes from ambiguity in the spec about which token is the right token.
338-
Some OAuth 2.0 standards legitimately have multiple tokens.
339-
You may need to subclass `OAuth2::AccessToken`, or write your own custom alternative to it, and pass it in.
340-
Specify your custom class with the `access_token_class` option.
333+
## 🔧 Basic Usage
341334

342-
If you only need one token, you can, as of v2.0.10,
343-
specify the exact token name you want to extract via the `OAuth2::AccessToken` using
344-
the `token_name` option.
335+
### Client Initialization Options
345336

346-
You'll likely need to do some source diving.
347-
This gem has 100% test coverage for lines and branches, so the specs are a great place to look for ideas.
348-
If you have time and energy, please contribute to the documentation!
337+
`OAuth2::Client.new` accepts several options:
349338

350-
## 🔧 Basic Usage
339+
- `:site`: The base URL for the OAuth 2.0 provider.
340+
- `:authorize_url`: The authorization endpoint (default: `"oauth/authorize"`).
341+
- `:token_url`: The token endpoint (default: `"oauth/token"`).
342+
- `:auth_scheme`: The authentication scheme (`:basic_auth`, `:request_body`, `:tls_client_auth`, `:private_key_jwt`). Default is `:basic_auth`.
343+
- `:connection_opts`: Options for the underlying Faraday connection (timeouts, proxy, etc.).
344+
- `:raise_errors`: Whether to raise `OAuth2::Error` on 400+ responses (default: `true`).
345+
346+
<details markdown="1">
347+
<summary><em>authorize_url</em> and <em>token_url</em></summary>
351348

352349
### `authorize_url` and `token_url` are on site root (Just Works!)
353350

@@ -394,6 +391,25 @@ client.class.name
394391
# => OAuth2::Client
395392
```
396393

394+
</details>
395+
396+
### Advanced Initializers
397+
398+
```ruby
399+
client = OAuth2::Client.new(id, secret, site: site) do |faraday|
400+
faraday.request(:url_encoded)
401+
faraday.adapter(:net_http_persistent)
402+
end
403+
```
404+
405+
### AccessToken Features
406+
407+
Instances of `OAuth2::AccessToken` handle request signing and token expiration.
408+
409+
- **Snake Case & Indifferent Access**: `response.parsed` returns a `SnakyHash` allowing access via string/symbol and snake_case keys even if the provider returns CamelCase.
410+
- **Auto-Refresh**: You can manually check `token.expired?` and call `token.refresh`.
411+
- **Serialization**: Persist tokens using `token.to_hash` and restore via `OAuth2::AccessToken.from_hash(client, hash)`.
412+
397413
### snake_case and indifferent access in Response#parsed
398414

399415
```ruby
@@ -546,12 +562,12 @@ client = OAuth2::Client.new(
546562
### OAuth2::Response
547563

548564
The `AccessToken` methods `#get`, `#post`, `#put` and `#delete` and the generic `#request`
549-
will return an instance of the #OAuth2::Response class.
565+
will return an instance of the `OAuth2::Response` class.
550566

551567
This instance contains a `#parsed` method that will parse the response body and
552568
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
553-
the body is a JSON object. It will return an Array if the body is a JSON
554-
array. Otherwise, it will return the original body string.
569+
the body is a JSON object. It will return an Array if the body is a JSON
570+
array. Otherwise, it will return the original body string.
555571

556572
The original response body, headers, and status can be accessed via their
557573
respective methods.
@@ -593,16 +609,22 @@ Response instance will contain the `OAuth2::Error` instance.
593609

594610
### Authorization Grants
595611

596-
Note on OAuth 2.1 (draft):
612+
Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
613+
authentication grant types have helper strategy classes that simplify client
614+
use. They are available via the [`#auth_code`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
615+
[`#implicit`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
616+
[`#password`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/password.rb),
617+
[`#client_credentials`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/client_credentials.rb), and
618+
[`#assertion`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/assertion.rb) methods respectively.
597619

598-
- PKCE is required for all OAuth clients using the authorization code flow (especially public clients). Implement PKCE in your app when required by your provider. See RFC 7636 and RFC 8252.
599-
- Redirect URIs must be compared using exact string matching by the Authorization Server.
600-
- The Implicit grant (response_type=token) and the Resource Owner Password Credentials grant are omitted from OAuth 2.1; they remain here for OAuth 2.0 compatibility but should be avoided for new apps.
601-
- Bearer tokens in the query string are omitted due to security risks; prefer Authorization header usage.
602-
- Refresh tokens for public clients must either be sender-constrained (e.g., DPoP/MTLS) or one-time use.
603-
- The definitions of public and confidential clients are simplified to refer only to whether the client has credentials.
620+
#### OAuth 2.1 (draft) Note:
604621

605-
References:
622+
- **PKCE** is required for all OAuth clients using the authorization code flow (especially public clients). Implement PKCE in your app when required by your provider. See RFC 7636 and RFC 8252.
623+
- **Implicit grant** (response_type=token) and **Resource Owner Password Credentials grant** are omitted from OAuth 2.1; they remain here for OAuth 2.0 compatibility but should be avoided for new apps.
624+
- **Redirect URIs** must be compared using exact string matching by the Authorization Server.
625+
626+
<details markdown="1">
627+
<summary>OAuth 2.1 (draft) References</summary>
606628

607629
- OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
608630
- Aaron Parecki: https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1
@@ -611,13 +633,7 @@ References:
611633
- Video: https://www.youtube.com/watch?v=g_aVPdwBTfw
612634
- Differences overview: https://fusionauth.io/learn/expert-advice/oauth/differences-between-oauth-2-oauth-2-1/
613635

614-
Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
615-
authentication grant types have helper strategy classes that simplify client
616-
use. They are available via the [`#auth_code`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
617-
[`#implicit`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/implicit.rb),
618-
[`#password`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/password.rb),
619-
[`#client_credentials`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/client_credentials.rb), and
620-
[`#assertion`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/assertion.rb) methods respectively.
636+
</details>
621637

622638
These aren't full examples, but demonstrative of the differences between usage for each strategy.
623639

@@ -752,7 +768,7 @@ Notes:
752768

753769
</details>
754770

755-
### Instagram API (verb‑dependent token mode)
771+
### Verb‑dependent Token Mode
756772

757773
Providers like Instagram require the access token to be sent differently depending on the HTTP verb:
758774

@@ -761,6 +777,14 @@ Providers like Instagram require the access token to be sent differently dependi
761777

762778
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.
763779

780+
Tips:
781+
782+
- Avoid query‑string bearer tokens unless required by your provider. Instagram explicitly requires it for `GET` requests.
783+
- If you need a custom rule, you can pass a `Proc` for `mode`, e.g. `mode: ->(verb) { verb == :get ? :query : :header }`.
784+
785+
<details markdown="1">
786+
<summary>Instagram API Example</summary>
787+
764788
Example: exchanging and refreshing long‑lived Instagram tokens, and making API calls
765789

766790
```ruby
@@ -819,10 +843,7 @@ me = long_lived.get("/me", params: {fields: "id,username"}).parsed
819843
# long_lived.post("/me/media", body: {image_url: "https://...", caption: "hello"})
820844
```
821845

822-
Tips:
823-
824-
- Avoid query‑string bearer tokens unless required by your provider. Instagram explicitly requires it for `GET` requests.
825-
- If you need a custom rule, you can pass a `Proc` for `mode`, e.g. `mode: ->(verb) { verb == :get ? :query : :header }`.
846+
</details>
826847

827848
### Refresh Tokens
828849

@@ -1063,11 +1084,12 @@ access = client.get_token({
10631084
})
10641085
```
10651086

1066-
### OpenID Connect (OIDC) Notes
1087+
### OpenID Connect (OIDC)
10671088

1068-
- 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.
1069-
- For private_key_jwt client authentication, provide `auth_scheme: :private_key_jwt` and ensure your key configuration matches the provider requirements.
1070-
- See [OIDC.md](OIDC.md) for a more complete OIDC overview, example, and links to the relevant specifications.
1089+
- If the token response includes an `id_token` (a JWT), this gem surfaces it in `token.params['id_token']`.
1090+
- **Note**: This gem does **not** validate the signature of the `id_token`. You must use a JWT library (like the `jwt` [gem](https://github.com/jwt/ruby-jwt)) and your provider's JWKs to verify it.
1091+
- For `private_key_jwt` client authentication, provide `auth_scheme: :private_key_jwt` and ensure your key configuration matches the provider requirements.
1092+
- See [OIDC.md](OIDC.md) for a more complete OIDC overview and examples.
10711093

10721094
### Debugging
10731095

@@ -1239,7 +1261,7 @@ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright
12391261

12401262
<ul>
12411263
<li>
1242-
Copyright (c) 2017 – 2025 Peter H. Boling, of
1264+
Copyright (c) 2017 – 2026 Peter H. Boling, of
12431265
<a href="https://discord.gg/3qme4XHNKN">
12441266
Galtzo.com
12451267
<picture>

docs/OAuth2.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ <h3 class="signature " id="configure-class_method">
373373
</div>
374374

375375
<div id="footer">
376-
Generated on Sun Mar 1 00:56:52 2026 by
376+
Generated on Sun Mar 1 02:08:24 2026 by
377377
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
378378
0.9.38 (ruby-4.0.1).
379379
</div>

docs/OAuth2/AccessToken.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3077,7 +3077,7 @@ <h3 class="signature " id="to_hash-instance_method">
30773077
</div>
30783078

30793079
<div id="footer">
3080-
Generated on Sun Mar 1 00:56:53 2026 by
3080+
Generated on Sun Mar 1 02:08:25 2026 by
30813081
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
30823082
0.9.38 (ruby-4.0.1).
30833083
</div>

docs/OAuth2/Authenticator.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ <h3 class="signature first" id="apply-instance_method">
883883
</div>
884884

885885
<div id="footer">
886-
Generated on Sun Mar 1 00:56:53 2026 by
886+
Generated on Sun Mar 1 02:08:25 2026 by
887887
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
888888
0.9.38 (ruby-4.0.1).
889889
</div>

docs/OAuth2/Client.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2656,7 +2656,7 @@ <h3 class="signature " id="token_url-instance_method">
26562656
</div>
26572657

26582658
<div id="footer">
2659-
Generated on Sun Mar 1 00:56:53 2026 by
2659+
Generated on Sun Mar 1 02:08:24 2026 by
26602660
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
26612661
0.9.38 (ruby-4.0.1).
26622662
</div>

docs/OAuth2/Error.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ <h3 class="signature " id="response-instance_method">
772772
</div>
773773

774774
<div id="footer">
775-
Generated on Sun Mar 1 00:56:53 2026 by
775+
Generated on Sun Mar 1 02:08:24 2026 by
776776
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
777777
0.9.38 (ruby-4.0.1).
778778
</div>

docs/OAuth2/FilteredAttributes.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ <h3 class="signature first" id="inspect-instance_method">
335335
</div>
336336

337337
<div id="footer">
338-
Generated on Sun Mar 1 00:56:53 2026 by
338+
Generated on Sun Mar 1 02:08:24 2026 by
339339
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
340340
0.9.38 (ruby-4.0.1).
341341
</div>

docs/OAuth2/FilteredAttributes/ClassMethods.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ <h3 class="signature " id="filtered_attributes-instance_method">
472472
</div>
473473

474474
<div id="footer">
475-
Generated on Sun Mar 1 00:56:53 2026 by
475+
Generated on Sun Mar 1 02:08:24 2026 by
476476
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
477477
0.9.38 (ruby-4.0.1).
478478
</div>

docs/OAuth2/Response.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,7 @@ <h3 class="signature " id="status-instance_method">
16191619
</div>
16201620

16211621
<div id="footer">
1622-
Generated on Sun Mar 1 00:56:53 2026 by
1622+
Generated on Sun Mar 1 02:08:25 2026 by
16231623
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
16241624
0.9.38 (ruby-4.0.1).
16251625
</div>

0 commit comments

Comments
 (0)