omniauth-rails-csrf-protection-1.0.1/0000755000175000000330000000000014325767304016633 5ustar avronrsudoomniauth-rails-csrf-protection-1.0.1/LICENSE.txt0000644000175000000330000000206714325767304020463 0ustar avronrsudoThe MIT License (MIT) Copyright (c) 2019 Cookpad Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. omniauth-rails-csrf-protection-1.0.1/omniauth-rails_csrf_protection.gemspec0000644000175000000330000000252314325767304026421 0ustar avronrsudolib = File.expand_path("lib", __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "omniauth/rails_csrf_protection/version" Gem::Specification.new do |spec| spec.name = "omniauth-rails_csrf_protection" spec.version = OmniAuth::RailsCsrfProtection::VERSION spec.authors = ["Cookpad Inc."] spec.email = ["kaihatsu@cookpad.com"] spec.summary = <<~SUMMARY Provides CSRF protection on OmniAuth request endpoint on Rails application. SUMMARY spec.description = <<~DESCRIPTION This gem provides a mitigation against CVE-2015-9284 (Cross-Site Request Forgery on the request phrase when using OmniAuth gem with a Ruby on Rails application) by implementing a CSRF token verifier that directly utilize `ActionController::RequestForgeryProtection` code from Rails. DESCRIPTION spec.homepage = "https://github.com/cookpad/omniauth-rails_csrf_protection" spec.license = "MIT" spec.files = `git ls-files`.split("\n") spec.test_files = `git ls-files -- test/*`.split("\n") spec.require_paths = ["lib"] spec.add_dependency "actionpack", ">= 4.2" spec.add_dependency "omniauth", "~> 2.0" spec.add_development_dependency "bundler" spec.add_development_dependency "minitest" spec.add_development_dependency "rails" spec.add_development_dependency "rake" end omniauth-rails-csrf-protection-1.0.1/Gemfile0000644000175000000330000000044714325767304020133 0ustar avronrsudosource "https://rubygems.org" # rubocop:disable Bundler/DuplicatedGem if ENV["RAILS_VERSION"] gem "rails", ENV["RAILS_VERSION"] elsif ENV["RAILS_BRANCH"] gem "rails", git: "https://github.com/rails/rails.git", branch: ENV["RAILS_BRANCH"] end # rubocop:enable Bundler/DuplicatedGem gemspec omniauth-rails-csrf-protection-1.0.1/.rubocop.yml0000644000175000000330000000035314325767304021106 0ustar avronrsudoinherit_from: - https://raw.githubusercontent.com/cookpad/global-style-guides/master/.rubocop.yml AllCops: TargetRubyVersion: 2.5 # Disable this as this does not apply to rack-test Rails/HttpPositionalArguments: Enabled: false omniauth-rails-csrf-protection-1.0.1/CODE_OF_CONDUCT.md0000644000175000000330000000623614325767304021441 0ustar avronrsudo# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kaihatsu@cookpad.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ omniauth-rails-csrf-protection-1.0.1/lib/0000755000175000000330000000000014325767304017401 5ustar avronrsudoomniauth-rails-csrf-protection-1.0.1/lib/omniauth/0000755000175000000330000000000014325767304021225 5ustar avronrsudoomniauth-rails-csrf-protection-1.0.1/lib/omniauth/rails_csrf_protection/0000755000175000000330000000000014325767304025622 5ustar avronrsudoomniauth-rails-csrf-protection-1.0.1/lib/omniauth/rails_csrf_protection/version.rb0000644000175000000330000000012414325767304027631 0ustar avronrsudomodule OmniAuth module RailsCsrfProtection VERSION = "1.0.1".freeze end end omniauth-rails-csrf-protection-1.0.1/lib/omniauth/rails_csrf_protection/railtie.rb0000644000175000000330000000047614325767304027607 0ustar avronrsudorequire "omniauth" require "omniauth/rails_csrf_protection/token_verifier" module OmniAuth module RailsCsrfProtection class Railtie < Rails::Railtie initializer "omniauth-rails_csrf_protection.initialize" do OmniAuth.config.request_validation_phase = TokenVerifier.new end end end end omniauth-rails-csrf-protection-1.0.1/lib/omniauth/rails_csrf_protection/token_verifier.rb0000644000175000000330000000312614325767304031164 0ustar avronrsudorequire "active_support/configurable" require "action_controller" module OmniAuth module RailsCsrfProtection # Provides a callable method that verifies Cross-Site Request Forgery # protection token. This class includes # `ActionController::RequestForgeryProtection` directly and utilizes # `verified_request?` method to match the way Rails performs token # verification in Rails controllers. # # If you like to learn more about how Rails generate and verify # authenticity token, you can find the source code at # https://github.com/rails/rails/blob/v5.2.2/actionpack/lib/action_controller/metal/request_forgery_protection.rb#L217-L240. class TokenVerifier include ActiveSupport::Configurable include ActionController::RequestForgeryProtection # `ActionController::RequestForgeryProtection` contains a few # configurable options. As we want to make sure that our configuration is # the same as what being set in `ActionController::Base`, we should make # all out configuration methods to delegate to `ActionController::Base`. config.each_key do |configuration_name| undef_method configuration_name define_method configuration_name do ActionController::Base.config[configuration_name] end end def call(env) @request = ActionDispatch::Request.new(env.dup) unless verified_request? raise ActionController::InvalidAuthenticityToken end end private attr_reader :request delegate :params, :session, to: :request end end end omniauth-rails-csrf-protection-1.0.1/lib/omniauth/rails_csrf_protection.rb0000644000175000000330000000014214325767304026144 0ustar avronrsudorequire "omniauth/rails_csrf_protection/version" require "omniauth/rails_csrf_protection/railtie" omniauth-rails-csrf-protection-1.0.1/.gitignore0000644000175000000330000000014314325767304020621 0ustar avronrsudo/.bundle/ /.rubocop-* /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ omniauth-rails-csrf-protection-1.0.1/README.md0000644000175000000330000000361414325767304020116 0ustar avronrsudo# OmniAuth - Rails CSRF Protection This gem provides a mitigation against [CVE-2015-9284] (Cross-Site Request Forgery on the request phase when using OmniAuth gem with a Ruby on Rails application) by implementing a CSRF token verifier that directly uses `ActionController::RequestForgeryProtection` code from Rails. [![CircleCI](https://circleci.com/gh/cookpad/omniauth-rails_csrf_protection/tree/main.svg?style=svg)](https://circleci.com/gh/cookpad/omniauth-rails_csrf_protection/tree/main) [CVE-2015-9284]: https://nvd.nist.gov/vuln/detail/CVE-2015-9284 ## Usage Add this line to your application's Gemfile: ```ruby gem "omniauth-rails_csrf_protection" ``` Then run `bundle install` to install this gem. You will then need to verify that all links in your application that would initiate OAuth request phase are being converted to a HTTP POST form that contains `authenticity_token` value. This might simply be done by changing all `link_to` to `button_to`, or use `link_to ..., method: :post`. ## Under the Hood This gem does a few things to your application: * Disable access to the OAuth request phase using HTTP GET method. * Insert a Rails CSRF token verifier at the before request phase. These actions mitigate you from the attack vector described in [CVE-2015-9284]. ## Contributing Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). ## Code of Conduct Everyone interacting in the this project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/cookpad/omniauth-rails_csrf_protection/blob/main/CODE_OF_CONDUCT.md). omniauth-rails-csrf-protection-1.0.1/Rakefile0000644000175000000330000000030314325767304020274 0ustar avronrsudorequire "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" t.libs << "lib" t.test_files = FileList["test/**/*_test.rb"] end task default: :test omniauth-rails-csrf-protection-1.0.1/.circleci/0000755000175000000330000000000014325767304020466 5ustar avronrsudoomniauth-rails-csrf-protection-1.0.1/.circleci/config.yml0000644000175000000330000001112214325767304022453 0ustar avronrsudoversion: 2.1 build_steps: &build_steps steps: - checkout - run: name: Install dependencies command: bundle update - run: command: |- echo "Ruby version:" $(ruby -v) echo "Rails version: " $(rails -v) name: Show build information - run: name: Run tests command: rake ruby-2-4: &ruby-2-4 docker: - image: circleci/ruby:2.4 ruby-2-5: &ruby-2-5 docker: - image: cimg/ruby:2.5 ruby-2-6: &ruby-2-6 docker: - image: cimg/ruby:2.6 ruby-2-7: &ruby-2-7 docker: - image: cimg/ruby:2.7 ruby-3-0: &ruby-3-0 docker: - image: cimg/ruby:3.0 ruby-3-1: &ruby-3-1 docker: - image: cimg/ruby:3.1 rails-4-2: &rails-4-2 environment: RAILS_VERSION: "~> 4.2.0" rails-5-0: &rails-5-0 environment: RAILS_VERSION: "~> 5.0.0" rails-5-1: &rails-5-1 environment: RAILS_VERSION: "~> 5.1.0" rails-5-2: &rails-5-2 environment: RAILS_VERSION: "~> 5.2.0" rails-6-0: &rails-6-0 environment: RAILS_VERSION: "~> 6.0.0" rails-6-1: &rails-6-1 environment: RAILS_VERSION: "~> 6.1.0" rails-7-0: &rails-7-0 environment: RAILS_VERSION: "~> 7.0.0" rails-edge: &rails-edge environment: RAILS_BRANCH: "main" jobs: "ruby-2-4-rails-4-2": <<: *ruby-2-4 <<: *rails-4-2 <<: *build_steps "ruby-2-4-rails-5-0": <<: *ruby-2-4 <<: *rails-5-0 <<: *build_steps "ruby-2-4-rails-5-1": <<: *ruby-2-4 <<: *rails-5-1 <<: *build_steps "ruby-2-4-rails-5-2": <<: *ruby-2-4 <<: *rails-5-2 <<: *build_steps "ruby-2-5-rails-5-0": <<: *ruby-2-5 <<: *rails-5-0 <<: *build_steps "ruby-2-5-rails-5-1": <<: *ruby-2-5 <<: *rails-5-1 <<: *build_steps "ruby-2-5-rails-5-2": <<: *ruby-2-5 <<: *rails-5-2 <<: *build_steps "ruby-2-5-rails-6-0": <<: *ruby-2-5 <<: *rails-6-0 <<: *build_steps "ruby-2-5-rails-6-1": <<: *ruby-2-5 <<: *rails-6-1 <<: *build_steps "ruby-2-5-rails-edge": <<: *ruby-2-5 <<: *rails-edge <<: *build_steps "ruby-2-6-rails-5-0": <<: *ruby-2-6 <<: *rails-5-0 <<: *build_steps "ruby-2-6-rails-5-1": <<: *ruby-2-6 <<: *rails-5-1 <<: *build_steps "ruby-2-6-rails-5-2": <<: *ruby-2-6 <<: *rails-5-2 <<: *build_steps "ruby-2-6-rails-6-0": <<: *ruby-2-6 <<: *rails-6-0 <<: *build_steps "ruby-2-6-rails-6-1": <<: *ruby-2-6 <<: *rails-6-1 <<: *build_steps "ruby-2-6-rails-edge": <<: *ruby-2-6 <<: *rails-edge <<: *build_steps "ruby-2-7-rails-5-0": <<: *ruby-2-7 <<: *rails-5-0 <<: *build_steps "ruby-2-7-rails-5-1": <<: *ruby-2-7 <<: *rails-5-1 <<: *build_steps "ruby-2-7-rails-5-2": <<: *ruby-2-7 <<: *rails-5-2 <<: *build_steps "ruby-2-7-rails-6-0": <<: *ruby-2-7 <<: *rails-6-0 <<: *build_steps "ruby-2-7-rails-6-1": <<: *ruby-2-7 <<: *rails-6-1 <<: *build_steps "ruby-2-7-rails-7-0": <<: *ruby-2-7 <<: *rails-7-0 <<: *build_steps "ruby-2-7-rails-edge": <<: *ruby-2-7 <<: *rails-edge <<: *build_steps "ruby-3-0-rails-6-0": <<: *ruby-3-0 <<: *rails-6-0 <<: *build_steps "ruby-3-0-rails-6-1": <<: *ruby-3-0 <<: *rails-6-1 <<: *build_steps "ruby-3-0-rails-7-0": <<: *ruby-3-0 <<: *rails-7-0 <<: *build_steps "ruby-3-0-rails-edge": <<: *ruby-3-0 <<: *rails-edge <<: *build_steps "ruby-3-1-rails-6-0": <<: *ruby-3-1 <<: *rails-6-0 <<: *build_steps "ruby-3-1-rails-6-1": <<: *ruby-3-1 <<: *rails-6-1 <<: *build_steps "ruby-3-1-rails-7-0": <<: *ruby-3-1 <<: *rails-7-0 <<: *build_steps "ruby-3-1-rails-edge": <<: *ruby-3-1 <<: *rails-edge <<: *build_steps workflows: version: 2 build: jobs: - "ruby-2-4-rails-4-2" - "ruby-2-4-rails-5-1" - "ruby-2-4-rails-5-2" - "ruby-2-5-rails-5-0" - "ruby-2-5-rails-5-1" - "ruby-2-5-rails-5-2" - "ruby-2-5-rails-6-0" - "ruby-2-5-rails-6-1" - "ruby-2-6-rails-5-0" - "ruby-2-6-rails-5-1" - "ruby-2-6-rails-5-2" - "ruby-2-6-rails-6-0" - "ruby-2-6-rails-6-1" - "ruby-2-7-rails-5-0" - "ruby-2-7-rails-5-1" - "ruby-2-7-rails-5-2" - "ruby-2-7-rails-6-0" - "ruby-2-7-rails-6-1" - "ruby-2-7-rails-7-0" - "ruby-2-7-rails-edge" - "ruby-3-0-rails-6-0" - "ruby-3-0-rails-6-1" - "ruby-3-0-rails-7-0" - "ruby-3-0-rails-edge" - "ruby-3-1-rails-6-0" - "ruby-3-1-rails-6-1" - "ruby-3-1-rails-7-0" - "ruby-3-1-rails-edge" omniauth-rails-csrf-protection-1.0.1/test/0000755000175000000330000000000014325767304017612 5ustar avronrsudoomniauth-rails-csrf-protection-1.0.1/test/application_test.rb0000644000175000000330000000147114325767304023504 0ustar avronrsudorequire "test_helper" class ApplicationTest < Minitest::Test include Rack::Test::Methods def test_request_phrase_not_accessible_via_get get "/auth/developer" assert last_response.not_found? end def test_request_phrase_without_token_via_post post "/auth/developer" follow_redirect! assert last_response.not_found? end def test_request_phrase_with_bad_token_via_post post "/auth/developer", authenticity_token: "BAD_TOKEN" follow_redirect! assert last_response.not_found? end def test_request_phrase_with_correct_token_via_post post "/auth/developer", authenticity_token: authenticity_token assert last_response.ok? end private def app Rails.application end def authenticity_token get "/token" last_response.body end end omniauth-rails-csrf-protection-1.0.1/test/test_helper.rb0000644000175000000330000000357514325767304022467 0ustar avronrsudo$LOAD_PATH.unshift File.expand_path("../lib", __dir__) # Simple Rails application template, based on Rails issue template # https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_gem.rb # Helper method to silence warnings from bundler/inline def silence_warnings old_verbose, $VERBOSE = $VERBOSE, nil yield ensure $VERBOSE = old_verbose end silence_warnings do require "bundler/inline" # Define dependencies required by this test app gemfile do source "https://rubygems.org" gem "rails" gem "omniauth" gem "omniauth-rails_csrf_protection", path: File.expand_path("..", __dir__) end end puts "Running test against Rails #{Rails.version}" require "rack/test" require "action_controller/railtie" require "minitest/autorun" # Build a test application which uses OmniAuth class TestApp < Rails::Application config.root = __dir__ config.session_store :cookie_store, key: "cookie_store_key" secrets.secret_key_base = "secret_key_base" config.eager_load = false config.hosts = [] # This allow us to send all logs to STDOUT if we run test wth `VERBOSE=1` config.logger = if ENV["VERBOSE"] Logger.new($stdout) else Logger.new("/dev/null") end Rails.logger = config.logger OmniAuth.config.logger = Rails.logger # Setup a simple OmniAuth configuration with only developer provider config.middleware.use OmniAuth::Builder do provider :developer end # We need to call initialize! to run all railties initialize! # Define our custom routes. This needs to be called after initialize! routes.draw do get "token" => "application#token" end end # A small test controller which we use to retrive the valid authenticity token class ApplicationController < ActionController::Base def token render plain: form_authenticity_token end end