diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 6c2fc8dd..81583536 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,7 +1,4 @@ { - "README.md:620392337": [ - [305, 3, 1, "Layout/ClosingParenthesisIndentation: Indent `)` to column 0 (not 2)", 177548] - ], "bin/bundle:3976421676": [ [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147], [78, 5, 74, "Style/InvertibleUnlessCondition: Prefer `if Gem.rubygems_version >= Gem::Version.new(\"2.7.0\")` over `unless Gem.rubygems_version < Gem::Version.new(\"2.7.0\")`.", 2453573257] diff --git a/CHANGELOG.md b/CHANGELOG.md index cf322133..1ca76b1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,13 +12,16 @@ and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2. ## [2.0.10] - 2025-05-12 ([tag][2.0.10t]) ### Added -[!635](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/635) - `.gitlab-ci.yml` file (@jessieay) -- 20 year certificate for signing gem releases, expires 2045-04-29 (@pboling) -- Gemspec metadata (@pboling) - - funding_uri - - news_uri - - mailing_list_uri -- SHA256 and SHA512 Checksums for release (@pboling) +- [!635](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/635) - `.gitlab-ci.yml` file (@jessieay) +- [!643](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/643) - Add token_name option (@pboling) + - Specify the parameter name that identifies the access token +- [!642](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/642) - 20 year certificate for signing gem releases, expires 2045-04-29 (@pboling) + - Gemspec metadata (@pboling) + - funding_uri + - news_uri + - mailing_list_uri + - SHA256 and SHA512 Checksums for release (@pboling) +- [#638](https://gitlab.com/oauth-xx/oauth2/-/issues/638) - Documentation of support for ILO Fundamental Principles of Rights at Work ### Changed - Gem releases are now cryptographically signed, with a 20-year cert (@pboling) - Allow linux distros to build release without signing, as their package managers sign independently @@ -29,6 +32,10 @@ and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2. [!639](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/639) - Only instantiate `OAuth2::Error` if `raise_errors` option is `true` (@glytch2) [!640](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/640) - `README.md` documentation fix (@martinezcoder) [!641](https://gitlab.com/oauth-xx/oauth2/-/merge_requests/641) - Do not include sensitive information in the `inspect` (@manuelvanrijn) +[#645](https://gitlab.com/oauth-xx/oauth2/-/issues/645) - Response no longer becomes a snaky hash (@pboling) +[#639](https://gitlab.com/oauth-xx/oauth2/-/issues/639) - AccessToken#to_hash is now serializable, just a regular Hash (@pboling) +[#95](https://gitlab.com/oauth-xx/oauth2/-/issues/95) - restoring an access token via `AccessToken#from_hash` (@pboling) + - This was a 13 year old bug report. 😘 ## [2.0.9] - 2022-09-16 ([tag][2.0.9t]) ### Added diff --git a/README.md b/README.md index 831cd55f..377b1ec1 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,34 @@ OAuth 2.0 focuses on client developer simplicity while providing specific author desktop applications, mobile phones, and living room devices. This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications. +Quick example: Convert the following `curl` command into a token request using this gem... + +```shell +curl --request POST \ + --url 'https://login.microsoftonline.com/REDMOND_REDACTED/oauth2/token' \ + --header 'content-type: application/x-www-form-urlencoded' \ + --data grant_type=client_credentials \ + --data client_id=REDMOND_CLIENT_ID \ + --data client_secret=REDMOND_CLIENT_SECRET \ + --data resource=REDMOND_RESOURCE_UUID +``` + +NOTE: In the ruby version, certain params go in the get_token call, rather than in the client creation. + +```ruby +OAuth2::Client.new( + "REDMOND_CLIENT_ID", # client_id + "REDMOND_CLIENT_SECRET", # client_secret + auth_scheme: :request_body, # Other modes are supported: :basic_auth, :tls_client_auth, :private_key_jwt + token_url: "oauth2/token", # relative path, except with leading `/`, then absolute path + site: "https://login.microsoftonline.com/REDMOND_REDACTED", +). # The base path for token_url when it is relative + client_credentials. # There are many other types to choose from! + get_token(resource: "REDMOND_RESOURCE_UUID") +``` + +NOTE: `header` - The content type specified in the `curl` is already the default! + ## 💡 Info you can shake a stick at * [OAuth 2.0 Spec][oauth2-spec] @@ -265,6 +293,19 @@ OAuth2.configure do |config| end ``` +This comes from ambiguity in the spec about which token is the right token. +Some OAuth 2.0 standards legitimately have multiple tokens. +You may need to subclass `OAuth2::AccessToken`, or write your own custom alternative to it, and pass it in. +Specify your custom class with the `access_token_class` option. + +If you only need one token you can, as of v2.0.10, +specify the exact token name you want to extract via the `OAuth2::AccessToken` using +the `token_name` option. + +You'll likely need to do some source diving. +This gem has 100% test coverage for lines and branches, so the specs are a great place to look for ideas. +If you have time and energy please contribute to the documentation! + ### `authorize_url` and `token_url` are on site root (Just Works!) ```ruby @@ -302,7 +343,7 @@ client = OAuth2::Client.new( site: "https://example.org/nested/directory/on/your/server", authorize_url: "/jaunty/authorize/", token_url: "/stirrups/access_token", - ) +) # => # "https://example.org/jaunty/authorize/?client_id=client_id&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth2%2Fcallback&response_type=code" diff --git a/lib/oauth2/client.rb b/lib/oauth2/client.rb index 88fb97fe..c0f1f2a6 100644 --- a/lib/oauth2/client.rb +++ b/lib/oauth2/client.rb @@ -36,7 +36,7 @@ class Client # rubocop:disable Metrics/ClassLength # @option options [String] :authorize_url ('/oauth/authorize') absolute or relative URL path to the Authorization endpoint # @option options [String] :token_url ('/oauth/token') absolute or relative URL path to the Token endpoint # @option options [Symbol] :token_method (:post) HTTP method to use to request token (:get, :post, :post_with_query_string) - # @option options [Symbol] :auth_scheme (:basic_auth) the authentication scheme (:basic_auth or :request_body) + # @option options [Symbol] :auth_scheme (:basic_auth) the authentication scheme (:basic_auth, :request_body, :tls_client_auth, :private_key_jwt) # @option options [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday # @option options [Boolean] :raise_errors (true) whether to raise an OAuth2::Error on responses with 400+ status codes # @option options [Integer] :max_redirects (5) maximum number of redirects to follow