├── REEK ├── docs ├── OAuth2.html ├── _index.html ├── frames.html ├── OAuth2 │ ├── Error.html │ ├── Strategy.html │ ├── Authenticator.html │ ├── Strategy │ │ ├── Base.html │ │ ├── Assertion.html │ │ ├── AuthCode.html │ │ ├── Implicit.html │ │ ├── Password.html │ │ └── ClientCredentials.html │ ├── FilteredAttributes.html │ └── Version.html ├── file.CITATION.html ├── file.FUNDING.html ├── file.LICENSE.html ├── file.OIDC.html ├── file.REEK.html ├── file.RUBOCOP.html ├── file.SECURITY.html ├── file.client.html ├── file.error.html ├── file.response.html ├── file.strategy.html ├── file.version.html ├── method_list.html ├── CNAME ├── file.CHANGELOG.html ├── file.CONTRIBUTING.html ├── file.THREAT_MODEL.html ├── file.access_token.html ├── file.authenticator.html ├── file.CODE_OF_CONDUCT.html ├── file.oauth2-2.0.10.gem.html ├── file.oauth2-2.0.11.gem.html ├── file.oauth2-2.0.12.gem.html ├── file.oauth2-2.0.14.gem.html ├── file.oauth2-2.0.15.gem.html ├── file.oauth2-2.0.16.gem.html ├── file.oauth2-2.0.17.gem.html ├── top-level-namespace.html ├── file.filtered_attributes.html ├── css │ └── common.css ├── file.oauth2-2.0.13.gem.html └── file.oauth2.html ├── CNAME ├── .jrubyrc ├── .tool-versions ├── spec ├── config │ ├── constants.rb │ ├── multi_xml.rb │ ├── faraday.rb │ └── debug.rb ├── fixtures │ ├── google_service_account_key.p12 │ ├── README.md │ └── RS256 │ │ ├── jwtRS256.key.pub │ │ └── jwtRS256.key ├── ext │ └── backports.rb ├── oauth2 │ ├── strategy │ │ ├── base_spec.rb │ │ ├── implicit_spec.rb │ │ ├── password_spec.rb │ │ └── client_credentials_spec.rb │ └── version_spec.rb ├── spec_helper.rb └── oauth2_spec.rb ├── gemfiles ├── modular │ ├── erb │ │ ├── r2 │ │ │ └── v3.0.gemfile │ │ ├── r3 │ │ │ └── v5.0.gemfile │ │ ├── r3.1 │ │ │ └── v4.0.gemfile │ │ ├── vHEAD.gemfile │ │ ├── r2.6 │ │ │ └── v2.2.gemfile │ │ ├── r2.4 │ │ │ └── v2.2.gemfile │ │ └── r2.3 │ │ │ └── default.gemfile │ ├── mutex_m │ │ ├── r2 │ │ │ └── v0.3.gemfile │ │ ├── r3 │ │ │ └── v0.3.gemfile │ │ ├── r2.4 │ │ │ └── v0.1.gemfile │ │ └── vHEAD.gemfile │ ├── x_std_libs.gemfile │ ├── jwt_v2.gemfile │ ├── jwt_v3.gemfile │ ├── stringio │ │ ├── vHEAD.gemfile │ │ ├── r2.4 │ │ │ └── v0.0.2.gemfile │ │ ├── r2 │ │ │ └── v3.0.gemfile │ │ └── r3 │ │ │ └── v3.0.gemfile │ ├── faraday_v2.gemfile │ ├── hashie_v0.gemfile │ ├── hashie_v1.gemfile │ ├── hashie_v2.gemfile │ ├── hashie_v3.gemfile │ ├── hashie_v4.gemfile │ ├── rack_v3.gemfile │ ├── faraday_v1.gemfile │ ├── hashie_v5.gemfile │ ├── optional.gemfile │ ├── x_std_libs │ │ ├── vHEAD.gemfile │ │ ├── r2 │ │ │ └── libs.gemfile │ │ ├── r3 │ │ │ └── libs.gemfile │ │ ├── r2.6 │ │ │ └── libs.gemfile │ │ ├── r3.1 │ │ │ └── libs.gemfile │ │ ├── r2.4 │ │ │ └── libs.gemfile │ │ └── r2.3 │ │ │ └── libs.gemfile │ ├── logger_v1_7.gemfile │ ├── jwt_v1.gemfile │ ├── multi_xml_v0_7.gemfile │ ├── audit.gemfile │ ├── coverage.gemfile │ ├── rack_v2.gemfile │ ├── logger_v1_5.gemfile │ ├── rack_v1_2.gemfile │ ├── rack_v1_6.gemfile │ ├── multi_xml_v0_5.gemfile │ ├── logger_v1_2.gemfile │ ├── latest.gemfile │ ├── multi_xml_v0_6.gemfile │ ├── faraday_v0.gemfile │ ├── debug.gemfile │ ├── documentation.gemfile │ ├── runtime_heads.gemfile │ ├── style.gemfile │ └── injected.gemfile ├── vanilla.gemfile ├── current.gemfile ├── dep_heads.gemfile ├── style.gemfile ├── head.gemfile ├── current_runtime_heads.gemfile ├── unlocked_deps.gemfile ├── ruby_2_7.gemfile ├── ruby_3_2.gemfile ├── ruby_3_3.gemfile ├── ruby_2_4.gemfile ├── ruby_2_5.gemfile ├── ruby_2_6.gemfile ├── ruby_3_0.gemfile ├── ruby_3_1.gemfile ├── ruby_2_3_hashie_v0.gemfile ├── ruby_2_3_hashie_v1.gemfile ├── ruby_2_3_hashie_v2.gemfile ├── ruby_2_3_hashie_v3.gemfile ├── ruby_2_3_hashie_v4.gemfile ├── ruby_2_3_hashie_v5.gemfile ├── audit.gemfile ├── coverage.gemfile └── omnibus.gemfile ├── checksums ├── oauth2-2.0.10.gem.sha256 ├── oauth2-2.0.11.gem.sha256 ├── oauth2-2.0.12.gem.sha256 ├── oauth2-2.0.13.gem.sha256 ├── oauth2-2.0.14.gem.sha256 ├── oauth2-2.0.15.gem.sha256 ├── oauth2-2.0.16.gem.sha256 ├── oauth2-2.0.17.gem.sha256 ├── oauth2-2.0.18.gem.sha256 ├── oauth2-2.0.10.gem.sha512 ├── oauth2-2.0.11.gem.sha512 ├── oauth2-2.0.12.gem.sha512 ├── oauth2-2.0.13.gem.sha512 ├── oauth2-2.0.14.gem.sha512 ├── oauth2-2.0.15.gem.sha512 ├── oauth2-2.0.16.gem.sha512 ├── oauth2-2.0.17.gem.sha512 └── oauth2-2.0.18.gem.sha512 ├── sig ├── oauth2 │ ├── version.rbs │ ├── filtered_attributes.rbs │ ├── error.rbs │ ├── response.rbs │ ├── authenticator.rbs │ ├── strategy.rbs │ ├── access_token.rbs │ └── client.rbs └── oauth2.rbs ├── .licenserc.yaml ├── lib ├── oauth2 │ ├── version.rb │ ├── strategy │ │ ├── base.rb │ │ ├── client_credentials.rb │ │ ├── password.rb │ │ ├── implicit.rb │ │ └── auth_code.rb │ ├── filtered_attributes.rb │ └── error.rb └── oauth2.rb ├── bin ├── setup ├── erb ├── pry ├── rbs ├── kramdown ├── nokogiri ├── appraisal ├── console ├── kettle-dvcs ├── kettle-release ├── kettle-changelog ├── kettle-dev-setup ├── kettle-commit-msg ├── kettle-pre-release ├── kettle-readme-backers ├── irb ├── rake ├── ri ├── yri ├── racc ├── rdbg ├── rdoc ├── reek ├── rspec ├── thor ├── yard ├── ldiff ├── rubocop ├── yardoc ├── coderay ├── htmldiff ├── redcarpet ├── ruby-parse ├── standardrb ├── yard-junk ├── ruby-rewrite ├── bundle-audit ├── bundler-audit ├── github-markup ├── code_climate_reek ├── gem_checksums ├── rubocop-gradual └── bundle ├── .opencollective.yml ├── .idea ├── misc.xml ├── kubernetes-settings.xml ├── copilot.data.migration.agent.xml ├── copilot.data.migration.ask.xml ├── copilot.data.migration.edit.xml ├── GitLink.xml ├── copilot.data.migration.ask2agent.xml ├── modules.xml ├── GitlabSettingsPlugin.xml ├── .gitignore ├── git_toolbox_blame.xml ├── csv-editor.xml ├── active-tab-highlighter.xml ├── vcs.xml ├── git_toolbox_prj.xml └── codestream.xml ├── .rspec ├── .git-hooks ├── prepare-commit-msg ├── commit-subjects-goalie.txt ├── footer-template.erb.txt └── commit-msg ├── .yardopts ├── .aiignore ├── .github ├── dependabot.yml ├── workflows │ ├── auto-assign.yml │ ├── dependency-review.yml │ ├── license-eye.yml │ ├── opencollective.yml │ ├── style.yml │ ├── windows.yml │ ├── jruby.yml │ ├── codeql-analysis.yml │ ├── legacy.yml │ ├── supported.yml │ ├── unsupported.yml │ ├── ancient.yml │ ├── locked_deps.yml │ ├── macos.yml │ └── unlocked_deps.yml ├── FUNDING.yml └── disabled-workflows │ ├── discord-notifier.yml │ └── danger.yml ├── .simplecov ├── docker-compose-ssl.yml ├── Appraisal.root.gemfile ├── config-ssl.json ├── CITATION.cff ├── Dangerfile ├── .rubocop_rspec.yml ├── SECURITY.md ├── .gitignore ├── Gemfile ├── .devcontainer └── devcontainer.json ├── LICENSE.txt ├── .overcommit.yml ├── .env.local.example ├── .qlty └── qlty.toml ├── certs └── pboling.pem ├── .junie └── guidelines-rbs.md ├── .envrc ├── .rubocop.yml ├── THREAT_MODEL.md ├── RUBOCOP.md └── Rakefile /REEK: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/frames.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | oauth2.galtzo.com -------------------------------------------------------------------------------- /docs/OAuth2/Error.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.CITATION.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.FUNDING.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.LICENSE.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.OIDC.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.REEK.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.RUBOCOP.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.SECURITY.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.client.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.error.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.response.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.strategy.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.version.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/method_list.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | oauth2.galtzo.com -------------------------------------------------------------------------------- /docs/OAuth2/Strategy.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.CHANGELOG.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.CONTRIBUTING.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.THREAT_MODEL.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.access_token.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.authenticator.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.jrubyrc: -------------------------------------------------------------------------------- 1 | debug.fullTrace=true 2 | -------------------------------------------------------------------------------- /docs/OAuth2/Authenticator.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/Strategy/Base.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.CODE_OF_CONDUCT.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.10.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.11.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.12.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.14.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.15.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.16.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.17.gem.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/top-level-namespace.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/FilteredAttributes.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/Strategy/Assertion.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/Strategy/AuthCode.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/Strategy/Implicit.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/Strategy/Password.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/file.filtered_attributes.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/OAuth2/Strategy/ClientCredentials.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | direnv 2.32.2 2 | ruby 3.4.7 3 | -------------------------------------------------------------------------------- /docs/css/common.css: -------------------------------------------------------------------------------- 1 | /* Override this file with custom rules */ -------------------------------------------------------------------------------- /spec/config/constants.rb: -------------------------------------------------------------------------------- 1 | VERBS = %i[get post put delete patch].freeze 2 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/r2/v3.0.gemfile: -------------------------------------------------------------------------------- 1 | gem "erb", "~> 3.0" # ruby >= 2.7.0 2 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/r3/v5.0.gemfile: -------------------------------------------------------------------------------- 1 | gem "erb", "~> 5.0" # ruby >= 3.2.0 2 | -------------------------------------------------------------------------------- /gemfiles/modular/mutex_m/r2/v0.3.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 2.5 2 | gem "mutex_m", "~> 0.2" 3 | -------------------------------------------------------------------------------- /gemfiles/modular/mutex_m/r3/v0.3.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 2.5 2 | gem "mutex_m", "~> 0.2" 3 | -------------------------------------------------------------------------------- /checksums/oauth2-2.0.10.gem.sha256: -------------------------------------------------------------------------------- 1 | 8f132679598d21885d4bcc68d7e7e6ef0a29f9a782abca00d67d884280dc3a42 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.11.gem.sha256: -------------------------------------------------------------------------------- 1 | 29e0505c2a39bc78dfb655dbf85a826b4408e55e7c3d02ce07b3dfd9b40da16c -------------------------------------------------------------------------------- /checksums/oauth2-2.0.12.gem.sha256: -------------------------------------------------------------------------------- 1 | f7edb8549c7912724d07087d808c3fa6756298fd64d55d4968324df69c64ab3f -------------------------------------------------------------------------------- /checksums/oauth2-2.0.13.gem.sha256: -------------------------------------------------------------------------------- 1 | e6588fe5902c07bac542a4a1197f558c319cb479b7fbe53f43f883b1a211be25 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.14.gem.sha256: -------------------------------------------------------------------------------- 1 | 9bcb7983048cb1ea1823f9b973762cf01ac79315d9991a0721e864747293e720 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.15.gem.sha256: -------------------------------------------------------------------------------- 1 | 96ce2ca86cd06e80b0452e17c5bc0a1e349815d29c875a7951cdd8ff04743eab -------------------------------------------------------------------------------- /checksums/oauth2-2.0.16.gem.sha256: -------------------------------------------------------------------------------- 1 | b45ce8b22e4c198ad372d6ba99134633a83c35aae365addbead0db27948f4294 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.17.gem.sha256: -------------------------------------------------------------------------------- 1 | c4e182aeabc06dfdafce9a15095c30edc3a1a21fc3c4f0ea49d9295429e79835 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.18.gem.sha256: -------------------------------------------------------------------------------- 1 | bacf11e470dfb963f17348666d0a75c7b29ca65bc48fd47be9057cf91a403287 -------------------------------------------------------------------------------- /sig/oauth2/version.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | module Version 3 | VERSION: String 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs.gemfile: -------------------------------------------------------------------------------- 1 | ### Std Lib Extracted Gems 2 | eval_gemfile "x_std_libs/r3/libs.gemfile" 3 | -------------------------------------------------------------------------------- /.licenserc.yaml: -------------------------------------------------------------------------------- 1 | header: 2 | license: 3 | spdx-id: MIT 4 | 5 | dependency: 6 | files: 7 | - Gemfile.lock 8 | -------------------------------------------------------------------------------- /spec/config/multi_xml.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "multi_xml" 4 | 5 | MultiXml.parser = :rexml 6 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/r3.1/v4.0.gemfile: -------------------------------------------------------------------------------- 1 | # last version compatible with Ruby 3.1 2 | gem "erb", "~> 4.0" # ruby >= 2.7.0 3 | -------------------------------------------------------------------------------- /gemfiles/modular/jwt_v2.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.5 4 | gem "jwt", "~> 2.10", ">= 2.10.1" 5 | -------------------------------------------------------------------------------- /gemfiles/modular/jwt_v3.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.5 4 | gem "jwt", ">= 3.0.0.beta1", "< 4" 5 | -------------------------------------------------------------------------------- /gemfiles/modular/mutex_m/r2.4/v0.1.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 0 2 | # Last version supporting Ruby <= 2.4 3 | gem "mutex_m", "~> 0.1" 4 | -------------------------------------------------------------------------------- /spec/config/faraday.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "faraday" 4 | 5 | Faraday.default_adapter = :test 6 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/vHEAD.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 3.2 (dependency of kettle-dev) 2 | gem "erb", github: "ruby/erb", branch: "master" 3 | -------------------------------------------------------------------------------- /gemfiles/vanilla.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://rubygems.org" 4 | 5 | gemspec path: "../" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/mutex_m/vHEAD.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 2.5 (dependency of omniauth) 2 | gem "mutex_m", github: "ruby/mutex_m", branch: "master" 3 | -------------------------------------------------------------------------------- /spec/fixtures/google_service_account_key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-oauth/oauth2/HEAD/spec/fixtures/google_service_account_key.p12 -------------------------------------------------------------------------------- /gemfiles/modular/stringio/vHEAD.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 2.5 (dependency of omniauth) 2 | gem "stringio", github: "ruby/stringio", branch: "master" 3 | -------------------------------------------------------------------------------- /lib/oauth2/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | module Version 5 | VERSION = "2.0.18" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/modular/stringio/r2.4/v0.0.2.gemfile: -------------------------------------------------------------------------------- 1 | # !!WARNING!! 2 | # NOT SEMVER 3 | # Last version to support Ruby <= 2.5 4 | gem "stringio", ">= 0.0.2" 5 | -------------------------------------------------------------------------------- /checksums/oauth2-2.0.10.gem.sha512: -------------------------------------------------------------------------------- 1 | e692f68ab79677ee7fa9300bbd5e0c41de08642d51659a49ca7fd742230445601ad3c2d271ee110718d58a27383aba0c25ddbdbef5b13f7c18585cdfda74850b -------------------------------------------------------------------------------- /checksums/oauth2-2.0.11.gem.sha512: -------------------------------------------------------------------------------- 1 | 048743f9efd89460231738885c9c0de7b36433055eefc66331b91eee343885cd9145bbac239c6121d13b716633fb8385fa886ce854bf14142f9894e6c8f19ba2 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.12.gem.sha512: -------------------------------------------------------------------------------- 1 | a209c7a0c4b9d46ccb00e750af8899c01d52648ca77a0d40b934593de53edc4f2774440fc50733c0e5098672c6c5a4a20f8709046be427fcf032f45922dff2d2 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.13.gem.sha512: -------------------------------------------------------------------------------- 1 | 3bfe481d98f859f37f3b90ced2b8856a843eef0f2e0263163cccc14430047bc3cd03d28597f48daa3d623b52d692c3b3e7c2dc26df5eb588dd82d28608fba639 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.14.gem.sha512: -------------------------------------------------------------------------------- 1 | 5ce561a6b103a123d9b96e1e4725c07094bd6e58c135cc775ae9d5a055c031169ca6d6de379c2569daf1dd8ab2727079db3c80aa8568d6947e94a0c06b4c6d2b -------------------------------------------------------------------------------- /checksums/oauth2-2.0.15.gem.sha512: -------------------------------------------------------------------------------- 1 | 287a5d2cff87b4f37dde7b97f0fc31ee4c79edcc451b33694d1ba6f13d218cd04848780a857b94b93b656d6d81de4f4fcb4e8345f432cee17a6d96bd3f313df2 -------------------------------------------------------------------------------- /checksums/oauth2-2.0.16.gem.sha512: -------------------------------------------------------------------------------- 1 | 49788bf25c3afcc08171f92c3c8a21b4bcd322aae0834f69ae77c08963f54be6c9155588ca66f82022af897ddd0bf28b0c5ee254bc9fe533d1a37b1d52f409be -------------------------------------------------------------------------------- /checksums/oauth2-2.0.17.gem.sha512: -------------------------------------------------------------------------------- 1 | 6385dfb2d4cb0309745de2d442d99c6148744abaca5599bd1e4f6038e99734d9cf90d1de83d1833e416e2682f0e3d6ae83e10a5a55d6e884b9cdc54e6070fb8b -------------------------------------------------------------------------------- /checksums/oauth2-2.0.18.gem.sha512: -------------------------------------------------------------------------------- 1 | 1db20c4bfe395f45e01ee2fbdcd4922aff6480c8071af404b324d4f5b6582b476359bf9bbcf38cd3537f26d15d413d31de4ea9c7e1b215bb0cf8a623a0d2e44e -------------------------------------------------------------------------------- /spec/ext/backports.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "backports/2.5.0/hash/transform_keys" 4 | require "backports/2.5.0/string/delete_prefix" 5 | -------------------------------------------------------------------------------- /gemfiles/modular/faraday_v2.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # last version that will install on Ruby 2.6 & 2.7 4 | gem "faraday", "~> 2.8", ">=2.8.1" 5 | -------------------------------------------------------------------------------- /gemfiles/modular/hashie_v0.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.3. 5 | gem "hashie", "~> 0.4", ">= 0.4.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/hashie_v1.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.4. 5 | gem "hashie", "~> 1.2", ">= 1.2.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/hashie_v2.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.5. 5 | gem "hashie", "~> 2.1", ">= 2.1.2" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/hashie_v3.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.6. 5 | gem "hashie", "~> 3.6", ">= 3.6.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/hashie_v4.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.7. 5 | gem "hashie", "~> 4.1", ">= 4.1.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/rack_v3.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.4 4 | # We will test it against Ruby 2.6+. 5 | gem "rack", "~> 3.1", ">= 3.1.14" 6 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /gemfiles/modular/faraday_v1.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Last version compatible with Ruby 2.4, and 2.5 4 | gem "faraday", "~> 1.10", ">= 1.10.4" 5 | -------------------------------------------------------------------------------- /gemfiles/modular/hashie_v5.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 3.0+. 5 | gem "hashie", "~> 5.0", ">= 5.0.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/optional.gemfile: -------------------------------------------------------------------------------- 1 | # Optional dependencies are not depended on directly, but may be used if present. 2 | gem "addressable", ">= 2.8", "< 3" # ruby >= 2.2 3 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/vHEAD.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../erb/vHEAD.gemfile" 2 | eval_gemfile "../mutex_m/vHEAD.gemfile" 3 | eval_gemfile "../stringio/vHEAD.gemfile" 4 | -------------------------------------------------------------------------------- /.opencollective.yml: -------------------------------------------------------------------------------- 1 | collective: "ruby-oauth" 2 | readme-backers-commit-subject: "💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜" 3 | readme-osc-tag: "OPENCOLLECTIVE" 4 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/r2.6/v2.2.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 2.3.0 (claimed, but not true, minimum support is Ruby 2.4) 2 | # Last version supporting Ruby <= 2.6 3 | gem "erb", "~> 2.2.2" 4 | -------------------------------------------------------------------------------- /gemfiles/current.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/x_std_libs.gemfile") 8 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/r2/libs.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../../erb/r2/v3.0.gemfile" 2 | eval_gemfile "../../mutex_m/r2/v0.3.gemfile" 3 | eval_gemfile "../../stringio/r2/v3.0.gemfile" 4 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/r3/libs.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../../erb/r3/v5.0.gemfile" 2 | eval_gemfile "../../mutex_m/r3/v0.3.gemfile" 3 | eval_gemfile "../../stringio/r3/v3.0.gemfile" 4 | -------------------------------------------------------------------------------- /gemfiles/dep_heads.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/runtime_heads.gemfile") 8 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/r2.6/libs.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../../erb/r2.6/v2.2.gemfile" 2 | eval_gemfile "../../mutex_m/r2/v0.3.gemfile" 3 | eval_gemfile "../../stringio/r2/v3.0.gemfile" 4 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/r3.1/libs.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../../erb/r3.1/v4.0.gemfile" 2 | eval_gemfile "../../mutex_m/r3/v0.3.gemfile" 3 | eval_gemfile "../../stringio/r3/v3.0.gemfile" 4 | -------------------------------------------------------------------------------- /gemfiles/modular/logger_v1_7.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.5 4 | # We will test it against Ruby 2.7, 3.0, 3.1, 3.2, 3.3, 3.4. 5 | gem "logger", "~> 1.7", ">= 1.7.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/r2.4/libs.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../../erb/r2.4/v2.2.gemfile" 2 | eval_gemfile "../../mutex_m/r2.4/v0.1.gemfile" 3 | eval_gemfile "../../stringio/r2.4/v0.0.2.gemfile" 4 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /gemfiles/modular/x_std_libs/r2.3/libs.gemfile: -------------------------------------------------------------------------------- 1 | eval_gemfile "../../erb/r2.3/default.gemfile" 2 | eval_gemfile "../../mutex_m/r2.4/v0.1.gemfile" 3 | eval_gemfile "../../stringio/r2.4/v0.0.2.gemfile" 4 | -------------------------------------------------------------------------------- /sig/oauth2/filtered_attributes.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | module FilteredAttributes 3 | def self.included: (untyped) -> untyped 4 | def filtered_attributes: (*String) -> void 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/config/debug.rb: -------------------------------------------------------------------------------- 1 | load_debugger = ENV.fetch("DEBUG", "false").casecmp("true") == 0 2 | 3 | puts "LOADING DEBUGGER: #{load_debugger}" if load_debugger 4 | 5 | require "debug" if load_debugger 6 | -------------------------------------------------------------------------------- /gemfiles/modular/jwt_v1.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # This version of jwt is the last compatible with Ruby 1.9, 2.0, 2.1, 2.2, 2.3, 2.4: 5 | gem "jwt", "~> 1.5", ">= 1.5.6" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/multi_xml_v0_7.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.5 4 | # We will test it against Ruby 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4. 5 | gem "multi_xml", "~> 0.7", ">= 0.7.2" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/stringio/r2/v3.0.gemfile: -------------------------------------------------------------------------------- 1 | # !!WARNING!! 2 | # NOT SEMVER 3 | # Version 3.0.7 dropped support for Ruby <= 2.7 4 | # Version 3.0.0 dropped support for Ruby <= 2.4 5 | gem "stringio", ">= 3.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/stringio/r3/v3.0.gemfile: -------------------------------------------------------------------------------- 1 | # !!WARNING!! 2 | # NOT SEMVER 3 | # Version 3.0.7 dropped support for Ruby <= 2.7 4 | # Version 3.0.0 dropped support for Ruby <= 2.4 5 | gem "stringio", ">= 3.0" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/audit.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Many gems are dropping support for Ruby < 3, 4 | # so we only want to run our security audit in CI on Ruby 3+ 5 | gem "bundler-audit", "~> 0.9.2" 6 | -------------------------------------------------------------------------------- /gemfiles/modular/coverage.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # We run code coverage on the latest version of Ruby only. 4 | 5 | # Coverage 6 | gem "kettle-soup-cover", "~> 1.0", ">= 1.0.10", require: false 7 | -------------------------------------------------------------------------------- /.idea/kubernetes-settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format progress 2 | --color 3 | --order random 4 | --require spec_helper 5 | --warnings 6 | --format html 7 | --out results/test_results.html 8 | --format RspecJunitFormatter 9 | --out results/test_results.xml 10 | -------------------------------------------------------------------------------- /gemfiles/modular/rack_v2.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.3 4 | # This version of rack is the last compatible with Ruby 2.3. 5 | # We will test it against Ruby 2.5. 6 | gem "rack", "~> 2.2", ">= 2.2.14" 7 | -------------------------------------------------------------------------------- /sig/oauth2.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | OAUTH_DEBUG: bool 3 | 4 | DEFAULT_CONFIG: untyped 5 | @config: untyped 6 | 7 | def self.config: () -> untyped 8 | def self.configure: () { (untyped) -> void } -> void 9 | end 10 | -------------------------------------------------------------------------------- /gemfiles/modular/logger_v1_5.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.3 4 | # This version of logger is the last compatible with Ruby 2.3, 2.4: 5 | # We will test it against 2.5, and 2.6. 6 | gem "logger", "~> 1.5.3" 7 | -------------------------------------------------------------------------------- /gemfiles/modular/rack_v1_2.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.3. 5 | # This minor version of rack is the oldest compatible with this gem: 6 | gem "rack", "~> 1.2", ">= 1.2.8" 7 | -------------------------------------------------------------------------------- /gemfiles/modular/rack_v1_6.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # This is the newest version of rack that installs on Ruby < 2.2.2. 5 | # We will test it against Ruby 2.4. 6 | gem "rack", "~> 1.6", ">= 1.6.13" 7 | -------------------------------------------------------------------------------- /gemfiles/style.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/style.gemfile") 8 | 9 | eval_gemfile("modular/x_std_libs.gemfile") 10 | -------------------------------------------------------------------------------- /lib/oauth2/strategy/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | module Strategy 5 | class Base 6 | def initialize(client) 7 | @client = client 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /.idea/copilot.data.migration.agent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/copilot.data.migration.ask.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/copilot.data.migration.edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/GitLink.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/copilot.data.migration.ask2agent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /gemfiles/modular/multi_xml_v0_5.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.3, 2.4 5 | # This minor version of multi_xml is the oldest compatible with this gem: 6 | gem "multi_xml", "~> 0.5", ">= 0.5.5" 7 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/r2.4/v2.2.gemfile: -------------------------------------------------------------------------------- 1 | # Ruby >= 2.3.0 (claimed, but not true, minimum support is Ruby 2.4) 2 | # Last version supporting Ruby <= 2.6 3 | gem "erb", "~> 2.2.2" 4 | 5 | # Pin CGI to a version compatible with Ruby 2.4. 6 | gem "cgi", "~> 0.1.1" 7 | -------------------------------------------------------------------------------- /gemfiles/head.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gem "cgi", ">= 0.5" 6 | gem "benchmark", "~> 0.4", ">= 0.4.1" 7 | 8 | gemspec path: "../" 9 | 10 | eval_gemfile("modular/runtime_heads.gemfile") 11 | -------------------------------------------------------------------------------- /gemfiles/modular/logger_v1_2.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 2.3 4 | # This version of logger is the last compatible with Ruby 1.8. 1.9, 2.0, 2.1, 2.2: 5 | # We will test it against 2.3, and 2.4. 6 | gem "logger", "~> 1.2.8", ">= 1.2.8.1" 7 | -------------------------------------------------------------------------------- /spec/oauth2/strategy/base_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe OAuth2::Strategy::Base do 4 | it "initializes with a Client" do 5 | expect { described_class.new(OAuth2::Client.new("abc", "def")) }.not_to raise_error 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/current_runtime_heads.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "mutex_m", ">= 0.2" 6 | gem "stringio", ">= 3.0" 7 | 8 | gemspec path: "../" 9 | 10 | eval_gemfile("modular/runtime_heads.gemfile") 11 | -------------------------------------------------------------------------------- /sig/oauth2/error.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | class Error < StandardError 3 | def initialize: (OAuth2::Response) -> void 4 | def code: () -> (String | Integer | nil) 5 | def description: () -> (String | nil) 6 | def response: () -> OAuth2::Response 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /.git-hooks/prepare-commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Fail on error and unset variables 4 | set -eu 5 | 6 | # We are not using direnv exec here because mise and direnv can result in conflicting PATH settings: 7 | # See: https://mise.jdx.dev/direnv.html 8 | exec "kettle-commit-msg" "$@" 9 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --plugin fence 2 | -e yard/fence/hoist.rb 3 | --plugin junk 4 | --plugin relative_markdown_links 5 | --readme tmp/yard-fence/README.md 6 | --charset utf-8 7 | --markup markdown 8 | --output docs 9 | 'lib/**/*.rb' 10 | - 11 | 'tmp/yard-fence/*.md' 12 | 'tmp/yard-fence/*.txt' 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /gemfiles/modular/latest.gemfile: -------------------------------------------------------------------------------- 1 | gem "mutex_m", ">= 0.2" 2 | gem "stringio", ">= 3.0" 3 | eval_gemfile "faraday_v2.gemfile" 4 | eval_gemfile "hashie_v5.gemfile" 5 | eval_gemfile "jwt_v3.gemfile" 6 | eval_gemfile "logger_v1_7.gemfile" 7 | eval_gemfile "multi_xml_v0_7.gemfile" 8 | eval_gemfile "rack_v3.gemfile" 9 | -------------------------------------------------------------------------------- /gemfiles/modular/multi_xml_v0_6.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 0 4 | # We will test it against Ruby 2.5, 2.6, 2.7, 3.0, 3.1. 5 | # This version of multi_xml is the last compatible with Ruby 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0: 6 | gem "multi_xml", "~> 0.6", ">= 0.6.0" 7 | -------------------------------------------------------------------------------- /spec/oauth2/version_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe OAuth2::Version do 4 | it_behaves_like "a Version module", described_class 5 | 6 | it "is greater than 1.0.0" do 7 | expect(Gem::Version.new(described_class) >= Gem::Version.new("1.0.0")).to(be(true)) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/fixtures/README.md: -------------------------------------------------------------------------------- 1 | # RS256 2 | 3 | ## How keys were made 4 | 5 | ```shell 6 | # No passphrase 7 | # Generates the public and private keys: 8 | ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key 9 | # Converts the key to PEM format 10 | openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub 11 | ``` 12 | -------------------------------------------------------------------------------- /gemfiles/modular/faraday_v0.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ruby >= 1.9 4 | # 0.17.3 is the first version to not use &Proc.new when forwarding blocks. 5 | # Thus, it is the oldest version oauth2 is compatible with. 6 | # This version of faraday is the last compatible with Ruby 1.9, 2.0, 2.1, 2.2, and 2.3: 7 | gem "faraday", "~> 0.17.6" 8 | -------------------------------------------------------------------------------- /.idea/GitlabSettingsPlugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.aiignore: -------------------------------------------------------------------------------- 1 | # An .aiignore file follows the same syntax as a .gitignore file. 2 | # .gitignore documentation: https://git-scm.com/docs/gitignore 3 | 4 | # you can ignore files 5 | .DS_Store 6 | *.log 7 | *.tmp 8 | 9 | # or folders 10 | .devcontainer/ 11 | .qlty/ 12 | .yardoc/ 13 | dist/ 14 | build/ 15 | out/ 16 | coverage/ 17 | docs/ 18 | pkg/ 19 | results/ 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | open-pull-requests-limit: 5 8 | ignore: 9 | - dependency-name: "rubocop-lts" 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "weekly" 14 | -------------------------------------------------------------------------------- /.simplecov: -------------------------------------------------------------------------------- 1 | require "kettle/soup/cover/config" 2 | 3 | # Minimum coverage thresholds are set by kettle-soup-cover. 4 | # It is controlled by ENV variables, which are set in .envrc and loaded via `direnv allow` 5 | # If the values for minimum coverage need to change, they should be changed both there, 6 | # and in 2 places in .github/workflows/coverage.yml. 7 | SimpleCov.start 8 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | 10 | # Zencoder local files 11 | /zencoder/chats 12 | /zencoder-chat-index.xml 13 | /zencoder-chats-dedicated.xml 14 | # Local project config 15 | *.iml 16 | -------------------------------------------------------------------------------- /docker-compose-ssl.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mock-oauth2-server: 3 | image: ghcr.io/navikt/mock-oauth2-server:2.3.0 4 | restart: unless-stopped 5 | ports: 6 | - "8080:8080" 7 | volumes: 8 | - ./config-ssl.json:/app/config.json:Z 9 | environment: 10 | LOG_LEVEL: "debug" 11 | SERVER_PORT: 8080 12 | JSON_CONFIG_PATH: /app/config.json 13 | -------------------------------------------------------------------------------- /gemfiles/unlocked_deps.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/coverage.gemfile") 8 | 9 | eval_gemfile("modular/documentation.gemfile") 10 | 11 | eval_gemfile("modular/style.gemfile") 12 | 13 | eval_gemfile("modular/optional.gemfile") 14 | 15 | eval_gemfile("modular/x_std_libs.gemfile") 16 | -------------------------------------------------------------------------------- /.idea/git_toolbox_blame.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /bin/erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'erb' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("erb", "erb") 17 | -------------------------------------------------------------------------------- /bin/pry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pry' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("pry", "pry") 17 | -------------------------------------------------------------------------------- /bin/rbs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rbs' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("rbs", "rbs") 17 | -------------------------------------------------------------------------------- /bin/kramdown: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kramdown' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kramdown", "kramdown") 17 | -------------------------------------------------------------------------------- /bin/nokogiri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nokogiri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("nokogiri", "nokogiri") 17 | -------------------------------------------------------------------------------- /bin/appraisal: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'appraisal' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("appraisal2", "appraisal") 17 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "oauth2" 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require "irb" 15 | IRB.start(__FILE__) 16 | -------------------------------------------------------------------------------- /Appraisal.root.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } 4 | 5 | source "https://gem.coop" 6 | 7 | # Appraisal Root Gemfile is for running appraisal to generate the Appraisal Gemfiles 8 | # in gemfiles/*gemfile. 9 | # On CI, we use it for the Appraisal-based builds. 10 | # We do not load the standard Gemfile, as it is tailored for local development. 11 | 12 | gemspec 13 | -------------------------------------------------------------------------------- /bin/kettle-dvcs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-dvcs' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-dvcs") 17 | -------------------------------------------------------------------------------- /.git-hooks/commit-subjects-goalie.txt: -------------------------------------------------------------------------------- 1 | 🔖 Prepare release v 2 | 🔒️ Checksums for v 3 | 4 | # Lines beginning with # are ignored. 5 | # This file is read by .git-hooks/prepare-commit-msg in each project. 6 | # Each line of this file will be matched against the commit subject using `starts_with?`. 7 | # If any `starts_with?` match the project script bin/prepare-commit-msg will run. 8 | # 🔒️ Checksums for v is the standard commit message by stone_checksums. 9 | -------------------------------------------------------------------------------- /bin/kettle-release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-release' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-release") 17 | -------------------------------------------------------------------------------- /bin/kettle-changelog: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-changelog' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-changelog") 17 | -------------------------------------------------------------------------------- /bin/kettle-dev-setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-dev-setup' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-dev-setup") 17 | -------------------------------------------------------------------------------- /bin/kettle-commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-commit-msg' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-commit-msg") 17 | -------------------------------------------------------------------------------- /bin/kettle-pre-release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-pre-release' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-pre-release") 17 | -------------------------------------------------------------------------------- /.idea/csv-editor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /bin/kettle-readme-backers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'kettle-readme-backers' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | require "rubygems" 14 | require "bundler/setup" 15 | 16 | load Gem.bin_path("kettle-dev", "kettle-readme-backers") 17 | -------------------------------------------------------------------------------- /.idea/active-tab-highlighter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | -------------------------------------------------------------------------------- /config-ssl.json: -------------------------------------------------------------------------------- 1 | { 2 | "interactiveLogin": true, 3 | "httpServer": { 4 | "type": "NettyWrapper" 5 | }, 6 | "tokenCallbacks": [ 7 | { 8 | "issuerId": "default", 9 | "requestMappings": [ 10 | { 11 | "requestParam": "grant_type", 12 | "match": "client_credentials", 13 | "claims": { 14 | "sub": "demo-sub", 15 | "aud": ["demo-aud"] 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /gemfiles/modular/erb/r2.3/default.gemfile: -------------------------------------------------------------------------------- 1 | # The cake is a lie. 2 | # erb v2.2, the oldest release, was never compatible with Ruby 2.3. 3 | # In addition, erb does not follow SemVer, and old rubies get dropped in a patch. 4 | # This means we have no choice but to use the erb that shipped with Ruby 2.3 5 | # /opt/hostedtoolcache/Ruby/2.3.8/x64/lib/ruby/gems/2.3.0/gems/erb-2.2.2/lib/erb.rb:670:in `prepare_trim_mode': undefined method `match?' for "-":String (NoMethodError) 6 | # gem "erb", ">= 2.2" # ruby >= 2.3.0 7 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_7.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v2.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v4.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_7.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_6.gemfile") 16 | 17 | eval_gemfile("modular/rack_v3.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_3_2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v2.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v5.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_7.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_7.gemfile") 16 | 17 | eval_gemfile("modular/rack_v3.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_3_3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v2.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v5.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_7.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_7.gemfile") 16 | 17 | eval_gemfile("modular/rack_v3.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v1.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v1.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_6.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.4/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v1.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v2.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_5.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_6.gemfile") 16 | 17 | eval_gemfile("modular/rack_v2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.6/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_6.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v2.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v3.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_5.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_6.gemfile") 16 | 17 | eval_gemfile("modular/rack_v3.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.6/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_3_0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v2.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v5.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_7.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_6.gemfile") 16 | 17 | eval_gemfile("modular/rack_v3.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r3.1/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_3_1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v2.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v5.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v2.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_7.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_6.gemfile") 16 | 17 | eval_gemfile("modular/rack_v3.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r3.1/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_3_hashie_v0.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v0.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v0.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_3_hashie_v1.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v0.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v1.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_3_hashie_v2.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v0.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v2.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_3_hashie_v3.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v0.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v3.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_3_hashie_v4.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v0.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v4.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/ruby_2_3_hashie_v5.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/faraday_v0.gemfile") 8 | 9 | eval_gemfile("modular/hashie_v5.gemfile") 10 | 11 | eval_gemfile("modular/jwt_v1.gemfile") 12 | 13 | eval_gemfile("modular/logger_v1_2.gemfile") 14 | 15 | eval_gemfile("modular/multi_xml_v0_5.gemfile") 16 | 17 | eval_gemfile("modular/rack_v1_2.gemfile") 18 | 19 | eval_gemfile("modular/x_std_libs/r2.3/libs.gemfile") 20 | -------------------------------------------------------------------------------- /gemfiles/modular/debug.gemfile: -------------------------------------------------------------------------------- 1 | # Ex-Standard Library gems 2 | gem "irb", "~> 1.15", ">= 1.15.2" # removed from stdlib in 3.5 3 | 4 | platform :mri do 5 | # Debugging - Ensure ENV["DEBUG"] == "true" to use debuggers within spec suite 6 | # Use binding.break, binding.b, or debugger in code 7 | gem "debug", ">= 1.1" # ruby >= 2.7 8 | 9 | # Dev Console - Binding.pry - Irb replacement 10 | # gem "pry", "~> 0.14" # ruby >= 2.0 11 | end 12 | 13 | gem "gem_bench", "~> 2.0", ">= 2.0.5" 14 | -------------------------------------------------------------------------------- /gemfiles/modular/documentation.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Documentation 4 | gem "kramdown", "~> 2.5", ">= 2.5.1" # Ruby >= 2.5 5 | gem "kramdown-parser-gfm", "~> 1.1" # Ruby >= 2.3 6 | gem "yard", "~> 0.9", ">= 0.9.37", require: false 7 | gem "yard-junk", "~> 0.0", ">= 0.0.10", github: "pboling/yard-junk", branch: "next", require: false 8 | gem "yard-relative_markdown_links", "~> 0.5.0" 9 | 10 | # Std Lib extractions 11 | gem "rdoc", "~> 6.11" 12 | gem "yard-fence", "~> 0.4", require: false # Ruby >= 3.2 13 | -------------------------------------------------------------------------------- /gemfiles/audit.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/audit.gemfile") 8 | 9 | eval_gemfile("modular/faraday_v2.gemfile") 10 | 11 | eval_gemfile("modular/hashie_v5.gemfile") 12 | 13 | eval_gemfile("modular/jwt_v2.gemfile") 14 | 15 | eval_gemfile("modular/logger_v1_7.gemfile") 16 | 17 | eval_gemfile("modular/multi_xml_v0_7.gemfile") 18 | 19 | eval_gemfile("modular/rack_v3.gemfile") 20 | 21 | eval_gemfile("modular/x_std_libs.gemfile") 22 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/git_toolbox_prj.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/auto-assign.yml: -------------------------------------------------------------------------------- 1 | name: Auto Assign 2 | on: 3 | issues: 4 | types: [opened] 5 | pull_request: 6 | types: [opened] 7 | jobs: 8 | run: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - name: 'Auto-assign issue' 15 | uses: pozil/auto-assign-issue@v2 16 | with: 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | assignees: pboling 19 | abortIfPreviousAssignees: true 20 | allowSelfAssign: true 21 | numOfAssignee: 1 -------------------------------------------------------------------------------- /gemfiles/coverage.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://gem.coop" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/coverage.gemfile") 8 | 9 | eval_gemfile("modular/faraday_v2.gemfile") 10 | 11 | eval_gemfile("modular/hashie_v5.gemfile") 12 | 13 | eval_gemfile("modular/jwt_v2.gemfile") 14 | 15 | eval_gemfile("modular/logger_v1_7.gemfile") 16 | 17 | eval_gemfile("modular/multi_xml_v0_7.gemfile") 18 | 19 | eval_gemfile("modular/optional.gemfile") 20 | 21 | eval_gemfile("modular/rack_v3.gemfile") 22 | 23 | eval_gemfile("modular/x_std_libs.gemfile") 24 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: oauth2 3 | message: >- 4 | If you use this work and you want to cite it, 5 | then you can use the metadata from this file. 6 | type: software 7 | authors: 8 | - given-names: Peter Hurn 9 | family-names: Boling 10 | email: peter@railsbling.com 11 | affiliation: railsbling.com 12 | orcid: 'https://orcid.org/0009-0008-8519-441X' 13 | identifiers: 14 | - type: url 15 | value: 'https://github.com/ruby-oauth/oauth2' 16 | description: oauth2 17 | repository-code: 'https://github.com/ruby-oauth/oauth2' 18 | abstract: >- 19 | oauth2 20 | license: See license file 21 | -------------------------------------------------------------------------------- /gemfiles/omnibus.gemfile: -------------------------------------------------------------------------------- 1 | # This file was generated by Appraisal2 2 | 3 | source "https://rubygems.org" 4 | 5 | gemspec path: "../" 6 | 7 | eval_gemfile("modular/audit.gemfile") 8 | 9 | eval_gemfile("modular/coverage.gemfile") 10 | 11 | eval_gemfile("modular/documentation.gemfile") 12 | 13 | eval_gemfile("modular/faraday_v2.gemfile") 14 | 15 | eval_gemfile("modular/hashie_v5.gemfile") 16 | 17 | eval_gemfile("modular/jwt_v2.gemfile") 18 | 19 | eval_gemfile("modular/logger_v1_7.gemfile") 20 | 21 | eval_gemfile("modular/multi_xml_v0_7.gemfile") 22 | 23 | eval_gemfile("modular/rack_v3.gemfile") 24 | 25 | eval_gemfile("modular/style.gemfile") 26 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | buy_me_a_coffee: pboling 4 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 5 | github: [pboling] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 6 | issuehunt: pboling # Replace with a single IssueHunt username 7 | ko_fi: pboling # Replace with a single Ko-fi username 8 | liberapay: pboling # Replace with a single Liberapay username 9 | open_collective: ruby-oauth 10 | patreon: galtzo # Replace with a single Patreon username 11 | polar: pboling 12 | thanks_dev: u/gh/pboling 13 | tidelift: rubygems/oauth2 14 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Ideas... 4 | # 1. Check for hashtags in PR title, and disallow changes to changelog? 5 | # e.g. github.pr_title.include? "#trivial" 6 | 7 | # Make it more obvious that a PR is a work in progress and shouldn't be merged yet 8 | warn("PR is classed as Work in Progress") if github.pr_title.include?("[WIP]") 9 | 10 | # Warn when there is a big PR 11 | warn("Big PR") if git.lines_of_code > 500 12 | 13 | # Don't let testing shortcuts get into main by accident 14 | raise("fdescribe left in tests") if %x(grep -r fdescribe specs/).length > 1 15 | raise("fit left in tests") if %x(grep -r fit specs/).length > 1 16 | -------------------------------------------------------------------------------- /.rubocop_rspec.yml: -------------------------------------------------------------------------------- 1 | RSpec/MultipleExpectations: 2 | Enabled: false 3 | 4 | RSpec/NamedSubject: 5 | Enabled: false 6 | 7 | RSpec/ExampleLength: 8 | Enabled: false 9 | 10 | RSpec/VerifiedDoubles: 11 | Enabled: false 12 | 13 | RSpec/MessageSpies: 14 | Enabled: false 15 | 16 | RSpec/InstanceVariable: 17 | Enabled: false 18 | 19 | RSpec/NestedGroups: 20 | Enabled: false 21 | 22 | RSpec/ExpectInHook: 23 | Enabled: false 24 | 25 | RSpec/DescribeClass: 26 | Exclude: 27 | - 'spec/examples/*' 28 | 29 | RSpec/MultipleMemoizedHelpers: 30 | Enabled: false 31 | 32 | RSpec/SpecFilePathFormat: 33 | CustomTransform: 34 | "OAuth": "oauth" 35 | -------------------------------------------------------------------------------- /sig/oauth2/response.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | class Response 3 | DEFAULT_OPTIONS: Hash[Symbol, untyped] 4 | 5 | def self.register_parser: (Symbol key, (Array[String] | String) mime_types) { (String) -> untyped } -> void 6 | 7 | def initialize: (untyped response, parse: Symbol?, snaky: bool?, snaky_hash_klass: untyped?, options: Hash[Symbol, untyped]?) -> void 8 | def headers: () -> Hash[untyped, untyped] 9 | def status: () -> Integer 10 | def body: () -> String 11 | def parsed: () -> untyped 12 | def content_type: () -> (String | nil) 13 | def parser: () -> (untyped | nil) 14 | 15 | attr_reader response: untyped 16 | attr_accessor options: Hash[Symbol, untyped] 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /.git-hooks/footer-template.erb.txt: -------------------------------------------------------------------------------- 1 | ⚡️ A message from a fellow meat-based-AI ⚡️ 2 | - [❤️] Finely-crafted open-source tools like <%= @gem_name %> (& many more) require time and effort. 3 | - [❤️] Though I adore my work, it lacks financial sustainability. 4 | - [❤️] Please, help me continue enhancing your tools by becoming a sponsor: 5 | - [💲] https://liberapay.com/pboling/donate 6 | - [💲] https://github.com/sponsors/pboling 7 | 8 | <% if ENV["GIT_HOOK_FOOTER_APPEND_DEBUG"] == "true" %> 9 | @pwd = <%= @pwd %> 10 | @gemspecs = <%= @gemspecs %> 11 | @spec = <%= @spec %> 12 | @gemspec_path = <%= @gemspec_path %> 13 | @gem_name <%= @gem_name %> 14 | @spec_name <%= @spec_name %> 15 | @content <%= @content %> 16 | <% end %> 17 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | |----------|-----------| 7 | | 1.latest | ✅ | 8 | 9 | ## Security contact information 10 | 11 | To report a security vulnerability, please use the 12 | [Tidelift security contact](https://tidelift.com/security). 13 | Tidelift will coordinate the fix and disclosure. 14 | 15 | More detailed explanation of the process is in [IRP.md][IRP] 16 | 17 | ## Additional Support 18 | 19 | If you are interested in support for versions older than the latest release, 20 | please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate, 21 | or find other sponsorship links in the [README]. 22 | 23 | [README]: README.md 24 | [IRP]: IRP.md 25 | -------------------------------------------------------------------------------- /sig/oauth2/authenticator.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | class Authenticator 3 | include OAuth2::FilteredAttributes 4 | 5 | attr_reader mode: (Symbol | String) 6 | attr_reader id: String? 7 | attr_reader secret: String? 8 | 9 | def initialize: (String? id, String? secret, (Symbol | String) mode) -> void 10 | 11 | def apply: (Hash[untyped, untyped]) -> Hash[untyped, untyped] 12 | 13 | def self.encode_basic_auth: (String, String) -> String 14 | 15 | private 16 | 17 | def apply_params_auth: (Hash[untyped, untyped]) -> Hash[untyped, untyped] 18 | def apply_client_id: (Hash[untyped, untyped]) -> Hash[untyped, untyped] 19 | def apply_basic_auth: (Hash[untyped, untyped]) -> Hash[untyped, untyped] 20 | def basic_auth_header: () -> Hash[String, String] 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Artifacts 2 | /pkg/ 3 | /tmp/ 4 | *.gem 5 | 6 | # Bundler 7 | /vendor/bundle/ 8 | /.bundle/ 9 | /gemfiles/*.lock 10 | /gemfiles/.bundle/ 11 | /gemfiles/.bundle/config 12 | /gemfiles/vendor/ 13 | Appraisal.*.gemfile.lock 14 | 15 | # Specs 16 | .rspec_status 17 | /coverage/ 18 | /spec/reports/ 19 | /results/ 20 | .output.txt 21 | 22 | # Documentation 23 | /.yardoc/ 24 | /_yardoc/ 25 | /rdoc/ 26 | /doc/ 27 | /blogs/ 28 | 29 | # Ruby Version Managers (RVM, rbenv, etc) 30 | # Ignored because we currently use .tool-versions 31 | .rvmrc 32 | .ruby-version 33 | .ruby-gemset 34 | 35 | # Benchmarking 36 | /measurement/ 37 | 38 | # Debugger detritus 39 | .byebug_history 40 | 41 | # direnv - brew install direnv 42 | .env.local 43 | 44 | # OS Detritus 45 | .DS_Store 46 | 47 | # Editors 48 | *~ 49 | 50 | # Sentinels 51 | .floss_funding.*.lock 52 | -------------------------------------------------------------------------------- /bin/irb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'irb' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("irb", "irb") 28 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rake' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rake", "rake") 28 | -------------------------------------------------------------------------------- /bin/ri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rdoc", "ri") 28 | -------------------------------------------------------------------------------- /bin/yri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("yard", "yri") 28 | -------------------------------------------------------------------------------- /bin/racc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'racc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("racc", "racc") 28 | -------------------------------------------------------------------------------- /bin/rdbg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rdbg' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("debug", "rdbg") 28 | -------------------------------------------------------------------------------- /bin/rdoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rdoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rdoc", "rdoc") 28 | -------------------------------------------------------------------------------- /bin/reek: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'reek' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("reek", "reek") 28 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rspec-core", "rspec") 28 | -------------------------------------------------------------------------------- /bin/thor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'thor' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("thor", "thor") 28 | -------------------------------------------------------------------------------- /bin/yard: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yard' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("yard", "yard") 28 | -------------------------------------------------------------------------------- /bin/ldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("diff-lcs", "ldiff") 28 | -------------------------------------------------------------------------------- /bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rubocop' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rubocop", "rubocop") 28 | -------------------------------------------------------------------------------- /bin/yardoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yardoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("yard", "yardoc") 28 | -------------------------------------------------------------------------------- /bin/coderay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'coderay' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("coderay", "coderay") 28 | -------------------------------------------------------------------------------- /bin/htmldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'htmldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("diff-lcs", "htmldiff") 28 | -------------------------------------------------------------------------------- /bin/redcarpet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'redcarpet' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("redcarpet", "redcarpet") 28 | -------------------------------------------------------------------------------- /bin/ruby-parse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-parse' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("parser", "ruby-parse") 28 | -------------------------------------------------------------------------------- /bin/standardrb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'standardrb' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("standard", "standardrb") 28 | -------------------------------------------------------------------------------- /bin/yard-junk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yard-junk' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("yard-junk", "yard-junk") 28 | -------------------------------------------------------------------------------- /spec/fixtures/RS256/jwtRS256.key.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5hdXV/4YSymY1T9VNvK2 3 | bWRfulwIty1RnAPNINQmfh3aRRkV+PNrbC2Crji9G0AHmQwgW1bZ3kgkkpIm6RVn 4 | 44fHvBvuXkZ9ABgXw0d2cLIHmwOFxSKmWAm/EW//GszUTLLLsMZUe2udtFJW0jxX 5 | B2GRY0WVYuo6Oo58RCeP719lw3Ags0YF9/IobxKkGd4BautUPw6ZszAa3o+j0zR7 6 | 4x7ouPxybZAOuPsMxqanyeYJeH4osJjLMYV9qem9uG2sj7GENJ8UszcpmGbqxBhe 7 | xPEB7mgDeONIF0XJF23zdOf8ANE5mAU2h2v7M6moAfkdUzJ+j48+VT2omHAzAL5y 8 | Ncmrl2xiWdyoxOw1Y1UmfEmJYV5VgGYyZ12JZRKY+szPT+vR+MDuYxbquF40O7kv 9 | kFNBfL1yCpzfSQCLnEs4rX8qRzZXciLeyq4Ht5FLuRFgxjA//XI8LAmp0u7gk+Q7 10 | FUH1UgW3kmJDTG0XaxQxYTBSIO7mcmyjDyBgKVuQmt5E1ycFeteOVdPD/CG/fPYh 11 | thvc4UytEFwsMdNy3iD6/wuUH68tAKam28UZaOb0qK+00cQQD8fulY9rKtSL10Lv 12 | JFWUOa/SJyLvk9vUmfvFn182il1nX6GpyxyMmE/FCnH4CT/DjrSZf08mOO8eL5of 13 | YHMK/oiXr1eODqx+pOwClNsCAwEAAQ== 14 | -----END PUBLIC KEY----- 15 | -------------------------------------------------------------------------------- /bin/ruby-rewrite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-rewrite' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("parser", "ruby-rewrite") 28 | -------------------------------------------------------------------------------- /gemfiles/modular/runtime_heads.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Test against HEAD of runtime dependencies so we can proactively file bugs 4 | 5 | # Ruby >= 3.0 6 | gem "faraday", github: "lostisland/faraday", branch: "main" 7 | 8 | # Ruby >= 0 9 | gem "hashie", github: "hashie/hashie", branch: "master" 10 | 11 | # Ruby >= 2.5 12 | gem "jwt", github: "jwt/ruby-jwt", branch: "main" 13 | 14 | # Ruby >= 2.5 15 | gem "logger", github: "ruby/logger", branch: "master" 16 | 17 | # Ruby >= 3.2 18 | gem "multi_xml", github: "sferik/multi_xml", branch: "master" 19 | 20 | # Ruby >= 2.4 21 | gem "rack", github: "rack/rack", branch: "main" 22 | 23 | # Ruby >= 2.2 24 | gem "version_gem", github: "ruby-oauth/version_gem", branch: "main" 25 | 26 | # Ruby >= 2.2 27 | gem "snaky_hash", github: "ruby-oauth/snaky_hash", branch: "main" 28 | 29 | eval_gemfile("x_std_libs/vHEAD.gemfile") 30 | -------------------------------------------------------------------------------- /bin/bundle-audit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle-audit' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("bundler-audit", "bundle-audit") 28 | -------------------------------------------------------------------------------- /bin/bundler-audit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundler-audit' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("bundler-audit", "bundler-audit") 28 | -------------------------------------------------------------------------------- /bin/github-markup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'github-markup' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("github-markup", "github-markup") 28 | -------------------------------------------------------------------------------- /bin/code_climate_reek: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'code_climate_reek' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("reek", "code_climate_reek") 28 | -------------------------------------------------------------------------------- /bin/gem_checksums: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'gem_checksums' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("stone_checksums", "gem_checksums") 28 | -------------------------------------------------------------------------------- /bin/rubocop-gradual: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rubocop-gradual' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 12 | 13 | bundle_binstub = File.expand_path("bundle", __dir__) 14 | 15 | if File.file?(bundle_binstub) 16 | if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") 17 | load(bundle_binstub) 18 | else 19 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 20 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 21 | end 22 | end 23 | 24 | require "rubygems" 25 | require "bundler/setup" 26 | 27 | load Gem.bin_path("rubocop-gradual", "rubocop-gradual") 28 | -------------------------------------------------------------------------------- /lib/oauth2/strategy/client_credentials.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | module Strategy 5 | # The Client Credentials Strategy 6 | # 7 | # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.4 8 | class ClientCredentials < Base 9 | # Not used for this strategy 10 | # 11 | # @raise [NotImplementedError] 12 | def authorize_url 13 | raise(NotImplementedError, "The authorization endpoint is not used in this strategy") 14 | end 15 | 16 | # Retrieve an access token given the specified client. 17 | # 18 | # @param [Hash] params additional params 19 | # @param [Hash] opts options 20 | def get_token(params = {}, opts = {}) 21 | params = params.merge("grant_type" => "client_credentials") 22 | @client.get_token(params, opts) 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ensure test env 4 | ENV["RACK_ENV"] = "test" 5 | 6 | # Global Extensions 7 | require_relative "ext/backports" 8 | 9 | # External libraries 10 | require "addressable/uri" 11 | require "rspec/pending_for" 12 | 13 | # Family libraries 14 | require "kettle/test/rspec" 15 | 16 | # Library Configs 17 | require_relative "config/debug" 18 | require_relative "config/multi_xml" 19 | require_relative "config/faraday" 20 | require_relative "config/constants" 21 | 22 | # NOTE: Gemfiles for older rubies won't have kettle-soup-cover. 23 | # The rescue LoadError handles that scenario. 24 | begin 25 | require "kettle-soup-cover" 26 | require "simplecov" if Kettle::Soup::Cover::DO_COV # `.simplecov` is run here! 27 | rescue LoadError => error 28 | # check the error message, and re-raise if not what is expected 29 | raise error unless error.message.include?("kettle") 30 | end 31 | 32 | # This gem 33 | require "oauth2" 34 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. 4 | # 5 | # Source repository: https://github.com/actions/dependency-review-action 6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement 7 | name: 'Dependency Review' 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | dependency-review: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: 'Checkout Repository' 18 | uses: actions/checkout@v6 19 | - name: 'Dependency Review' 20 | uses: actions/dependency-review-action@v4 21 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://gem.coop" 4 | 5 | git_source(:codeberg) { |repo_name| "https://codeberg.org/#{repo_name}" } 6 | git_source(:gitlab) { |repo_name| "https://gitlab.com/#{repo_name}" } 7 | 8 | #### IMPORTANT ####################################################### 9 | # Gemfile is for local development ONLY; Gemfile is NOT loaded in CI # 10 | ####################################################### IMPORTANT #### 11 | 12 | # Include dependencies from .gemspec 13 | gemspec 14 | 15 | # Debugging 16 | eval_gemfile "gemfiles/modular/debug.gemfile" 17 | 18 | # Code Coverage 19 | eval_gemfile "gemfiles/modular/coverage.gemfile" 20 | 21 | # Linting 22 | eval_gemfile "gemfiles/modular/style.gemfile" 23 | 24 | # Documentation 25 | eval_gemfile "gemfiles/modular/documentation.gemfile" 26 | 27 | # Optional 28 | eval_gemfile "gemfiles/modular/optional.gemfile" 29 | 30 | ### Std Lib Extracted Gems 31 | eval_gemfile "gemfiles/modular/x_std_libs.gemfile" 32 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ruby 3 | { 4 | "name": "Ruby", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/ruby:1-3-bookworm", 7 | 8 | // Features to add to the dev container. More info: https://containers.dev/features. 9 | // "features": {}, 10 | 11 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 12 | // "forwardPorts": [], 13 | 14 | // Use 'postCreateCommand' to run commands after the container is created. 15 | // "postCreateCommand": "ruby --version", 16 | 17 | // Configure tool-specific properties. 18 | "customizations" : { 19 | "jetbrains" : { 20 | "backend" : "RubyMine" 21 | } 22 | }, 23 | 24 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 25 | // "remoteUser": "root" 26 | } 27 | -------------------------------------------------------------------------------- /gemfiles/modular/style.gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # We run rubocop on the latest version of Ruby, 4 | # but in support of the oldest supported version of Ruby 5 | 6 | gem "reek", "~> 6.5" 7 | # gem "rubocop", "~> 1.73", ">= 1.73.2" # constrained by standard 8 | gem "rubocop-packaging", "~> 0.6", ">= 0.6.0" 9 | gem "standard", ">= 1.50" 10 | gem "rubocop-on-rbs", "~> 1.8" # ruby >= 3.1.0 11 | 12 | # Std Lib extractions 13 | gem "benchmark", "~> 0.4", ">= 0.4.1" # Removed from Std Lib in Ruby 3.5 14 | 15 | if ENV.fetch("RUBOCOP_LTS_LOCAL", "false").casecmp("true").zero? 16 | home = ENV["HOME"] 17 | gem "rubocop-lts", path: "#{home}/src/rubocop-lts/rubocop-lts" 18 | gem "rubocop-lts-rspec", path: "#{home}/src/rubocop-lts/rubocop-lts-rspec" 19 | gem "rubocop-ruby2_2", path: "#{home}/src/rubocop-lts/rubocop-ruby2_2" 20 | gem "standard-rubocop-lts", path: "#{home}/src/rubocop-lts/standard-rubocop-lts" 21 | else 22 | gem "rubocop-lts", "~> 8.0" 23 | gem "rubocop-ruby2_2" 24 | gem "rubocop-rspec", "~> 3.6" 25 | end 26 | -------------------------------------------------------------------------------- /.github/disabled-workflows/discord-notifier.yml: -------------------------------------------------------------------------------- 1 | name: Discord Notify 2 | 3 | on: 4 | check_run: 5 | types: [completed] 6 | discussion: 7 | types: [ created ] 8 | discussion_comment: 9 | types: [ created ] 10 | fork: 11 | gollum: 12 | issues: 13 | types: [ opened ] 14 | issue_comment: 15 | types: [ created ] 16 | pull_request: 17 | types: [ opened, reopened, closed ] 18 | release: 19 | types: [ published ] 20 | watch: 21 | types: [ started ] 22 | 23 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 24 | jobs: 25 | # This workflow contains a single job called "build" 26 | notify: 27 | if: false 28 | # The type of runner that the job will run on 29 | runs-on: ubuntu-latest 30 | 31 | # Steps represent a sequence of tasks that will be executed as part of the job 32 | steps: 33 | - name: Actions Status Discord 34 | uses: sarisia/actions-status-discord@v1 35 | if: always() 36 | with: 37 | webhook: ${{ secrets.DISCORD_WEBHOOK }} 38 | status: ${{ job.status }} 39 | username: GitHub Actions 40 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2025 Peter H. Boling, of Galtzo.com, and oauth2 contributors 4 | Copyright (c) 2011-2013 Michael Bleigh and Intridea, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /spec/oauth2_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe OAuth2 do 4 | it "silence_extra_tokens_warning is a boolean" do 5 | expect(described_class.config.silence_extra_tokens_warning).to be(true).or be(false) 6 | end 7 | 8 | describe ".configure" do 9 | subject(:configure) do 10 | described_class.configure do |config| 11 | config.silence_extra_tokens_warning = true 12 | config.silence_no_tokens_warning = true 13 | end 14 | end 15 | 16 | before do 17 | described_class.configure do |config| 18 | config.silence_extra_tokens_warning = false 19 | config.silence_no_tokens_warning = false 20 | end 21 | end 22 | 23 | after do 24 | described_class.configure do |config| 25 | config.silence_extra_tokens_warning = false 26 | config.silence_no_tokens_warning = false 27 | end 28 | end 29 | 30 | it "can change setting of silence_extra_tokens_warning" do 31 | block_is_expected.to change(described_class.config, :silence_extra_tokens_warning).from(false).to(true) 32 | end 33 | 34 | it "can change setting of silence_no_tokens_warning" do 35 | block_is_expected.to change(described_class.config, :silence_no_tokens_warning).from(false).to(true) 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | # Use this file to configure the Overcommit hooks you wish to use. This will 2 | # extend the default configuration defined in: 3 | # https://github.com/sds/overcommit/blob/master/config/default.yml 4 | # 5 | # At the topmost level of this YAML file is a key representing type of hook 6 | # being run (e.g. pre-commit, commit-msg, etc.). Within each type you can 7 | # customize each hook, such as whether to only run it on certain files (via 8 | # `include`), whether to only display output if it fails (via `quiet`), etc. 9 | # 10 | # For a complete list of hooks, see: 11 | # https://github.com/sds/overcommit/tree/master/lib/overcommit/hook 12 | # 13 | # For a complete list of options that you can use to customize hooks, see: 14 | # https://github.com/sds/overcommit#configuration 15 | # 16 | # Uncomment the following lines to make the configuration take effect. 17 | 18 | PreCommit: 19 | RuboCop: 20 | enabled: true 21 | on_warn: fail # Treat all warnings as failures 22 | 23 | TrailingWhitespace: 24 | enabled: true 25 | 26 | PostCheckout: 27 | ALL: # Special hook name that customizes all hooks of this type 28 | quiet: true # Change all post-checkout hooks to only display output on failure 29 | # 30 | # IndexTags: 31 | # enabled: true # Generate a tags file with `ctags` each time HEAD changes 32 | -------------------------------------------------------------------------------- /sig/oauth2/strategy.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | module Strategy 3 | class Base 4 | def initialize: (OAuth2::Client) -> void 5 | end 6 | 7 | class AuthCode < Base 8 | def authorize_params: (?Hash[untyped, untyped]) -> Hash[untyped, untyped] 9 | def authorize_url: (?Hash[untyped, untyped]) -> String 10 | def get_token: (String, ?Hash[untyped, untyped], ?Hash[Symbol, untyped]) -> OAuth2::AccessToken 11 | end 12 | 13 | class Implicit < Base 14 | def authorize_params: (?Hash[untyped, untyped]) -> Hash[untyped, untyped] 15 | def authorize_url: (?Hash[untyped, untyped]) -> String 16 | def get_token: (*untyped) -> void 17 | end 18 | 19 | class Password < Base 20 | def authorize_url: () -> void 21 | def get_token: (String, String, ?Hash[untyped, untyped], ?Hash[Symbol, untyped]) -> OAuth2::AccessToken 22 | end 23 | 24 | class ClientCredentials < Base 25 | def authorize_url: () -> void 26 | def get_token: (?Hash[untyped, untyped], ?Hash[Symbol, untyped]) -> OAuth2::AccessToken 27 | end 28 | 29 | class Assertion < Base 30 | def authorize_url: () -> void 31 | def get_token: (Hash[untyped, untyped], Hash[Symbol, untyped], ?Hash[Symbol, untyped], ?Hash[Symbol, untyped]) -> OAuth2::AccessToken 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /.env.local.example: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE 3 | # 4 | # COPT THIS FILE TO .env.local 5 | # 6 | # That file is ignored by .gitignore. This file is not. 7 | # 8 | export DEBUG=false # do not allow byebug statements (override in .env.local) 9 | export FLOSS_FUNDING_DEBUG=false # extra logging to help diagnose issues (override in .env.local) 10 | export AUTOGEN_FIXTURE_CLEANUP=false # autogenerated gem fixture cleanup after every RSpec run 11 | export GIT_HOOK_FOOTER_APPEND=false 12 | export GIT_HOOK_FOOTER_APPEND_DEBUG=false 13 | export GIT_HOOK_FOOTER_SENTINEL="⚡️ A message from a fellow meat-based-AI" 14 | 15 | # Tokens used by ci:act and CI helpers for reading workflow/pipeline status via APIs 16 | # GitHub (either GITHUB_TOKEN or GH_TOKEN will be used; fine-grained recommended) 17 | # - Scope/permissions: For fine-grained tokens, grant repository access (Read) and Actions: Read 18 | # - For classic tokens, public repos need no scopes; private repos typically require repo 19 | export GITHUB_TOKEN= 20 | # Alternatively: 21 | # export GH_TOKEN= 22 | 23 | # GitLab (either GITLAB_TOKEN or GL_TOKEN will be used) 24 | # - Scope: read_api is sufficient to read pipelines 25 | export GITLAB_TOKEN= 26 | # Alternatively: 27 | # export GL_TOKEN= 28 | -------------------------------------------------------------------------------- /.github/workflows/license-eye.yml: -------------------------------------------------------------------------------- 1 | name: Apache SkyWalking Eyes 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'main' 10 | - '*-stable' 11 | tags: 12 | - '!*' # Do not execute on tags 13 | pull_request: 14 | branches: 15 | - '*' 16 | # Allow manually triggering the workflow. 17 | workflow_dispatch: 18 | 19 | # Cancels all previous workflow runs for the same branch that have not yet completed. 20 | concurrency: 21 | # The concurrency group contains the workflow name and the branch name. 22 | group: "${{ github.workflow }}-${{ github.ref }}" 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | license-check: 27 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v6 32 | 33 | - name: Check Dependencies' License 34 | uses: apache/skywalking-eyes/dependency@main 35 | with: 36 | config: .licenserc.yaml 37 | # Ruby packages declared as dependencies in gemspecs or Gemfiles are 38 | # typically consumed as binaries; enable weak-compatibility 39 | # so permissive and weak-copyleft combinations are treated as compatible. 40 | flags: --weak-compatible 41 | -------------------------------------------------------------------------------- /.idea/codestream.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.github/disabled-workflows/danger.yml: -------------------------------------------------------------------------------- 1 | name: What's up Danger? 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'main' 7 | - '*-stable' 8 | 9 | jobs: 10 | danger: 11 | runs-on: ubuntu-latest 12 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 13 | BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile 14 | if: false 15 | # if: github.event_name == 'pull_request' # if only run pull request when multiple trigger workflow 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | gemfile: 20 | - vanilla 21 | rubygems: 22 | - latest 23 | bundler: 24 | - latest 25 | ruby: 26 | - "ruby" 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v4 30 | - name: Setup Ruby & Bundle 31 | uses: ruby/setup-ruby@v1 32 | with: 33 | ruby-version: ${{ matrix.ruby }} 34 | rubygems: ${{ matrix.rubygems }} 35 | bundler: ${{ matrix.bundler }} 36 | bundler-cache: true 37 | - uses: MeilCli/danger-action@v6 38 | with: 39 | plugins_file: 'Gemfile' 40 | install_path: 'vendor/bundle' 41 | danger_file: 'Dangerfile' 42 | danger_id: 'danger-pr' 43 | env: 44 | DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} 45 | -------------------------------------------------------------------------------- /.github/workflows/opencollective.yml: -------------------------------------------------------------------------------- 1 | name: Open Collective Backers 2 | 3 | on: 4 | schedule: 5 | # Run once a week on Sunday at 12:00 AM UTC 6 | - cron: '0 0 * * 0' 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: write 11 | 12 | jobs: 13 | update-backers: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v6 17 | with: 18 | persist-credentials: false 19 | - name: Setup Ruby & RubyGems 20 | uses: ruby/setup-ruby@v1 21 | with: 22 | ruby-version: ruby 23 | rubygems: default 24 | bundler: default 25 | bundler-cache: true 26 | 27 | - name: README Update 28 | env: 29 | # Keep GITHUB_TOKEN for any tools/scripts expecting it, mapped to the same secret 30 | GITHUB_TOKEN: ${{ secrets.README_UPDATER_TOKEN }} 31 | README_UPDATER_TOKEN: ${{ secrets.README_UPDATER_TOKEN }} 32 | REPO: ${{ github.repository }} 33 | run: | 34 | git config user.name 'autobolt' 35 | git config user.email 'autobots@9thbit.net' 36 | # Use the configured token for authenticated pushes 37 | git remote set-url origin "https://x-access-token:${README_UPDATER_TOKEN}@github.com/${REPO}.git" 38 | bin/kettle-readme-backers 39 | # Push back to the same branch/ref that triggered the workflow (default branch for schedule) 40 | git push origin HEAD 41 | -------------------------------------------------------------------------------- /spec/oauth2/strategy/implicit_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe OAuth2::Strategy::Implicit do 4 | subject { client.implicit } 5 | 6 | let(:client) { OAuth2::Client.new("abc", "def", site: "http://api.example.com") } 7 | 8 | describe "#authorize_url" do 9 | it "includes the client_id" do 10 | expect(subject.authorize_url).to include("client_id=abc") 11 | end 12 | 13 | it "includes the type" do 14 | expect(subject.authorize_url).to include("response_type=token") 15 | end 16 | 17 | it "does not include the client_secret" do 18 | expect(subject.authorize_url).not_to include("client_secret=def") 19 | end 20 | 21 | it "raises an error if the client_secret is passed in" do 22 | expect { subject.authorize_url(client_secret: "def") }.to raise_error(ArgumentError) 23 | end 24 | 25 | it "raises an error if the client_secret is passed in with string keys" do 26 | expect { subject.authorize_url("client_secret" => "def") }.to raise_error(ArgumentError) 27 | end 28 | 29 | it "includes passed in options" do 30 | cb = "http://myserver.local/oauth/callback" 31 | expect(subject.authorize_url(redirect_uri: cb)).to include("redirect_uri=#{CGI.escape(cb)}") 32 | end 33 | end 34 | 35 | describe "#get_token" do 36 | it "raises NotImplementedError" do 37 | expect { subject.get_token }.to raise_error(NotImplementedError) 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /sig/oauth2/access_token.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | class AccessToken 3 | def self.from_hash: (OAuth2::Client, Hash[untyped, untyped]) -> OAuth2::AccessToken 4 | def self.from_kvform: (OAuth2::Client, String) -> OAuth2::AccessToken 5 | 6 | def initialize: (OAuth2::Client, String, ?Hash[Symbol, untyped]) -> void 7 | def []: (String | Symbol) -> untyped 8 | def expires?: () -> bool 9 | def expired?: () -> bool 10 | def refresh: (?Hash[untyped, untyped], ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::AccessToken 11 | def revoke: (?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 12 | def to_hash: () -> Hash[Symbol, untyped] 13 | def request: (Symbol, String, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 14 | def get: (String, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 15 | def post: (String, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 16 | def put: (String, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 17 | def patch: (String, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 18 | def delete: (String, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 19 | def headers: () -> Hash[String, String] 20 | def configure_authentication!: (Hash[Symbol, untyped], Symbol) -> void 21 | def convert_expires_at: (untyped) -> (Time | Integer | nil) 22 | 23 | attr_accessor response: OAuth2::Response 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/oauth2/strategy/password.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | module Strategy 5 | # The Resource Owner Password Credentials Authorization Strategy 6 | # 7 | # IMPORTANT (OAuth 2.1): The Resource Owner Password Credentials grant is omitted in OAuth 2.1. 8 | # It remains here for backward compatibility with OAuth 2.0 providers. Prefer Authorization Code + PKCE. 9 | # 10 | # References: 11 | # - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13 12 | # - Okta explainer: https://developer.okta.com/blog/2019/12/13/oauth-2-1-how-many-rfcs 13 | # - FusionAuth blog: https://fusionauth.io/blog/2020/04/15/whats-new-in-oauth-2-1 14 | # 15 | # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.3 16 | class Password < Base 17 | # Not used for this strategy 18 | # 19 | # @raise [NotImplementedError] 20 | def authorize_url 21 | raise(NotImplementedError, "The authorization endpoint is not used in this strategy") 22 | end 23 | 24 | # Retrieve an access token given the specified End User username and password. 25 | # 26 | # @param [String] username the End User username 27 | # @param [String] password the End User password 28 | # @param [Hash] params additional params 29 | def get_token(username, password, params = {}, opts = {}) 30 | params = { 31 | "grant_type" => "password", 32 | "username" => username, 33 | "password" => password, 34 | }.merge(params) 35 | @client.get_token(params, opts) 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /.qlty/qlty.toml: -------------------------------------------------------------------------------- 1 | # For a guide to configuration, visit https://qlty.sh/d/config 2 | # Or for a full reference, visit https://qlty.sh/d/qlty-toml 3 | config_version = "0" 4 | 5 | exclude_patterns = [ 6 | "*_min.*", 7 | "*-min.*", 8 | "*.min.*", 9 | "**/.yarn/**", 10 | "**/*.d.ts", 11 | "**/assets/**", 12 | "**/bin/**", 13 | "**/bower_components/**", 14 | "**/build/**", 15 | "**/cache/**", 16 | "**/config/**", 17 | "**/.devcontainer", 18 | "**/db/**", 19 | "**/deps/**", 20 | "**/dist/**", 21 | "**/doc/**", 22 | "**/docs/**", 23 | "**/extern/**", 24 | "**/external/**", 25 | "**/generated/**", 26 | "**/Godeps/**", 27 | "**/gradlew/**", 28 | "**/mvnw/**", 29 | "**/node_modules/**", 30 | "**/protos/**", 31 | "**/seed/**", 32 | "**/target/**", 33 | "**/templates/**", 34 | "**/testdata/**", 35 | "**/vendor/**", 36 | ".github/workflows/codeql-analysis.yml" 37 | ] 38 | 39 | test_patterns = [ 40 | "**/test/**", 41 | "**/spec/**", 42 | "**/*.test.*", 43 | "**/*.spec.*", 44 | "**/*_test.*", 45 | "**/*_spec.*", 46 | "**/test_*.*", 47 | "**/spec_*.*", 48 | ] 49 | 50 | [smells] 51 | mode = "comment" 52 | 53 | [smells.boolean_logic] 54 | threshold = 4 55 | enabled = true 56 | 57 | [smells.file_complexity] 58 | threshold = 55 59 | enabled = false 60 | 61 | [smells.return_statements] 62 | threshold = 4 63 | enabled = true 64 | 65 | [smells.nested_control_flow] 66 | threshold = 4 67 | enabled = true 68 | 69 | [smells.function_parameters] 70 | threshold = 4 71 | enabled = true 72 | 73 | [smells.function_complexity] 74 | threshold = 5 75 | enabled = true 76 | 77 | [smells.duplication] 78 | enabled = true 79 | threshold = 20 -------------------------------------------------------------------------------- /certs/pboling.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl 3 | ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW 4 | A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM 5 | DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy 6 | LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA 7 | uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61 8 | LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5 9 | mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN 10 | coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV 11 | FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj 12 | yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1 13 | to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD 14 | qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj 15 | fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ 16 | HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG 17 | A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD 18 | ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9 19 | wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR 20 | L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm 21 | GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k 22 | kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq 23 | QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA 24 | 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p 25 | DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt 26 | L9nRqA== 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /.junie/guidelines-rbs.md: -------------------------------------------------------------------------------- 1 | # Junie Project Guidelines Addendum: RBS Documentation 2 | 3 | This repository ships RBS type signatures under `sig/` which are included in the published gem and referenced by documentation tooling. 4 | 5 | RBS files must contain only valid RBS syntax. Do not embed Ruby code or YARD-style Ruby documentation constructs in `.rbs` files. 6 | 7 | Requirements for RBS documentation and signatures: 8 | 9 | - Use RBS comment style (`# ...`) for notes and documentation inside `.rbs` files. 10 | - Do not use Ruby heredocs (`<<-DOC`, `<<~RUBY`, etc.) or any Ruby code constructs in `.rbs` files. 11 | - Do not use Ruby metaprogramming notation like `class << self` in `.rbs`. For singleton methods, use: 12 | - `def self.method_name: ...` 13 | - Do not use `extend self` or `module self` in `.rbs`. Declare singleton methods explicitly with `def self.method_name: ...`. 14 | - Keep type aliases, interfaces, and method signatures in proper RBS form only (e.g., `def foo: (String) -> Integer`). 15 | - If you need to document parameters or returns, place brief comments above the signature lines using `#` and keep them RBS-friendly (no `@param` / `@return` tags from YARD). 16 | 17 | Examples: 18 | 19 | Valid (RBS): 20 | 21 | ``` 22 | module Foo 23 | # Runs tasks 24 | def self.run: () -> void 25 | end 26 | ``` 27 | 28 | Invalid (not allowed in .rbs): 29 | 30 | ``` 31 | # Ruby syntax – not RBS 32 | class << self 33 | def run: () -> void 34 | end 35 | 36 | # Not supported across RBS versions; avoid in this project 37 | module self 38 | def run: () -> void 39 | end 40 | 41 | # Heredocs or any Ruby bodies are not allowed in .rbs 42 | def self.run: () -> void 43 | <<~DOC 44 | DOC 45 | end 46 | ``` 47 | 48 | Enforcement: 49 | - CI and local builds may parse `.rbs` files during gem install or doc generation. Any non-RBS syntax can cause installation to fail. Keep `.rbs` clean to avoid such failures. 50 | -------------------------------------------------------------------------------- /lib/oauth2/strategy/implicit.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | module Strategy 5 | # The Implicit Strategy 6 | # 7 | # IMPORTANT (OAuth 2.1): The Implicit grant (response_type=token) is omitted from the OAuth 2.1 draft specification. 8 | # It remains here for backward compatibility with OAuth 2.0 providers. Prefer the Authorization Code flow with PKCE. 9 | # 10 | # References: 11 | # - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13 12 | # - Why drop implicit: https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1 13 | # - Background: https://fusionauth.io/learn/expert-advice/oauth/differences-between-oauth-2-oauth-2-1/ 14 | # 15 | # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-4.2 16 | class Implicit < Base 17 | # The required query parameters for the authorize URL 18 | # 19 | # @param [Hash] params additional query parameters 20 | def authorize_params(params = {}) 21 | params.merge("response_type" => "token", "client_id" => @client.id) 22 | end 23 | 24 | # The authorization URL endpoint of the provider 25 | # 26 | # @param [Hash] params additional query parameters for the URL 27 | def authorize_url(params = {}) 28 | assert_valid_params(params) 29 | @client.authorize_url(authorize_params.merge(params)) 30 | end 31 | 32 | # Not used for this strategy 33 | # 34 | # @raise [NotImplementedError] 35 | def get_token(*) 36 | raise(NotImplementedError, "The token is accessed differently in this strategy") 37 | end 38 | 39 | private 40 | 41 | def assert_valid_params(params) 42 | raise(ArgumentError, "client_secret is not allowed in authorize URL query params") if params.key?(:client_secret) || params.key?("client_secret") 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/oauth2/filtered_attributes.rb: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | # Mixin that redacts sensitive instance variables in #inspect output. 3 | # 4 | # Classes include this module and declare which attributes should be filtered 5 | # using {.filtered_attributes}. Any instance variable name that includes one of 6 | # those attribute names will be shown as [FILTERED] in the object's inspect. 7 | module FilteredAttributes 8 | # Hook invoked when the module is included. Extends the including class with 9 | # class-level helpers. 10 | # 11 | # @param [Class] base The including class 12 | # @return [void] 13 | def self.included(base) 14 | base.extend(ClassMethods) 15 | end 16 | 17 | # Class-level helpers for configuring filtered attributes. 18 | module ClassMethods 19 | # Declare attributes that should be redacted in inspect output. 20 | # 21 | # @param [Array] attributes One or more attribute names 22 | # @return [void] 23 | def filtered_attributes(*attributes) 24 | @filtered_attribute_names = attributes.map(&:to_sym) 25 | end 26 | 27 | # The configured attribute names to filter. 28 | # 29 | # @return [Array] 30 | def filtered_attribute_names 31 | @filtered_attribute_names || [] 32 | end 33 | end 34 | 35 | # Custom inspect that redacts configured attributes. 36 | # 37 | # @return [String] 38 | def inspect 39 | filtered_attribute_names = self.class.filtered_attribute_names 40 | return super if filtered_attribute_names.empty? 41 | 42 | inspected_vars = instance_variables.map do |var| 43 | if filtered_attribute_names.any? { |filtered_var| var.to_s.include?(filtered_var.to_s) } 44 | "#{var}=[FILTERED]" 45 | else 46 | "#{var}=#{instance_variable_get(var).inspect}" 47 | end 48 | end 49 | "#<#{self.class}:#{object_id} #{inspected_vars.join(", ")}>" 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/oauth2/strategy/password_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe OAuth2::Strategy::Password do 4 | subject { client.password } 5 | 6 | let(:client) do 7 | cli = OAuth2::Client.new("abc", "def", site: "http://api.example.com") 8 | cli.connection = Faraday.new(cli.site, cli.options[:connection_opts]) do |b| 9 | b.request :url_encoded 10 | b.adapter :test do |stub| 11 | stub.post("/oauth/token") do |_env| 12 | case @mode 13 | when "formencoded" 14 | [200, {"Content-Type" => "application/x-www-form-urlencoded"}, "expires_in=600&access_token=salmon&refresh_token=trout"] 15 | when "json" 16 | [200, {"Content-Type" => "application/json"}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}'] 17 | else raise ArgumentError, "Bad @mode: #{@mode}" 18 | end 19 | end 20 | end 21 | end 22 | cli 23 | end 24 | 25 | describe "#authorize_url" do 26 | it "raises NotImplementedError" do 27 | expect { subject.authorize_url }.to raise_error(NotImplementedError) 28 | end 29 | end 30 | 31 | %w[json formencoded].each do |mode| 32 | describe "#get_token (#{mode})" do 33 | before do 34 | @mode = mode 35 | @access = subject.get_token("username", "password") 36 | end 37 | 38 | it "returns AccessToken with same Client" do 39 | expect(@access.client).to eq(client) 40 | end 41 | 42 | it "returns AccessToken with #token" do 43 | expect(@access.token).to eq("salmon") 44 | end 45 | 46 | it "returns AccessToken with #refresh_token" do 47 | expect(@access.refresh_token).to eq("trout") 48 | end 49 | 50 | it "returns AccessToken with #expires_in" do 51 | expect(@access.expires_in).to eq(600) 52 | end 53 | 54 | it "returns AccessToken with #expires_at" do 55 | expect(@access.expires_at).not_to be_nil 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /docs/file.oauth2-2.0.13.gem.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | File: oauth2-2.0.13.gem 8 | 9 | — Documentation by YARD 0.9.37 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 |
36 | 59 | 60 |

3bfe481d98f859f37f3b90ced2b8856a843eef0f2e0263163cccc14430047bc3cd03d28597f48daa3d623b52d692c3b3e7c2dc26df5eb588dd82d28608fba639

61 |
62 | 63 | 68 | 69 |
70 | 71 | -------------------------------------------------------------------------------- /.git-hooks/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # vim: set syntax=ruby 3 | 4 | # Do not rely on Bundler; allow running outside a Bundler context 5 | begin 6 | require "rubygems" 7 | rescue LoadError 8 | # continue 9 | end 10 | 11 | begin 12 | # External gems 13 | require "gitmoji/regex" 14 | 15 | full_text = File.read(ARGV[0]) 16 | # Is the first character a GitMoji? 17 | gitmoji_index = full_text =~ Gitmoji::Regex::REGEX 18 | if gitmoji_index == 0 19 | exit(0) 20 | else 21 | denied = <<~EOM 22 | Oh snap, think again... 23 | 24 | ______ _______ ___ _______ _______ _______ _______ ______ __ 25 | | _ | | | | || || || || || | | | 26 | | | || | ___| | || ___|| ||_ _|| ___|| _ || | 27 | | |_||_ | |___ | || |___ | | | | | |___ | | | || | 28 | | __ || ___| ___| || ___|| _| | | | ___|| |_| ||__| 29 | | | | || |___ | || |___ | |_ | | | |___ | | __ 30 | |___| |_||_______||_______||_______||_______| |___| |_______||______| |__| 31 | 32 | 33 | Did you forget to add a relevant gitmoji? (see https://gitmoji.dev/ for tools) 34 | In this project, a Gitmoji must be the first grapheme of the commit message. 35 | What's a grapheme? 36 | A symbol rendered to be visually identifiable as a single character, but which may be composed of multiple Unicode code points) 37 | Must match: #{Gitmoji::Regex::REGEX} 38 | #{"Found a gitmoji at character index #{gitmoji_index}... not good enough.\n" if gitmoji_index} 39 | Example: git commit -m "✨ My excellent new feature" 40 | 41 | EOM 42 | puts denied 43 | exit(1) 44 | end 45 | rescue LoadError => e 46 | failure = <<~EOM 47 | gitmoji-regex gem not found: #{e.class}: #{e.message}. 48 | Skipping gitmoji check and allowing commit to proceed. 49 | Recommendation: add 'gitmoji-regex' to your development dependencies to enable this check. 50 | 51 | EOM 52 | warn(failure) 53 | exit(0) 54 | end 55 | -------------------------------------------------------------------------------- /docs/file.oauth2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | File: oauth2 8 | 9 | — Documentation by YARD 0.9.37 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 |
36 | 59 | 60 |

module OAuth2
61 | OAUTH_DEBUG: bool

62 | 63 |

DEFAULT_CONFIG: untyped
64 | @config: untyped

65 | 66 |

def self.config: () -> untyped
67 | def self.configure: () { (untyped) -> void } -> void
68 | end

69 |
70 | 71 | 76 | 77 |
78 | 79 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | # Run any command in this library's bin/ without the bin/ prefix! 2 | # Prefer exe version over binstub 3 | PATH_add exe 4 | PATH_add bin 5 | 6 | # Only add things to this file that should be shared with the team. 7 | 8 | # **dotenv** (See end of file for .env.local integration) 9 | # .env would override anything in this file, if enabled. 10 | # .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments. 11 | # Override and customize anything below in your own .env.local 12 | # If you are using dotenv and not direnv, 13 | # copy the following `export` statements to your own .env file. 14 | 15 | ### General Ruby ### 16 | # Turn off Ruby Warnings about deprecated code 17 | # export RUBYOPT="-W0" 18 | 19 | ### External Testing Controls 20 | export K_SOUP_COV_DO=true # Means you want code coverage 21 | export K_SOUP_COV_COMMAND_NAME="Test Coverage" 22 | # Available formats are html, xml, rcov, lcov, json, tty 23 | export K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty" 24 | export K_SOUP_COV_MIN_BRANCH=78 # Means you want to enforce X% branch coverage 25 | export K_SOUP_COV_MIN_LINE=97 # Means you want to enforce X% line coverage 26 | export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met 27 | export K_SOUP_COV_MULTI_FORMATTERS=true 28 | export K_SOUP_COV_OPEN_BIN= # Means don't try to open coverage results in browser 29 | export MAX_ROWS=1 # Setting for simplecov-console gem for tty output, limits to the worst N rows of bad coverage 30 | export KETTLE_TEST_SILENT=true 31 | 32 | # Internal Debugging Controls 33 | export DEBUG=false # do not allow byebug statements (override in .env.local) 34 | export FLOSS_CFG_FUND_DEBUG=false # extra logging to help diagnose issues (override in .env.local) 35 | export FLOSS_CFG_FUND_LOGFILE=tmp/log/debug.log 36 | 37 | # Concurrently developing the rubocop-lts suite? 38 | export RUBOCOP_LTS_LOCAL=false 39 | 40 | # .env would override anything in this file, if `dotenv` is uncommented below. 41 | # .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments, 42 | # and that is why we generally want to leave it commented out. 43 | # dotenv 44 | 45 | # .env.local will override anything in this file. 46 | dotenv_if_exists .env.local 47 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_gem: 2 | rubocop-lts: config/rubygem_rspec.yml 3 | 4 | inherit_from: 5 | - .rubocop_rspec.yml 6 | 7 | plugins: rubocop-on-rbs 8 | 9 | RBS: 10 | Enabled: true 11 | 12 | AllCops: 13 | DisplayCopNames: true # Display the name of the failing cops 14 | Exclude: 15 | - 'gemfiles/vendor/**/*' 16 | - 'vendor/**/*' 17 | - '**/.irbrc' 18 | 19 | Layout/IndentationConsistency: 20 | Exclude: ['*.md'] 21 | 22 | Metrics/BlockLength: 23 | Enabled: false 24 | 25 | Gemspec/RequiredRubyVersion: 26 | Enabled: false 27 | 28 | Metrics/BlockNesting: 29 | Max: 2 30 | 31 | Layout/LineLength: 32 | Enabled: false 33 | 34 | Metrics/ParameterLists: 35 | Max: 4 36 | 37 | Layout/AccessModifierIndentation: 38 | EnforcedStyle: outdent 39 | 40 | Layout/DotPosition: 41 | EnforcedStyle: trailing 42 | 43 | Layout/SpaceInsideHashLiteralBraces: 44 | EnforcedStyle: no_space 45 | 46 | Lint/UnusedBlockArgument: 47 | Exclude: 48 | - 'spec/**/*.rb' 49 | - 'gemfiles/vendor/**/*' 50 | - 'vendor/**/*' 51 | - '**/.irbrc' 52 | 53 | # Test if we can turn this back on after upgrading rubocop-md. 54 | # It is still an open issue, so not expecting it to be fixed. 55 | # See: https://github.com/rubocop/rubocop-md/issues/28 56 | Layout/InitialIndentation: 57 | Enabled: false 58 | 59 | Style/ClassVars: 60 | Enabled: false 61 | 62 | Style/CollectionMethods: 63 | PreferredMethods: 64 | map: 'collect' 65 | reduce: 'inject' 66 | find: 'detect' 67 | find_all: 'select' 68 | 69 | Style/Documentation: 70 | Enabled: false 71 | 72 | Style/DoubleNegation: 73 | Enabled: false 74 | 75 | Style/EmptyMethod: 76 | EnforcedStyle: expanded 77 | 78 | Style/Encoding: 79 | Enabled: false 80 | 81 | # Does not work with older rubies 82 | #Style/MapToHash: 83 | # Enabled: false 84 | 85 | # Does not work with older rubies 86 | #Style/RedundantBegin: 87 | # Enabled: false 88 | 89 | Style/TrailingCommaInArrayLiteral: 90 | EnforcedStyleForMultiline: comma 91 | 92 | Style/TrailingCommaInHashLiteral: 93 | EnforcedStyleForMultiline: comma 94 | 95 | Gemspec/DependencyVersion: 96 | Enabled: false 97 | 98 | Lint/LiteralInInterpolation: 99 | Exclude: 100 | - 'spec/**/*.rb' 101 | -------------------------------------------------------------------------------- /.github/workflows/style.yml: -------------------------------------------------------------------------------- 1 | name: Style 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'main' 10 | - '*-stable' 11 | tags: 12 | - '!*' # Do not execute on tags 13 | pull_request: 14 | branches: 15 | - '*' 16 | # Allow manually triggering the workflow. 17 | workflow_dispatch: 18 | 19 | # Cancels all previous workflow runs for the same branch that have not yet completed. 20 | concurrency: 21 | # The concurrency group contains the workflow name and the branch name. 22 | group: "${{ github.workflow }}-${{ github.ref }}" 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | rubocop: 27 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 28 | name: Style on ${{ matrix.ruby }}@current 29 | runs-on: ubuntu-latest 30 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 31 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 32 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | include: 37 | # Style 38 | - ruby: "ruby" 39 | appraisal: "style" 40 | exec_cmd: "rake rubocop_gradual:check" 41 | gemfile: "Appraisal.root" 42 | rubygems: latest 43 | bundler: latest 44 | 45 | steps: 46 | - name: Checkout 47 | uses: actions/checkout@v6 48 | 49 | - name: Setup Ruby & RubyGems 50 | uses: ruby/setup-ruby@v1 51 | with: 52 | ruby-version: ${{ matrix.ruby }} 53 | rubygems: ${{ matrix.rubygems }} 54 | bundler: ${{ matrix.bundler }} 55 | bundler-cache: false 56 | 57 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 58 | # We need to do this first to get appraisal installed. 59 | # NOTE: This does not use the primary Gemfile at all. 60 | - name: Install Root Appraisal 61 | run: bundle 62 | - name: Appraisal for ${{ matrix.appraisal }} 63 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 64 | - name: Run ${{ matrix.appraisal }} checks via ${{ matrix.exec_cmd }} 65 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 66 | - name: Validate RBS Types 67 | run: bundle exec appraisal ${{ matrix.appraisal }} bin/rbs validate 68 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | # Targets the evergreen latest release of ruby, truffleruby, and jruby 2 | name: Windows 3 | 4 | permissions: 5 | contents: read 6 | 7 | env: 8 | K_SOUP_COV_DO: false 9 | 10 | on: 11 | push: 12 | branches: 13 | - 'main' 14 | - '*-stable' 15 | tags: 16 | - '!*' # Do not execute on tags 17 | pull_request: 18 | branches: 19 | - '*' 20 | # Allow manually triggering the workflow. 21 | workflow_dispatch: 22 | 23 | # Cancels all previous workflow runs for the same branch that have not yet completed. 24 | concurrency: 25 | # The concurrency group contains the workflow name and the branch name. 26 | group: "${{ github.workflow }}-${{ github.ref }}" 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | test: 31 | name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal }} 32 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 33 | runs-on: windows-latest 34 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 35 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 36 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 37 | strategy: 38 | matrix: 39 | include: 40 | # Ruby 3.4 41 | - ruby: "ruby" 42 | appraisal: "current" 43 | exec_cmd: "rake test" 44 | gemfile: "Appraisal.root" 45 | rubygems: latest 46 | bundler: latest 47 | 48 | steps: 49 | - name: Checkout 50 | uses: actions/checkout@v6 51 | 52 | - name: Setup Ruby & RubyGems 53 | uses: ruby/setup-ruby@v1 54 | with: 55 | ruby-version: ${{ matrix.ruby }} 56 | rubygems: ${{ matrix.rubygems }} 57 | bundler: ${{ matrix.bundler }} 58 | bundler-cache: false 59 | 60 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 61 | # We need to do this first to get appraisal installed. 62 | # NOTE: This does not use the primary Gemfile at all. 63 | - name: Install Root Appraisal 64 | run: bundle 65 | - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }} 66 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 67 | - name: Tests for ${{ matrix.ruby }}@${{ matrix.appraisal }} via ${{ matrix.exec_cmd }} 68 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 69 | -------------------------------------------------------------------------------- /lib/oauth2/strategy/auth_code.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | module Strategy 5 | # The Authorization Code Strategy 6 | # 7 | # OAuth 2.1 notes: 8 | # - PKCE is required for all OAuth clients using the authorization code flow (especially public clients). 9 | # This library does not enforce PKCE generation/verification; implement PKCE in your application when required. 10 | # - Redirect URIs must be compared using exact string matching by the Authorization Server. 11 | # This client forwards redirect_uri but does not perform server-side validation. 12 | # 13 | # References: 14 | # - OAuth 2.1 draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13 15 | # - OAuth for native apps (RFC 8252) and PKCE (RFC 7636) 16 | # 17 | # @see http://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-15#section-4.1 18 | class AuthCode < Base 19 | # The required query parameters for the authorize URL 20 | # 21 | # @param [Hash] params additional query parameters 22 | def authorize_params(params = {}) 23 | params.merge("response_type" => "code", "client_id" => @client.id) 24 | end 25 | 26 | # The authorization URL endpoint of the provider 27 | # 28 | # @param [Hash] params additional query parameters for the URL 29 | def authorize_url(params = {}) 30 | assert_valid_params(params) 31 | @client.authorize_url(authorize_params.merge(params)) 32 | end 33 | 34 | # Retrieve an access token given the specified validation code. 35 | # 36 | # @param [String] code The Authorization Code value 37 | # @param [Hash] params additional params 38 | # @param [Hash] opts access_token_opts, @see Client#get_token 39 | # @note that you must also provide a :redirect_uri with most OAuth 2.0 providers 40 | def get_token(code, params = {}, opts = {}) 41 | params = {"grant_type" => "authorization_code", "code" => code}.merge(@client.redirection_params).merge(params) 42 | params_dup = params.dup 43 | params.each_key do |key| 44 | params_dup[key.to_s] = params_dup.delete(key) if key.is_a?(Symbol) 45 | end 46 | 47 | @client.get_token(params_dup, opts) 48 | end 49 | 50 | private 51 | 52 | def assert_valid_params(params) 53 | raise(ArgumentError, "client_secret is not allowed in authorize URL query params") if params.key?(:client_secret) || params.key?("client_secret") 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /sig/oauth2/client.rbs: -------------------------------------------------------------------------------- 1 | module OAuth2 2 | class Client 3 | RESERVED_REQ_KEYS: Array[String] 4 | RESERVED_PARAM_KEYS: Array[String] 5 | 6 | include OAuth2::FilteredAttributes 7 | 8 | attr_reader id: String 9 | attr_reader secret: String 10 | attr_reader site: String? 11 | attr_accessor options: Hash[Symbol, untyped] 12 | attr_writer connection: untyped 13 | 14 | def initialize: (String client_id, String client_secret, ?Hash[Symbol, untyped]) { (untyped) -> void } -> void 15 | 16 | def site=: (String) -> String 17 | 18 | def connection: () -> untyped 19 | 20 | def authorize_url: (?Hash[untyped, untyped]) -> String 21 | def token_url: (?Hash[untyped, untyped]) -> String 22 | def revoke_url: (?Hash[untyped, untyped]) -> String 23 | 24 | def request: (Symbol verb, String url, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 25 | 26 | def get_token: (Hash[untyped, untyped] params, ?Hash[Symbol, untyped] access_token_opts, ?Proc) { (Hash[Symbol, untyped]) -> void } -> (OAuth2::AccessToken | nil) 27 | 28 | def revoke_token: (String token, ?String token_type_hint, ?Hash[Symbol, untyped]) { (untyped) -> void } -> OAuth2::Response 29 | 30 | def http_method: () -> Symbol 31 | 32 | def auth_code: () -> OAuth2::Strategy::AuthCode 33 | def implicit: () -> OAuth2::Strategy::Implicit 34 | def password: () -> OAuth2::Strategy::Password 35 | def client_credentials: () -> OAuth2::Strategy::ClientCredentials 36 | def assertion: () -> OAuth2::Strategy::Assertion 37 | 38 | def redirection_params: () -> Hash[String, String] 39 | 40 | private 41 | 42 | def params_to_req_opts: (Hash[untyped, untyped]) -> Hash[Symbol, untyped] 43 | def parse_snaky_params_headers: (Hash[untyped, untyped]) -> [Symbol, bool, untyped, (Symbol | nil), Hash[untyped, untyped], Hash[String, String]] 44 | def execute_request: (Symbol verb, String url, ?Hash[Symbol, untyped]) { (Faraday::Request) -> void } -> OAuth2::Response 45 | def authenticator: () -> OAuth2::Authenticator 46 | def parse_response_legacy: (OAuth2::Response, Hash[Symbol, untyped], Proc) -> (OAuth2::AccessToken | nil) 47 | def parse_response: (OAuth2::Response, Hash[Symbol, untyped]) -> (OAuth2::AccessToken | nil) 48 | def build_access_token: (OAuth2::Response, Hash[Symbol, untyped], untyped) -> OAuth2::AccessToken 49 | def build_access_token_legacy: (OAuth2::Response, Hash[Symbol, untyped], Proc) -> (OAuth2::AccessToken | nil) 50 | def oauth_debug_logging: (untyped) -> void 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /.github/workflows/jruby.yml: -------------------------------------------------------------------------------- 1 | name: JRuby 2 | 3 | permissions: 4 | contents: read 5 | 6 | env: 7 | K_SOUP_COV_DO: false 8 | 9 | on: 10 | push: 11 | branches: 12 | - 'main' 13 | - '*-stable' 14 | tags: 15 | - '!*' # Do not execute on tags 16 | pull_request: 17 | branches: 18 | - '*' 19 | # Allow manually triggering the workflow. 20 | workflow_dispatch: 21 | 22 | # Cancels all previous workflow runs for the same branch that have not yet completed. 23 | concurrency: 24 | # The concurrency group contains the workflow name and the branch name. 25 | group: "${{ github.workflow }}-${{ github.ref }}" 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | test: 30 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 31 | name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} 32 | runs-on: ubuntu-22.04 33 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 34 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 35 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 36 | strategy: 37 | matrix: 38 | include: 39 | # jruby-9.4 (targets Ruby 3.1 compatibility) 40 | - ruby: "jruby-9.4" 41 | appraisal: "ruby-3-1" 42 | exec_cmd: "rake test" 43 | gemfile: "Appraisal.root" 44 | rubygems: default 45 | bundler: default 46 | 47 | steps: 48 | - name: Checkout 49 | if: ${{ !env.ACT }} 50 | uses: actions/checkout@v6 51 | 52 | - name: Setup Ruby & RubyGems 53 | if: ${{ !env.ACT }} 54 | uses: ruby/setup-ruby@v1 55 | with: 56 | ruby-version: ${{ matrix.ruby }} 57 | rubygems: ${{ matrix.rubygems }} 58 | bundler: ${{ matrix.bundler }} 59 | bundler-cache: false 60 | 61 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 62 | # We need to do this first to get appraisal installed. 63 | # NOTE: This does not use the primary Gemfile at all. 64 | - name: Install Root Appraisal 65 | if: ${{ !env.ACT }} 66 | run: bundle 67 | - name: Appraisal for ${{ matrix.appraisal }} 68 | if: ${{ !env.ACT }} 69 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 70 | - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} 71 | if: ${{ !env.ACT }} 72 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 73 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main, '*-stable' ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main, '*-stable' ] 20 | schedule: 21 | - cron: '35 1 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'ruby' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v6 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v4 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v4 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v4 71 | -------------------------------------------------------------------------------- /.github/workflows/legacy.yml: -------------------------------------------------------------------------------- 1 | name: MRI 3.0, 3.1 (EOL) 2 | 3 | permissions: 4 | contents: read 5 | 6 | env: 7 | K_SOUP_COV_DO: false 8 | 9 | on: 10 | push: 11 | branches: 12 | - 'main' 13 | - '*-stable' 14 | tags: 15 | - '!*' # Do not execute on tags 16 | pull_request: 17 | branches: 18 | - '*' 19 | # Allow manually triggering the workflow. 20 | workflow_dispatch: 21 | 22 | # Cancels all previous workflow runs for the same branch that have not yet completed. 23 | concurrency: 24 | # The concurrency group contains the workflow name and the branch name. 25 | group: "${{ github.workflow }}-${{ github.ref }}" 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | test: 30 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 31 | name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} 32 | runs-on: ubuntu-22.04 33 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 34 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 35 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | include: 40 | # Ruby 3.0 41 | - ruby: "ruby-3.0" 42 | appraisal: "ruby-3-0" 43 | exec_cmd: "rake test" 44 | gemfile: "Appraisal.root" 45 | rubygems: '3.5.23' 46 | bundler: '2.5.23' 47 | 48 | # Ruby 3.1 49 | - ruby: "ruby-3.1" 50 | appraisal: "ruby-3-1" 51 | exec_cmd: "rake test" 52 | gemfile: "Appraisal.root" 53 | rubygems: '3.6.9' 54 | bundler: '2.6.9' 55 | 56 | steps: 57 | - name: Checkout 58 | uses: actions/checkout@v6 59 | 60 | - name: Setup Ruby & RubyGems 61 | uses: ruby/setup-ruby@v1 62 | with: 63 | ruby-version: ${{ matrix.ruby }} 64 | rubygems: ${{ matrix.rubygems }} 65 | bundler: ${{ matrix.bundler }} 66 | bundler-cache: false 67 | 68 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 69 | # We need to do this first to get appraisal installed. 70 | # NOTE: This does not use the primary Gemfile at all. 71 | - name: Install Root Appraisal 72 | run: bundle 73 | - name: Appraisal for ${{ matrix.appraisal }} 74 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 75 | - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} 76 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 77 | -------------------------------------------------------------------------------- /.github/workflows/supported.yml: -------------------------------------------------------------------------------- 1 | name: MRI Non-EOL 2 | 3 | permissions: 4 | contents: read 5 | 6 | env: 7 | K_SOUP_COV_DO: false 8 | 9 | on: 10 | push: 11 | branches: 12 | - 'main' 13 | - '*-stable' 14 | tags: 15 | - '!*' # Do not execute on tags 16 | pull_request: 17 | branches: 18 | - '*' 19 | # Allow manually triggering the workflow. 20 | workflow_dispatch: 21 | 22 | # Cancels all previous workflow runs for the same branch that have not yet completed. 23 | concurrency: 24 | # The concurrency group contains the workflow name and the branch name. 25 | group: "${{ github.workflow }}-${{ github.ref }}" 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | test: 30 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 31 | name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} 32 | runs-on: ubuntu-latest 33 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 34 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 35 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 36 | strategy: 37 | matrix: 38 | include: 39 | # Ruby 3.2 40 | - ruby: "ruby-3.2" 41 | appraisal: "ruby-3-2" 42 | exec_cmd: "rake test" 43 | gemfile: "Appraisal.root" 44 | rubygems: latest 45 | bundler: latest 46 | 47 | # Ruby 3.3 48 | - ruby: "ruby-3.3" 49 | appraisal: "ruby-3-3" 50 | exec_cmd: "rake test" 51 | gemfile: "Appraisal.root" 52 | rubygems: latest 53 | bundler: latest 54 | 55 | steps: 56 | - name: Checkout 57 | uses: actions/checkout@v6 58 | 59 | - name: Setup Ruby & RubyGems 60 | uses: ruby/setup-ruby@v1 61 | with: 62 | ruby-version: ${{ matrix.ruby }} 63 | rubygems: ${{ matrix.rubygems }} 64 | bundler: ${{ matrix.bundler }} 65 | bundler-cache: false 66 | 67 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 68 | # We need to do this first to get appraisal installed. 69 | # NOTE: This does not use the primary Gemfile at all. 70 | - name: Install Root Appraisal 71 | run: bundle 72 | - name: Appraisal for ${{ matrix.ruby }} ${{ matrix.appraisal }} 73 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 74 | - name: Tests for ${{ matrix.ruby }} ${{ matrix.appraisal }} via ${{ matrix.exec_cmd }} 75 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 76 | -------------------------------------------------------------------------------- /.github/workflows/unsupported.yml: -------------------------------------------------------------------------------- 1 | name: MRI 2.6 & 2.7 (EOL) 2 | 3 | permissions: 4 | contents: read 5 | 6 | env: 7 | K_SOUP_COV_DO: false 8 | 9 | on: 10 | push: 11 | branches: 12 | - 'main' 13 | - '*-stable' 14 | tags: 15 | - '!*' # Do not execute on tags 16 | pull_request: 17 | branches: 18 | - '*' 19 | # Allow manually triggering the workflow. 20 | workflow_dispatch: 21 | 22 | # Cancels all previous workflow runs for the same branch that have not yet completed. 23 | concurrency: 24 | # The concurrency group contains the workflow name and the branch name. 25 | group: "${{ github.workflow }}-${{ github.ref }}" 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | test: 30 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 31 | name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} 32 | runs-on: ubuntu-22.04 33 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 34 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 35 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | include: 40 | # Ruby 2.6 41 | - ruby: "ruby-2.6" 42 | appraisal: "ruby-2-6" 43 | exec_cmd: "rake test" 44 | gemfile: "Appraisal.root" 45 | rubygems: '3.4.22' 46 | bundler: '2.4.22' 47 | 48 | # Ruby 2.7 49 | - ruby: "ruby-2.7" 50 | appraisal: "ruby-2-7" 51 | exec_cmd: "rake test" 52 | gemfile: "Appraisal.root" 53 | rubygems: '3.4.22' 54 | bundler: '2.4.22' 55 | 56 | steps: 57 | - name: Checkout 58 | uses: actions/checkout@v6 59 | 60 | - name: Setup Ruby & RubyGems 61 | uses: ruby/setup-ruby@v1 62 | with: 63 | ruby-version: ${{ matrix.ruby }} 64 | rubygems: ${{ matrix.rubygems }} 65 | bundler: ${{ matrix.bundler }} 66 | bundler-cache: false 67 | 68 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 69 | # We need to do this first to get appraisal installed. 70 | # NOTE: This does not use the primary Gemfile at all. 71 | - name: Install Root Appraisal 72 | run: bundle 73 | - name: Appraisal for ${{ matrix.appraisal }} 74 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 75 | - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} 76 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 77 | -------------------------------------------------------------------------------- /lib/oauth2.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # includes modules from stdlib 4 | require "cgi" 5 | require "time" 6 | 7 | # third party gems 8 | require "snaky_hash" 9 | require "version_gem" 10 | 11 | # includes gem files 12 | require_relative "oauth2/version" 13 | require_relative "oauth2/filtered_attributes" 14 | require_relative "oauth2/error" 15 | require_relative "oauth2/authenticator" 16 | require_relative "oauth2/client" 17 | require_relative "oauth2/strategy/base" 18 | require_relative "oauth2/strategy/auth_code" 19 | require_relative "oauth2/strategy/implicit" 20 | require_relative "oauth2/strategy/password" 21 | require_relative "oauth2/strategy/client_credentials" 22 | require_relative "oauth2/strategy/assertion" 23 | require_relative "oauth2/access_token" 24 | require_relative "oauth2/response" 25 | 26 | # The namespace of this library 27 | # 28 | # This module is the entry point and top-level namespace for the oauth2 gem. 29 | # It exposes configuration, constants, and requires the primary public classes. 30 | module OAuth2 31 | # When true, enables verbose HTTP logging via Faraday's logger middleware. 32 | # Controlled by the OAUTH_DEBUG environment variable. Any case-insensitive 33 | # value equal to "true" will enable debugging. 34 | # 35 | # @return [Boolean] 36 | OAUTH_DEBUG = ENV.fetch("OAUTH_DEBUG", "false").casecmp("true").zero? 37 | 38 | # Default configuration values for the oauth2 library. 39 | # 40 | # @example Toggle warnings 41 | # OAuth2.configure do |config| 42 | # config[:silence_extra_tokens_warning] = false 43 | # config[:silence_no_tokens_warning] = false 44 | # end 45 | # 46 | # @return [SnakyHash::SymbolKeyed] A mutable Hash-like config with symbol keys 47 | DEFAULT_CONFIG = SnakyHash::SymbolKeyed.new( 48 | silence_extra_tokens_warning: true, 49 | silence_no_tokens_warning: true, 50 | ) 51 | 52 | # The current runtime configuration for the library. 53 | # 54 | # @return [SnakyHash::SymbolKeyed] 55 | @config = DEFAULT_CONFIG.dup 56 | 57 | class << self 58 | # Access the current configuration. 59 | # 60 | # Prefer using {OAuth2.configure} to mutate configuration. 61 | # 62 | # @return [SnakyHash::SymbolKeyed] 63 | attr_reader :config 64 | end 65 | 66 | # Configure global library behavior. 67 | # 68 | # Yields the mutable configuration object so callers can update settings. 69 | # 70 | # @yieldparam [SnakyHash::SymbolKeyed] config the configuration object 71 | # @return [void] 72 | def configure 73 | yield @config 74 | end 75 | module_function :configure 76 | end 77 | 78 | # Extend OAuth2::Version with VersionGem helpers to provide semantic version helpers. 79 | OAuth2::Version.class_eval do 80 | extend VersionGem::Basic 81 | end 82 | -------------------------------------------------------------------------------- /lib/oauth2/error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module OAuth2 4 | # Represents an OAuth2 error condition. 5 | # 6 | # Wraps details from an OAuth2::Response or Hash payload returned by an 7 | # authorization server, exposing error code and description per RFC 6749. 8 | class Error < StandardError 9 | # @return [OAuth2::Response, Hash, Object] Original response or payload used to build the error 10 | # @return [String] Raw body content (if available) 11 | # @return [String, nil] Error code (e.g., 'invalid_grant') 12 | # @return [String, nil] Human-readable description for the error 13 | attr_reader :response, :body, :code, :description 14 | 15 | # Create a new OAuth2::Error 16 | # 17 | # @param [OAuth2::Response, Hash, Object] response A Response or error payload 18 | def initialize(response) 19 | @response = response 20 | if response.respond_to?(:parsed) 21 | if response.parsed.is_a?(Hash) 22 | @code = response.parsed["error"] 23 | @description = response.parsed["error_description"] 24 | end 25 | elsif response.is_a?(Hash) 26 | @code = response["error"] 27 | @description = response["error_description"] 28 | end 29 | @body = if response.respond_to?(:body) 30 | response.body 31 | else 32 | @response 33 | end 34 | message_opts = parse_error_description(@code, @description) 35 | super(error_message(@body, message_opts)) 36 | end 37 | 38 | private 39 | 40 | # Builds a multi-line error message including description and raw body. 41 | # 42 | # @param [String, #encode] response_body Response body content 43 | # @param [Hash] opts Options including :error_description 44 | # @return [String] Message suitable for StandardError 45 | def error_message(response_body, opts = {}) 46 | lines = [] 47 | 48 | lines << opts[:error_description] if opts[:error_description] 49 | 50 | error_string = if response_body.respond_to?(:encode) && opts[:error_description].respond_to?(:encoding) 51 | script_encoding = opts[:error_description].encoding 52 | response_body.encode(script_encoding, invalid: :replace, undef: :replace) 53 | else 54 | response_body 55 | end 56 | 57 | lines << error_string 58 | 59 | lines.join("\n") 60 | end 61 | 62 | # Formats the OAuth2 error code and description into a single string. 63 | # 64 | # @param [String, nil] code OAuth2 error code 65 | # @param [String, nil] description OAuth2 error description 66 | # @return [Hash] Options hash containing :error_description when present 67 | def parse_error_description(code, description) 68 | return {} unless code || description 69 | 70 | error_description = "" 71 | error_description += "#{code}: " if code 72 | error_description += description if description 73 | 74 | {error_description: error_description} 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /.github/workflows/ancient.yml: -------------------------------------------------------------------------------- 1 | name: MRI 2.4, 2.5 (EOL) 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'main' 10 | - '*-stable' 11 | tags: 12 | - '!*' # Do not execute on tags 13 | pull_request: 14 | branches: 15 | - '*' 16 | # Allow manually triggering the workflow. 17 | workflow_dispatch: 18 | 19 | # Cancels all previous workflow runs for the same branch that have not yet completed. 20 | concurrency: 21 | # The concurrency group contains the workflow name and the branch name. 22 | group: "${{ github.workflow }}-${{ github.ref }}" 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | test: 27 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 28 | name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} 29 | runs-on: ubuntu-22.04 30 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 31 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 32 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | include: 37 | # Ruby 2.3 is tested heavily by caboose.yml 38 | # # Ruby 2.3 39 | # - ruby: "ruby-2.3" 40 | # appraisal: "ruby-2-3" 41 | # exec_cmd: "rake test" 42 | # gemfile: "Appraisal.root" 43 | # rubygems: "3.3.27" 44 | # bundler: "2.3.27" 45 | 46 | # Ruby 2.4 47 | - ruby: "ruby-2.4" 48 | appraisal: "ruby-2-4" 49 | exec_cmd: "rake test" 50 | gemfile: "Appraisal.root" 51 | rubygems: "3.3.27" 52 | bundler: "2.3.27" 53 | 54 | # Ruby 2.5 55 | - ruby: "ruby-2.5" 56 | appraisal: "ruby-2-5" 57 | exec_cmd: "rake test" 58 | gemfile: "Appraisal.root" 59 | rubygems: "3.3.27" 60 | bundler: "2.3.27" 61 | 62 | steps: 63 | - name: Checkout 64 | uses: actions/checkout@v6 65 | 66 | - name: Setup Ruby & RubyGems 67 | uses: ruby/setup-ruby@v1 68 | with: 69 | ruby-version: ${{ matrix.ruby }} 70 | rubygems: ${{ matrix.rubygems }} 71 | bundler: ${{ matrix.bundler }} 72 | bundler-cache: false 73 | 74 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 75 | # We need to do this first to get appraisal installed. 76 | # NOTE: This does not use the primary Gemfile at all. 77 | - name: Install Root Appraisal 78 | run: bundle 79 | - name: Appraisal for ${{ matrix.appraisal }} 80 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 81 | - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} 82 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 83 | -------------------------------------------------------------------------------- /docs/OAuth2/Version.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Module: OAuth2::Version 8 | 9 | — Documentation by YARD 0.9.37 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 |
36 | 61 | 62 |

Module: OAuth2::Version 63 | 64 | 65 | 66 |

67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 |
Defined in:
81 |
lib/oauth2/version.rb
82 |
83 | 84 |
85 | 86 | 87 | 88 |

89 | Constant Summary 90 | collapse 91 |

92 | 93 |
94 | 95 |
VERSION = 96 | 97 |
98 |
"2.0.18"
99 | 100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
112 | 113 | 118 | 119 |
120 | 121 | -------------------------------------------------------------------------------- /.github/workflows/locked_deps.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Lock/Unlock Deps Pattern 3 | # 4 | # Two often conflicting goals resolved! 5 | # 6 | # - unlocked_deps.yml 7 | # - All runtime & dev dependencies, but does not have a `gemfiles/*.gemfile.lock` committed 8 | # - Uses an Appraisal2 "unlocked_deps" gemfile, and the current MRI Ruby release 9 | # - Know when new dependency releases will break local dev with unlocked dependencies 10 | # - Broken workflow indicates that new releases of dependencies may not work 11 | # 12 | # - locked_deps.yml 13 | # - All runtime & dev dependencies, and has a `Gemfile.lock` committed 14 | # - Uses the project's main Gemfile, and the current MRI Ruby release 15 | # - Matches what contributors and maintainers use locally for development 16 | # - Broken workflow indicates that a new contributor will have a bad time 17 | # 18 | name: Deps Locked 19 | 20 | permissions: 21 | contents: read 22 | 23 | env: 24 | # Running coverage, but not validating minimum coverage, 25 | # because it would be redundant with the coverage workflow. 26 | # Also we can validate all output formats without breaking CodeCov, 27 | # since we aren't submitting these reports anywhere. 28 | K_SOUP_COV_MIN_BRANCH: 71 29 | K_SOUP_COV_MIN_LINE: 86 30 | K_SOUP_COV_MIN_HARD: false 31 | K_SOUP_COV_FORMATTERS: "html,xml,rcov,lcov,json,tty" 32 | K_SOUP_COV_DO: true 33 | K_SOUP_COV_MULTI_FORMATTERS: true 34 | K_SOUP_COV_COMMAND_NAME: "Test Coverage" 35 | 36 | on: 37 | push: 38 | branches: 39 | - 'main' 40 | - '*-stable' 41 | tags: 42 | - '!*' # Do not execute on tags 43 | pull_request: 44 | branches: 45 | - '*' 46 | # Allow manually triggering the workflow. 47 | workflow_dispatch: 48 | 49 | # Cancels all previous workflow runs for the same branch that have not yet completed. 50 | concurrency: 51 | # The concurrency group contains the workflow name and the branch name. 52 | group: "${{ github.workflow }}-${{ github.ref }}" 53 | cancel-in-progress: true 54 | 55 | jobs: 56 | test: 57 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 58 | name: Default rake task w/ main Gemfile.lock ${{ matrix.name_extra || '' }} 59 | runs-on: ubuntu-latest 60 | continue-on-error: ${{ matrix.experimental }} 61 | strategy: 62 | fail-fast: false 63 | matrix: 64 | include: 65 | # Ruby 66 | - ruby: "ruby" 67 | exec_cmd: "rake" 68 | rubygems: latest 69 | bundler: latest 70 | experimental: false 71 | 72 | steps: 73 | - name: Checkout 74 | uses: actions/checkout@v6 75 | 76 | - name: Setup Ruby & RubyGems 77 | uses: ruby/setup-ruby@v1 78 | with: 79 | ruby-version: ${{ matrix.ruby }} 80 | rubygems: ${{ matrix.rubygems }} 81 | bundler: ${{ matrix.bundler }} 82 | bundler-cache: true 83 | 84 | - name: Checks the kitchen sink via ${{ matrix.exec_cmd }} 85 | run: bundle exec ${{ matrix.exec_cmd }} 86 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | # Targets the evergreen latest release of ruby, truffleruby, and jruby 2 | name: MacOS 3 | 4 | permissions: 5 | contents: read 6 | 7 | env: 8 | K_SOUP_COV_DO: false 9 | 10 | on: 11 | push: 12 | branches: 13 | - 'main' 14 | - '*-stable' 15 | tags: 16 | - '!*' # Do not execute on tags 17 | pull_request: 18 | branches: 19 | - '*' 20 | # Allow manually triggering the workflow. 21 | workflow_dispatch: 22 | 23 | # Cancels all previous workflow runs for the same branch that have not yet completed. 24 | concurrency: 25 | # The concurrency group contains the workflow name and the branch name. 26 | group: "${{ github.workflow }}-${{ github.ref }}" 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | test: 31 | name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal }} 32 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 33 | runs-on: macos-latest 34 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 35 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 36 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 37 | strategy: 38 | matrix: 39 | include: 40 | # Ruby 3.4 41 | - ruby: "ruby" 42 | appraisal: "current" 43 | exec_cmd: "rake test" 44 | gemfile: "Appraisal.root" 45 | rubygems: latest 46 | bundler: latest 47 | 48 | # truffleruby-24.1 49 | # (according to documentation: targets Ruby 3.3 compatibility) 50 | # (according to runtime: targets Ruby 3.2 compatibility) 51 | - ruby: "truffleruby" 52 | appraisal: "current" 53 | exec_cmd: "rake test" 54 | gemfile: "Appraisal.root" 55 | rubygems: default 56 | bundler: default 57 | 58 | # jruby-10.0 (targets Ruby 3.4 compatibility) 59 | - ruby: "jruby" 60 | appraisal: "current" 61 | exec_cmd: "rake test" 62 | gemfile: "Appraisal.root" 63 | rubygems: default 64 | bundler: default 65 | 66 | steps: 67 | - name: Checkout 68 | uses: actions/checkout@v6 69 | 70 | - name: Setup Ruby & RubyGems 71 | uses: ruby/setup-ruby@v1 72 | with: 73 | ruby-version: ${{ matrix.ruby }} 74 | rubygems: ${{ matrix.rubygems }} 75 | bundler: ${{ matrix.bundler }} 76 | bundler-cache: false 77 | 78 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 79 | # We need to do this first to get appraisal installed. 80 | # NOTE: This does not use the primary Gemfile at all. 81 | - name: Install Root Appraisal 82 | run: bundle 83 | - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }} 84 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle 85 | - name: Tests for ${{ matrix.ruby }}@${{ matrix.appraisal }} via ${{ matrix.exec_cmd }} 86 | run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} 87 | -------------------------------------------------------------------------------- /THREAT_MODEL.md: -------------------------------------------------------------------------------- 1 | # Threat Model Outline for oauth2 Ruby Gem 2 | 3 | ## 1. Overview 4 | This document outlines the threat model for the `oauth2` Ruby gem, which implements OAuth 2.0, 2.1, and OIDC Core protocols. The gem is used to facilitate secure authorization and authentication in Ruby applications. 5 | 6 | ## 2. Assets to Protect 7 | - OAuth access tokens, refresh tokens, and ID tokens 8 | - User credentials (if handled) 9 | - Client secrets and application credentials 10 | - Sensitive user data accessed via OAuth 11 | - Private keys and certificates (for signing/verifying tokens) 12 | 13 | ## 3. Potential Threat Actors 14 | - External attackers (internet-based) 15 | - Malicious OAuth clients or resource servers 16 | - Insiders (developers, maintainers) 17 | - Compromised dependencies 18 | 19 | ## 4. Attack Surfaces 20 | - OAuth endpoints (authorization, token, revocation, introspection) 21 | - HTTP request/response handling 22 | - Token storage and management 23 | - Configuration files and environment variables 24 | - Dependency supply chain 25 | 26 | ## 5. Threats and Mitigations 27 | 28 | ### 5.1 Token Leakage 29 | - **Threat:** Tokens exposed via logs, URLs, or insecure storage 30 | - **Mitigations:** 31 | - Avoid logging sensitive tokens 32 | - Use secure storage mechanisms 33 | - Never expose tokens in URLs 34 | 35 | ### 5.2 Token Replay and Forgery 36 | - **Threat:** Attackers reuse or forge tokens 37 | - **Mitigations:** 38 | - Validate token signatures and claims 39 | - Use short-lived tokens and refresh tokens 40 | - Implement token revocation 41 | 42 | ### 5.3 Insecure Communication 43 | - **Threat:** Data intercepted via MITM attacks 44 | - **Mitigations:** 45 | - Enforce HTTPS for all communications 46 | - Validate SSL/TLS certificates 47 | 48 | ### 5.4 Client Secret Exposure 49 | - **Threat:** Client secrets leaked in code or version control 50 | - **Mitigations:** 51 | - Store secrets in environment variables or secure vaults 52 | - Never commit secrets to source control 53 | 54 | ### 5.5 Dependency Vulnerabilities 55 | - **Threat:** Vulnerabilities in third-party libraries 56 | - **Mitigations:** 57 | - Regularly update dependencies 58 | - Use tools like `bundler-audit` for vulnerability scanning 59 | 60 | ### 5.6 Improper Input Validation 61 | - **Threat:** Injection attacks via untrusted input 62 | - **Mitigations:** 63 | - Validate and sanitize all inputs 64 | - Use parameterized queries and safe APIs 65 | 66 | ### 5.7 Insufficient Logging and Monitoring 67 | - **Threat:** Attacks go undetected 68 | - **Mitigations:** 69 | - Log security-relevant events (without sensitive data) 70 | - Monitor for suspicious activity 71 | 72 | ## 6. Assumptions 73 | - The gem is used in a secure environment with up-to-date Ruby and dependencies 74 | - End-users are responsible for secure configuration and deployment 75 | 76 | ## 7. Out of Scope 77 | - Security of external OAuth providers 78 | - Application-level business logic 79 | 80 | ## 8. References 81 | - [OAuth 2.0 Threat Model and Security Considerations (RFC 6819)](https://tools.ietf.org/html/rfc6819) 82 | - [OWASP Top Ten](https://owasp.org/www-project-top-ten/) 83 | 84 | --- 85 | This outline should be reviewed and updated regularly as the project evolves. 86 | -------------------------------------------------------------------------------- /.github/workflows/unlocked_deps.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Lock/Unlock Deps Pattern 3 | # 4 | # Two often conflicting goals resolved! 5 | # 6 | # - unlocked_deps.yml 7 | # - All runtime & dev dependencies, but does not have a `gemfiles/*.gemfile.lock` committed 8 | # - Uses an Appraisal2 "unlocked_deps" gemfile, and the current MRI Ruby release 9 | # - Know when new dependency releases will break local dev with unlocked dependencies 10 | # - Broken workflow indicates that new releases of dependencies may not work 11 | # 12 | # - locked_deps.yml 13 | # - All runtime & dev dependencies, and has a `Gemfile.lock` committed 14 | # - Uses the project's main Gemfile, and the current MRI Ruby release 15 | # - Matches what contributors and maintainers use locally for development 16 | # - Broken workflow indicates that a new contributor will have a bad time 17 | # 18 | name: Deps Unlocked 19 | 20 | permissions: 21 | contents: read 22 | 23 | env: 24 | K_SOUP_COV_DO: false 25 | 26 | on: 27 | push: 28 | branches: 29 | - 'main' 30 | - '*-stable' 31 | tags: 32 | - '!*' # Do not execute on tags 33 | pull_request: 34 | branches: 35 | - '*' 36 | # Allow manually triggering the workflow. 37 | workflow_dispatch: 38 | 39 | # Cancels all previous workflow runs for the same branch that have not yet completed. 40 | concurrency: 41 | # The concurrency group contains the workflow name and the branch name. 42 | group: "${{ github.workflow }}-${{ github.ref }}" 43 | cancel-in-progress: true 44 | 45 | jobs: 46 | test: 47 | if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" 48 | name: Default rake task w/ unlocked deps ${{ matrix.name_extra || '' }} 49 | runs-on: ubuntu-latest 50 | continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} 51 | env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps 52 | BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile 53 | strategy: 54 | matrix: 55 | include: 56 | # Ruby 57 | - ruby: "ruby" 58 | appraisal_name: "unlocked_deps" 59 | exec_cmd: "rake" 60 | gemfile: "Appraisal.root" 61 | rubygems: latest 62 | bundler: latest 63 | 64 | steps: 65 | - name: Checkout 66 | uses: actions/checkout@v6 67 | 68 | - name: Setup Ruby & RubyGems 69 | uses: ruby/setup-ruby@v1 70 | with: 71 | ruby-version: ${{ matrix.ruby }} 72 | rubygems: ${{ matrix.rubygems }} 73 | bundler: ${{ matrix.bundler }} 74 | bundler-cache: false 75 | 76 | # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) 77 | # We need to do this first to get appraisal installed. 78 | # NOTE: This does not use the primary Gemfile at all. 79 | - name: Install Root Appraisal 80 | run: bundle 81 | - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} 82 | run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle 83 | - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} 84 | run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} 85 | -------------------------------------------------------------------------------- /spec/fixtures/RS256/jwtRS256.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIJKwIBAAKCAgEA5hdXV/4YSymY1T9VNvK2bWRfulwIty1RnAPNINQmfh3aRRkV 3 | +PNrbC2Crji9G0AHmQwgW1bZ3kgkkpIm6RVn44fHvBvuXkZ9ABgXw0d2cLIHmwOF 4 | xSKmWAm/EW//GszUTLLLsMZUe2udtFJW0jxXB2GRY0WVYuo6Oo58RCeP719lw3Ag 5 | s0YF9/IobxKkGd4BautUPw6ZszAa3o+j0zR74x7ouPxybZAOuPsMxqanyeYJeH4o 6 | sJjLMYV9qem9uG2sj7GENJ8UszcpmGbqxBhexPEB7mgDeONIF0XJF23zdOf8ANE5 7 | mAU2h2v7M6moAfkdUzJ+j48+VT2omHAzAL5yNcmrl2xiWdyoxOw1Y1UmfEmJYV5V 8 | gGYyZ12JZRKY+szPT+vR+MDuYxbquF40O7kvkFNBfL1yCpzfSQCLnEs4rX8qRzZX 9 | ciLeyq4Ht5FLuRFgxjA//XI8LAmp0u7gk+Q7FUH1UgW3kmJDTG0XaxQxYTBSIO7m 10 | cmyjDyBgKVuQmt5E1ycFeteOVdPD/CG/fPYhthvc4UytEFwsMdNy3iD6/wuUH68t 11 | AKam28UZaOb0qK+00cQQD8fulY9rKtSL10LvJFWUOa/SJyLvk9vUmfvFn182il1n 12 | X6GpyxyMmE/FCnH4CT/DjrSZf08mOO8eL5ofYHMK/oiXr1eODqx+pOwClNsCAwEA 13 | AQKCAgEAy34vMFI4WBk04rx9d/hWoQ7Znu8QgjihaZLvEy6t0HJEfUH/bcqS4fyq 14 | C72Aeh452gCgiUeZrf4t4jdCFHhrBg8q9dHaEiTTHocwVPPZ6zd4hH8sCrpnVYth 15 | IWHkw2YOCLtEbFYrl3AI7Na5lHvrGEsREzQSN4Yh83Has0guAy1iyeNb+FFgq/XO 16 | DtX0ri/rHw1717zo8FIGIXn2EK/lNWw7tIcICKAUdUMK/JGd6XD6RUeGYxDu/CAs 17 | kF55/Sd6Kyd7XjKnUwzhS7kRvlYzUog4BgqVr4+LTZHZlFAYtfcJqAtinXFW1ZQJ 18 | eZp9TSlt5wvMZNjx7t92QUNRyEGmrQAU+8COHnT0/drFf0MCiyHSUN0E7/5fswhc 19 | uMSU9XiJA9G0wYvJl4zIuOuIYWZWhIqvjYSkvdlP70t9XO2gk/ZcCWsMW8i+xbwC 20 | w1+MMjsKsNedXxI99TIPPHcCNMxqlt1E1kHH3SAwCuEH/ez7PRMyEQQ0EyAk22x/ 21 | piYIWXkX5835cLbLRIYafXgOiugWZjCwIqfRIcIpscmcijZwCF2DyevveYdx3krR 22 | FGA2PFydFyxCNG7XwvKb9kHb7WBERUPV/H3eCqu2SZ/RvF+I94LUYP4bu6CmFdO9 23 | wCJcGJoL1P7tVhS9lA5Oj0QWczrjnejCoI9XMMduWk032rR1VYECggEBAPZDnTBY 24 | H2uiVmGdMfWTAmX86kiHVpkL03OG6rgvDMsMOYKnik9Lb3gNeUIuPeAWFNrXCoD1 25 | qp0loxPhKSojNOOM8Yiz/GwQ/QI9dzgtxs7E7rFFyTuJcY48Do8uOFyUHbAbeOBF 26 | b9UL/uBfWZGVV1YY753xyqYlCpxTVQGms1jsbVFdZE1iVpOwAkFVuoLYaHLut4zB 27 | 01ORyBSoWan173P+IQH6F1uNXE2Kk/FIMDN6bgP1pXkdkrTx4WjAmRnP/Sc4r38/ 28 | F1xN+gxnWGPUKDVRPYBpVzDR036w65ODgg2FROK2vIxlStiAC/rc0JLsvaWfb1Rn 29 | dsWdJJ1V6mZ6a5sCggEBAO8wC1jcIoiBz3xoA8E5BSt8qLJ7ZuSFaaidvWX2/xj6 30 | lSWJxCGQfhR7P6ozvH6UDo1WbJT6nNyXPkiDkAzcmAdsYVjULW3K2LI9oPajaJxY 31 | L7KJpylgh9JhMvbMz3VVjTgYRt+kjX+3uFMZNx1YfiBP+S6xx5sjK9CKDz3H99kC 32 | q9bX95YFqZ7yFE3aBCR6CENo2tXpMN96CLQGpwa0bwt3xNzC4MhZMXbGR3DdBYbD 33 | tS9lJfQvAVUYxbSE/2FBgjpO6ArMyU2ZUEDFx9J6IhfhVbQV4VeITMyRNo0XwBiQ 34 | /+XpLXgHkw7LiNMIoc7d+M7yLA1Vz7+r8XxWHHZCL8ECggEBAPK8VrYORno7e1Wg 35 | MlxS2WxZzTxMWmlkpLoc5END7SI/HHjSV5wtSORWs40uM0MrwMasa+gNPmzDamjv 36 | 6Tllln4ssO8EKe0DGcAZgefYBzxMFNKbbOzIXyvJurga4Ocv/8tUaOL2znJ67nGO 37 | yqSbRYjR724JpKv7mufXo9SK0gD2mhI3MeSs55WPScnIjJzoXpva/QU7D+gxq7vg 38 | 7PCAP9RfS329W0Sco7yyuXx8oTY8mTBB8ybcpXzBZmNwY/hzcJ42W5XbRFVxbuTH 39 | APL1beSP/UUTkCPIzuTz0mCGoaxeDjZB1Lu2I/4eyLAu80+/FneoHX5etU23xR1o 40 | UDFOvb0CggEBALTTc6CoPAtLaBs7X6tSelAYHEli9bTKD8kEB83wX4b42ozYjEh7 41 | vnWpf8Yi+twO/rlnnws6NCCoztNvcxXmJ6FlFGtdbULV2eFWqjwL6ehY2yZ03sVv 42 | Tv+DsE3ZJPYlyW+hGuO0uazWrilUpNAwuJmhHFdq2+azPkqYNVGVvhB37oWsHGd0 43 | vHmHtkXtDris8VZVDSwu8V3iGnZPmTJ+cn0O/OuRAPM2SyjqWdQ/pA/wIShFpd3n 44 | M3CsG7uP2KokJloCkXaov39E6uEtJRZAc0nudyaAbC4Kw1Tca4tba0SnSm78S/20 45 | bD8BLN2uZvXH5nQ9rYQfXcIgMZ64UygsfYECggEBAIw0fQaIVmafa0Hz3ipD4PJI 46 | 5QNkh2t9hvOCSKm1xYTNATl0q/VIkZoy1WoxY6SSchcObLxQKbJ9ORi4XNr+IJK5 47 | 3C1Qz/3iv/S3/ktgmqGhQiqybkkHZcbqTXB2wxrx+aaLS7PEfYiuYCrPbX93160k 48 | MVns8PjvYU8KCNMbL2e+AiKEt1KkKAZIpNQdeeJOEhV9wuLYFosd400aYssuSOVW 49 | IkJhGI0lT/7FDJaw0LV98DhQtauANPSUQKN5iw6vciwtsaF1kXMfGlMXj58ntiMq 50 | NizQPR6/Ar1ewLPMh1exDoAfLnCIMk8nbSraW+cebLAZctPugUpfpu3j2LM98aE= 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /gemfiles/modular/injected.gemfile: -------------------------------------------------------------------------------- 1 | # NOTE: It is preferable to list development dependencies in the gemspec due to increased 2 | # visibility and discoverability on RubyGems.org. 3 | # However, this gem sits underneath all my other gems, and also "depends on" many of them. 4 | # So instead of depending on them directly it injects them into the other gem's gemspec on install. 5 | # This gem, and its injected dev dependencies, will install on Ruby down to 2.3.x. 6 | # This gem does not inject runtime dependencies. 7 | # Thus, dev dependencies injected into gemspecs must have 8 | # 9 | # required_ruby_version ">= 2.3" (or lower) 10 | # 11 | # Development dependencies that require strictly newer Ruby versions should be in a "gemfile", 12 | # and preferably a modular one (see gemfiles/modular/*.gemfile). 13 | 14 | # Security 15 | gem "bundler-audit", "~> 0.9.2" # ruby >= 2.0.0 16 | 17 | # Tasks 18 | gem "rake", "~> 13.0" # ruby >= 2.2.0 19 | 20 | # Debugging 21 | gem "require_bench", "~> 1.0", ">= 1.0.4" # ruby >= 2.2.0 22 | 23 | # Testing 24 | gem "appraisal2", "~> 3.0" # ruby >= 1.8.7, for testing against multiple versions of dependencies 25 | gem "kettle-test", "~> 1.0" # ruby >= 2.3 26 | gem "rspec-pending_for" # ruby >= 2.3, used to skip specs on incompatible Rubies 27 | 28 | # Releasing 29 | gem "ruby-progressbar", "~> 1.13" # ruby >= 0 30 | gem "stone_checksums", "~> 1.0", ">= 1.0.2" # ruby >= 2.2.0 31 | 32 | # Git integration (optional) 33 | # The 'git' gem is optional; kettle-dev falls back to shelling out to `git` if it is not present. 34 | # The current release of the git gem depends on activesupport, which makes it too heavy to depend on directly 35 | # Compatibility with the git gem is tested via appraisals instead. 36 | # gem("git", ">= 1.19.1") # ruby >= 2.3 37 | 38 | # Development tasks 39 | gem "gitmoji-regex", "~> 1.0", ">= 1.0.3" # ruby >= 2.3.0 40 | 41 | # The cake is a lie. erb v2.2, the oldest release on RubyGems.org, was never compatible with Ruby 2.3. 42 | # This means we have no choice but to use the erb that shipped with Ruby 2.3 43 | # /opt/hostedtoolcache/Ruby/2.3.8/x64/lib/ruby/gems/2.3.0/gems/erb-2.2.2/lib/erb.rb:670:in `prepare_trim_mode': undefined method `match?' for "-":String (NoMethodError) 44 | # gem "erb", ">= 2.2" # ruby >= 2.3.0, not SemVer, old rubies get dropped in a patch. 45 | 46 | # HTTP recording for deterministic specs 47 | # It seems that somehow just having a newer version of appraisal installed breaks 48 | # Ruby 2.3 and 2.4 even if their bundle specifies an older version, 49 | # and as a result it can only be a dependency in the appraisals. 50 | # | An error occurred while loading spec_helper. 51 | # | Failure/Error: require "vcr" 52 | # | 53 | # | NoMethodError: 54 | # | undefined method `delete_prefix' for "CONTENT_LENGTH":String 55 | # | # ./spec/config/vcr.rb:3:in `require' 56 | # | # ./spec/config/vcr.rb:3:in `' 57 | # | # ./spec/spec_helper.rb:8:in `require_relative' 58 | # | # ./spec/spec_helper.rb:8:in `' 59 | # gem "vcr", ">= 4" # 6.0 claims to support ruby >= 2.3, but fails on ruby 2.4 60 | # gem "webmock", ">= 3" # Last version to support ruby >= 2.3 61 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($PROGRAM_NAME) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | 28 | bundler_version = nil 29 | update_index = nil 30 | ARGV.each_with_index do |a, i| 31 | bundler_version = a if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 32 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/o 33 | 34 | bundler_version = Regexp.last_match(1) 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../Gemfile", __dir__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | 59 | lockfile_contents = File.read(lockfile) 60 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/o 61 | 62 | Regexp.last_match(1) 63 | end 64 | 65 | def bundler_requirement 66 | @bundler_requirement ||= 67 | env_var_version || cli_arg_version || 68 | bundler_requirement_for(lockfile_version) 69 | end 70 | 71 | def bundler_requirement_for(version) 72 | return "#{Gem::Requirement.default}.a" unless version 73 | 74 | bundler_gem_version = Gem::Version.new(version) 75 | 76 | requirement = bundler_gem_version.approximate_recommendation 77 | 78 | return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0") 79 | 80 | requirement += ".a" if bundler_gem_version.prerelease? 81 | 82 | requirement 83 | end 84 | 85 | def load_bundler! 86 | ENV["BUNDLE_GEMFILE"] ||= gemfile 87 | 88 | activate_bundler 89 | end 90 | 91 | def activate_bundler 92 | gem_error = activation_error_handling do 93 | gem("bundler", bundler_requirement) 94 | end 95 | return if gem_error.nil? 96 | 97 | require_error = activation_error_handling do 98 | require "bundler/version" 99 | end 100 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 101 | 102 | warn("Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`") 103 | exit(42) 104 | end 105 | 106 | def activation_error_handling 107 | yield 108 | nil 109 | rescue StandardError, LoadError => e 110 | e 111 | end 112 | end 113 | 114 | m.load_bundler! 115 | 116 | load Gem.bin_path("bundler", "bundle") if m.invoked_as_script? 117 | -------------------------------------------------------------------------------- /RUBOCOP.md: -------------------------------------------------------------------------------- 1 | # RuboCop Usage Guide 2 | 3 | ## Overview 4 | 5 | A tale of two RuboCop plugin gems. 6 | 7 | ### RuboCop Gradual 8 | 9 | This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file. 10 | 11 | ### RuboCop LTS 12 | 13 | This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2. 14 | RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more. 15 | 16 | ## Checking RuboCop Violations 17 | 18 | To check for RuboCop violations in this project, always use: 19 | 20 | ```bash 21 | bundle exec rake rubocop_gradual:check 22 | ``` 23 | 24 | **Do not use** the standard RuboCop commands like: 25 | - `bundle exec rubocop` 26 | - `rubocop` 27 | 28 | ## Understanding the Lock File 29 | 30 | The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to: 31 | 32 | 1. Prevent new violations while gradually fixing existing ones 33 | 2. Track progress on code style improvements 34 | 3. Ensure CI builds don't fail due to pre-existing violations 35 | 36 | ## Common Commands 37 | 38 | - **Check violations** 39 | - `bundle exec rake rubocop_gradual` 40 | - `bundle exec rake rubocop_gradual:check` 41 | - **(Safe) Autocorrect violations, and update lockfile if no new violations** 42 | - `bundle exec rake rubocop_gradual:autocorrect` 43 | - **Force update the lock file (w/o autocorrect) to match violations present in code** 44 | - `bundle exec rake rubocop_gradual:force_update` 45 | 46 | ## Workflow 47 | 48 | 1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect` 49 | a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task. 50 | 2. If there are new violations, either: 51 | - Fix them in your code 52 | - Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately) 53 | 3. Commit the updated `.rubocop_gradual.lock` file along with your changes 54 | 55 | ## Never add inline RuboCop disables 56 | 57 | Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways: 58 | 59 | - Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide. 60 | - Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow: 61 | - `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced) 62 | - If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately) 63 | 64 | In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test. 65 | 66 | ## Benefits of rubocop_gradual 67 | 68 | - Allows incremental adoption of code style rules 69 | - Prevents CI failures due to pre-existing violations 70 | - Provides a clear record of code style debt 71 | - Enables focused efforts on improving code quality over time 72 | -------------------------------------------------------------------------------- /spec/oauth2/strategy/client_credentials_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe OAuth2::Strategy::ClientCredentials do 4 | subject { client.client_credentials } 5 | 6 | let(:kvform_token) { "expires_in=600&access_token=salmon&refresh_token=trout" } 7 | let(:json_token) { '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}' } 8 | 9 | let(:client) do 10 | OAuth2::Client.new("abc", "def", site: "http://api.example.com") do |builder| 11 | builder.adapter :test do |stub| 12 | stub.post("/oauth/token", "grant_type" => "client_credentials") do |env| 13 | client_id, client_secret = Base64.decode64(env[:request_headers]["Authorization"].split(" ", 2)[1]).split(":", 2) 14 | (client_id == "abc" && client_secret == "def") || raise(Faraday::Adapter::Test::Stubs::NotFound) 15 | @last_headers = env[:request_headers] 16 | case @mode 17 | when "formencoded" 18 | [200, {"Content-Type" => "application/x-www-form-urlencoded"}, kvform_token] 19 | when "json" 20 | [200, {"Content-Type" => "application/json"}, json_token] 21 | else raise ArgumentError, "Bad @mode: #{@mode}" 22 | end 23 | end 24 | stub.post("/oauth/token", "client_id" => "abc", "client_secret" => "def", "grant_type" => "client_credentials") do |_env| 25 | case @mode 26 | when "formencoded" 27 | [200, {"Content-Type" => "application/x-www-form-urlencoded"}, kvform_token] 28 | when "json" 29 | [200, {"Content-Type" => "application/json"}, json_token] 30 | else raise ArgumentError, "Bad @mode: #{@mode}" 31 | end 32 | end 33 | end 34 | end 35 | end 36 | 37 | describe "#authorize_url" do 38 | it "raises NotImplementedError" do 39 | expect { subject.authorize_url }.to raise_error(NotImplementedError) 40 | end 41 | end 42 | 43 | %w[json formencoded].each do |mode| 44 | %i[basic_auth request_body].each do |auth_scheme| 45 | describe "#get_token (#{mode}) (#{auth_scheme})" do 46 | before do 47 | @mode = mode 48 | client.options[:auth_scheme] = auth_scheme 49 | @access = subject.get_token 50 | end 51 | 52 | it "returns AccessToken with same Client" do 53 | expect(@access.client).to eq(client) 54 | end 55 | 56 | it "returns AccessToken with #token" do 57 | expect(@access.token).to eq("salmon") 58 | end 59 | 60 | it "returns AccessToken without #refresh_token" do 61 | expect(@access.refresh_token).to eq("trout") 62 | end 63 | 64 | it "returns AccessToken with #expires_in" do 65 | expect(@access.expires_in).to eq(600) 66 | end 67 | 68 | it "returns AccessToken with #expires_at" do 69 | expect(@access.expires_at).not_to be_nil 70 | end 71 | end 72 | end 73 | end 74 | 75 | describe "#get_token (with extra header parameters)" do 76 | before do 77 | @mode = "json" 78 | @access = subject.get_token(headers: {"X-Extra-Header" => "wow"}) 79 | end 80 | 81 | it "sends the header correctly." do 82 | expect(@last_headers["X-Extra-Header"]).to eq("wow") 83 | end 84 | end 85 | 86 | describe "#get_token (with option overriding response)" do 87 | before do 88 | @mode = "json" 89 | @access = subject.get_token({}, {"refresh_token" => "guppy"}) 90 | end 91 | 92 | it "override is applied" do 93 | expect(@access.token).to eq("salmon") 94 | expect(@access.refresh_token).to eq("guppy") 95 | end 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # kettle-dev Rakefile v1.1.51 - 2025-11-07 4 | # Ruby 2.3 (Safe Navigation) or higher required 5 | # 6 | # MIT License (see License.txt) 7 | # 8 | # Copyright (c) 2025 Peter H. Boling (galtzo.com) 9 | # 10 | # Expected to work in any project that uses Bundler. 11 | # 12 | # Sets up tasks for appraisal, floss_funding, rspec, minitest, rubocop, reek, yard, and stone_checksums. 13 | # 14 | # rake appraisal:update # Update Appraisal gemfiles and run RuboCop... 15 | # rake bench # Run all benchmarks (alias for bench:run) 16 | # rake bench:list # List available benchmark scripts 17 | # rake bench:run # Run all benchmark scripts (skips on CI) 18 | # rake build:generate_checksums # Generate both SHA256 & SHA512 checksums i... 19 | # rake bundle:audit:check # Checks the Gemfile.lock for insecure depe... 20 | # rake bundle:audit:update # Updates the bundler-audit vulnerability d... 21 | # rake ci:act[opt] # Run 'act' with a selected workflow 22 | # rake coverage # Run specs w/ coverage and open results in... 23 | # rake default # Default tasks aggregator 24 | # rake install # Build and install kettle-dev-1.0.0.gem in... 25 | # rake install:local # Build and install kettle-dev-1.0.0.gem in... 26 | # rake kettle:dev:install # Install kettle-dev GitHub automation and ... 27 | # rake kettle:dev:template # Template kettle-dev files into the curren... 28 | # rake reek # Check for code smells 29 | # rake reek:update # Run reek and store the output into the RE... 30 | # rake release[remote] # Create tag v1.0.0 and build and push kett... 31 | # rake rubocop_gradual # Run RuboCop Gradual 32 | # rake rubocop_gradual:autocorrect # Run RuboCop Gradual with autocorrect (onl... 33 | # rake rubocop_gradual:autocorrect_all # Run RuboCop Gradual with autocorrect (saf... 34 | # rake rubocop_gradual:check # Run RuboCop Gradual to check the lock file 35 | # rake rubocop_gradual:force_update # Run RuboCop Gradual to force update the l... 36 | # rake rubocop_gradual_debug # Run RuboCop Gradual 37 | # rake rubocop_gradual_debug:autocorrect # Run RuboCop Gradual with autocorrect (onl... 38 | # rake rubocop_gradual_debug:autocorrect_all # Run RuboCop Gradual with autocorrect (saf... 39 | # rake rubocop_gradual_debug:check # Run RuboCop Gradual to check the lock file 40 | # rake rubocop_gradual_debug:force_update # Run RuboCop Gradual to force update the l... 41 | # rake spec # Run RSpec code examples 42 | # rake test # Run tests 43 | # rake yard # Generate YARD Documentation 44 | # 45 | 46 | require "bundler/gem_tasks" if !Dir[File.join(__dir__, "*.gemspec")].empty? 47 | 48 | # Define a base default task early so other files can enhance it. 49 | desc "Default tasks aggregator" 50 | task :default do 51 | puts "Default task complete." 52 | end 53 | 54 | # External gems that define tasks - add here! 55 | require "kettle/dev" 56 | 57 | ### RELEASE TASKS 58 | # Setup stone_checksums 59 | begin 60 | require "stone_checksums" 61 | rescue LoadError 62 | desc("(stub) build:generate_checksums is unavailable") 63 | task("build:generate_checksums") do 64 | warn("NOTE: stone_checksums isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") 65 | end 66 | end 67 | --------------------------------------------------------------------------------