diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock
index 77253f0f..9e178ebe 100644
--- a/.rubocop_gradual.lock
+++ b/.rubocop_gradual.lock
@@ -6,7 +6,7 @@
"lib/oauth2.rb:2435263975": [
[73, 11, 7, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 651502127]
],
- "lib/oauth2/access_token.rb:558937598": [
+ "lib/oauth2/access_token.rb:1775225572": [
[64, 13, 5, "Style/IdenticalConditionalBranches: Move `t_key` out of the conditional.", 183811513],
[70, 13, 5, "Style/IdenticalConditionalBranches: Move `t_key` out of the conditional.", 183811513]
],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6ebafb3..7c36d47d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,19 @@
# Changelog
All notable changes to this project will be documented in this file.
-The format (since v2) is based on [Keep a Changelog v1](https://keepachangelog.com/en/1.0.0/),
-and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2.0.0.html).
+The format (since v2) is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- improved documentation by @pboling
+- documentation notes in code comments and README highlighting OAuth 2.1 differences, with references, such as:
+ - PKCE required for auth code,
+ - exact redirect URI match,
+ - implicit/password grants omitted,
+ - avoid bearer tokens in query,
+ - refresh token guidance for public clients,
+ - simplified client definitions)
### Changed
### Deprecated
### Removed
diff --git a/README.md b/README.md
index 3b54066f..56365fa0 100644
--- a/README.md
+++ b/README.md
@@ -692,6 +692,22 @@ Response instance will contain the `OAuth2::Error` instance.
### Authorization Grants
+Note on OAuth 2.1 (draft):
+- 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.
+- Redirect URIs must be compared using exact string matching by the Authorization Server.
+- 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.
+- Bearer tokens in the query string are omitted due to security risks; prefer Authorization header usage.
+- Refresh tokens for public clients must either be sender-constrained (e.g., DPoP/MTLS) or one-time use.
+- The definitions of public and confidential clients are simplified to refer only to whether the client has credentials.
+
+References:
+- OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
+- Aaron Parecki: https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1
+- FusionAuth: https://fusionauth.io/blog/2020/04/15/whats-new-in-oauth-2-1
+- Okta: https://developer.okta.com/blog/2019/12/13/oauth-2-1-how-many-rfcs
+- Video: https://www.youtube.com/watch?v=g_aVPdwBTfw
+- Differences overview: https://fusionauth.io/learn/expert-advice/oauth/differences-between-oauth-2-oauth-2-1/
+
Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
authentication grant types have helper strategy classes that simplify client
use. They are available via the [`#auth_code`](https://gitlab.com/ruby-oauth/oauth2/-/blob/main/lib/oauth2/strategy/auth_code.rb),
diff --git a/docs/OAuth2.html b/docs/OAuth2.html
index 794f4356..f147de49 100644
--- a/docs/OAuth2.html
+++ b/docs/OAuth2.html
@@ -415,7 +415,7 @@
PKCE is required for all OAuth clients using the authorization code flow (especially public clients).
+This library does not enforce PKCE generation/verification; implement PKCE in your application when required.
+
Redirect URIs must be compared using exact string matching by the Authorization Server.
+This client forwards redirect_uri but does not perform server-side validation.
IMPORTANT (OAuth 2.1): The Implicit grant (response_type=token) is omitted from the OAuth 2.1 draft specification.
+It remains here for backward compatibility with OAuth 2.0 providers. Prefer the Authorization Code flow with PKCE.
# File 'lib/oauth2/strategy/implicit.rb', line 12
+
# File 'lib/oauth2/strategy/implicit.rb', line 20defauthorize_params(params={})params.merge("response_type"=>"token","client_id"=>@client.id)
@@ -335,13 +345,13 @@
-19
-20
-21
-22
+27
+28
+29
+30
-
# File 'lib/oauth2/strategy/implicit.rb', line 19
+
# File 'lib/oauth2/strategy/implicit.rb', line 27defauthorize_url(params={})assert_valid_params(params)
@@ -390,12 +400,12 @@
-27
-28
-29
+35
+36
+37
-
# File 'lib/oauth2/strategy/implicit.rb', line 27
+
# File 'lib/oauth2/strategy/implicit.rb', line 35defget_token(*)raise(NotImplementedError,"The token is accessed differently in this strategy")
@@ -410,7 +420,7 @@
The Resource Owner Password Credentials Authorization Strategy
+
IMPORTANT (OAuth 2.1): The Resource Owner Password Credentials grant is omitted in OAuth 2.1.
+It remains here for backward compatibility with OAuth 2.0 providers. Prefer Authorization Code + PKCE.
# File 'lib/oauth2/strategy/password.rb', line 12
+
# File 'lib/oauth2/strategy/password.rb', line 20defauthorize_urlraise(NotImplementedError,"The authorization endpoint is not used in this strategy")
@@ -334,17 +344,17 @@
-21
-22
-23
-24
-25
-26
-27
-28
+29
+30
+31
+32
+33
+34
+35
+36
-
# File 'lib/oauth2/strategy/password.rb', line 21
+
# File 'lib/oauth2/strategy/password.rb', line 29defget_token(username,password,params={},opts={})params={
@@ -364,7 +374,7 @@
Another Way to Support Open
diff --git a/docs/file.LICENSE.html b/docs/file.LICENSE.html
index 6c799800..d1165879 100644
--- a/docs/file.LICENSE.html
+++ b/docs/file.LICENSE.html
@@ -60,7 +60,7 @@
MIT License
Copyright (c) 2017-2025 Peter H. Boling, of Galtzo.com, and oauth2 contributors Copyright (c) 2011-2013 Michael Bleigh and Intridea, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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.
+
Redirect URIs must be compared using exact string matching by the Authorization Server.
+
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.
+
Bearer tokens in the query string are omitted due to security risks; prefer Authorization header usage.
+
Refresh tokens for public clients must either be sender-constrained (e.g., DPoP/MTLS) or one-time use.
+
The definitions of public and confidential clients are simplified to refer only to whether the client has credentials.
Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
authentication grant types have helper strategy classes that simplify client
use. They are available via the #auth_code,
@@ -1160,7 +1180,7 @@
🔐 Security
🤝 Contributing
If you need some ideas of where to help, you could work on adding more code coverage,
-or if it is already 💯 (see below) check reek, issues, or PRs,
+or if it is already 💯 (see below) check reek, issues, or PRs,
or use the gem and think about how it could be better.
We so if you make changes, remember to update it.
@@ -1306,7 +1326,7 @@
Please give the project a star ⭐ ♥
diff --git a/docs/file.REEK.html b/docs/file.REEK.html
index 137dfca2..57f29476 100644
--- a/docs/file.REEK.html
+++ b/docs/file.REEK.html
@@ -61,7 +61,7 @@
diff --git a/docs/file.RUBOCOP.html b/docs/file.RUBOCOP.html
index 62540ff2..4ac6b96e 100644
--- a/docs/file.RUBOCOP.html
+++ b/docs/file.RUBOCOP.html
@@ -161,7 +161,7 @@
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.
+
Redirect URIs must be compared using exact string matching by the Authorization Server.
+
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.
+
Bearer tokens in the query string are omitted due to security risks; prefer Authorization header usage.
+
Refresh tokens for public clients must either be sender-constrained (e.g., DPoP/MTLS) or one-time use.
+
The definitions of public and confidential clients are simplified to refer only to whether the client has credentials.
Currently, the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion
authentication grant types have helper strategy classes that simplify client
use. They are available via the #auth_code,
@@ -1160,7 +1180,7 @@
🔐 Security
🤝 Contributing
If you need some ideas of where to help, you could work on adding more code coverage,
-or if it is already 💯 (see below) check reek, issues, or PRs,
+or if it is already 💯 (see below) check reek, issues, or PRs,
or use the gem and think about how it could be better.
We so if you make changes, remember to update it.
@@ -1306,7 +1326,7 @@
Please give the project a star ⭐ ♥
diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html
index 785e5eb9..2c7379c1 100644
--- a/docs/top-level-namespace.html
+++ b/docs/top-level-namespace.html
@@ -100,7 +100,7 @@
Defined Under Namespace
diff --git a/lib/oauth2/access_token.rb b/lib/oauth2/access_token.rb
index c5607392..57b95b10 100644
--- a/lib/oauth2/access_token.rb
+++ b/lib/oauth2/access_token.rb
@@ -376,6 +376,8 @@ def configure_authentication!(opts)
opts[:headers] ||= {}
opts[:headers].merge!(headers)
when :query
+ # OAuth 2.1 note: Bearer tokens in the query string are omitted from the spec due to security risks.
+ # Prefer the default :header mode whenever possible.
opts[:params] ||= {}
opts[:params][options[:param_name]] = token
when :body
diff --git a/lib/oauth2/client.rb b/lib/oauth2/client.rb
index 193e95c4..7c64c3c1 100644
--- a/lib/oauth2/client.rb
+++ b/lib/oauth2/client.rb
@@ -321,6 +321,9 @@ def assertion
# requesting authorization. If it is provided at authorization time it MUST
# also be provided with the token exchange request.
#
+ # OAuth 2.1 note: Authorization Servers must compare redirect URIs using exact string matching.
+ # This client simply forwards the configured redirect_uri; the exact-match validation happens server-side.
+ #
# Providing :redirect_uri to the OAuth2::Client instantiation will take
# care of managing this.
#
@@ -330,6 +333,7 @@ def assertion
# @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
# @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.1
# @see https://datatracker.ietf.org/doc/html/rfc6749#section-10.6
+ # @see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
#
# @return [Hash] the params to add to a request or URL
def redirection_params
diff --git a/lib/oauth2/strategy/auth_code.rb b/lib/oauth2/strategy/auth_code.rb
index 96eedf5d..ff909a37 100644
--- a/lib/oauth2/strategy/auth_code.rb
+++ b/lib/oauth2/strategy/auth_code.rb
@@ -4,6 +4,16 @@ module OAuth2
module Strategy
# The Authorization Code Strategy
#
+ # OAuth 2.1 notes:
+ # - PKCE is required for all OAuth clients using the authorization code flow (especially public clients).
+ # This library does not enforce PKCE generation/verification; implement PKCE in your application when required.
+ # - Redirect URIs must be compared using exact string matching by the Authorization Server.
+ # This client forwards redirect_uri but does not perform server-side validation.
+ #
+ # References:
+ # - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
+ # - OAuth for native apps (RFC 8252) and PKCE (RFC 7636)
+ #
# @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.1
class AuthCode < Base
# The required query parameters for the authorize URL
diff --git a/lib/oauth2/strategy/implicit.rb b/lib/oauth2/strategy/implicit.rb
index e9efe5c2..8dfd0a64 100644
--- a/lib/oauth2/strategy/implicit.rb
+++ b/lib/oauth2/strategy/implicit.rb
@@ -4,6 +4,14 @@ module OAuth2
module Strategy
# The Implicit Strategy
#
+ # IMPORTANT (OAuth 2.1): The Implicit grant (response_type=token) is omitted from the OAuth 2.1 draft specification.
+ # It remains here for backward compatibility with OAuth 2.0 providers. Prefer the Authorization Code flow with PKCE.
+ #
+ # References:
+ # - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
+ # - Why drop implicit: https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1
+ # - Background: https://fusionauth.io/learn/expert-advice/oauth/differences-between-oauth-2-oauth-2-1/
+ #
# @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2
class Implicit < Base
# The required query parameters for the authorize URL
diff --git a/lib/oauth2/strategy/password.rb b/lib/oauth2/strategy/password.rb
index 79acf654..9621e684 100644
--- a/lib/oauth2/strategy/password.rb
+++ b/lib/oauth2/strategy/password.rb
@@ -4,6 +4,14 @@ module OAuth2
module Strategy
# The Resource Owner Password Credentials Authorization Strategy
#
+ # IMPORTANT (OAuth 2.1): The Resource Owner Password Credentials grant is omitted in OAuth 2.1.
+ # It remains here for backward compatibility with OAuth 2.0 providers. Prefer Authorization Code + PKCE.
+ #
+ # References:
+ # - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
+ # - Okta explainer: https://developer.okta.com/blog/2019/12/13/oauth-2-1-how-many-rfcs
+ # - FusionAuth blog: https://fusionauth.io/blog/2020/04/15/whats-new-in-oauth-2-1
+ #
# @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.3
class Password < Base
# Not used for this strategy