diff --git a/.rubocop.yml b/.rubocop.yml index e0d96c7..32e06fe 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,27 +1,27 @@ +Layout/AccessModifierIndentation: + EnforcedStyle: outdent + +Layout/SpaceInsideHashLiteralBraces: + EnforcedStyle: no_space + Metrics/BlockNesting: Max: 2 -Metrics/ClassLength: - CountComments: false - Max: 120 - -Metrics/PerceivedComplexity: - Max: 8 +Metrics/LineLength: + AllowURI: true + Enabled: false -Metrics/ModuleLength: +Metrics/MethodLength: CountComments: false - Max: 120 + Max: 10 Metrics/ParameterLists: - Max: 3 + Max: 4 CountKeywordArgs: true -Metrics/AbcSize: - Enabled: false - Style/CollectionMethods: PreferredMethods: - collect: 'map' + map: 'collect' reduce: 'inject' find: 'detect' find_all: 'select' @@ -29,41 +29,27 @@ Style/CollectionMethods: Style/Documentation: Enabled: false -Style/DotPosition: - EnforcedStyle: trailing - Style/DoubleNegation: Enabled: false -Style/EachWithObject: - Enabled: false - -Style/Encoding: +Style/ExpandPathArguments: Enabled: false Style/HashSyntax: EnforcedStyle: hash_rockets -Style/Lambda: - Enabled: false - -Style/SingleSpaceBeforeFirstArg: +Style/StderrPuts: Enabled: false -Style/SpaceAroundOperators: - MultiSpaceAllowedForOperators: - - "=" - - "=>" - - "||" - - "||=" - - "&&" - - "&&=" +Style/StringLiterals: + EnforcedStyle: single_quotes -Style/SpaceInsideHashLiteralBraces: - EnforcedStyle: no_space +Style/TrailingCommaInArguments: + EnforcedStyleForMultiline: comma -Style/StringLiterals: - EnforcedStyle: double_quotes +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: comma -Style/TrivialAccessors: - Enabled: false +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: comma + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..cdc5e9c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,22 @@ +bundler_args: --without development +before_install: + - gem update --system + - gem update bundler +cache: bundler +env: + global: + - JRUBY_OPTS="$JRUBY_OPTS --debug" +language: ruby +rvm: + - jruby-9000 + - 2.3.5 + - 2.4.4 + - 2.5.3 + - jruby-head + - ruby-head +matrix: + allow_failures: + - rvm: jruby-head + - rvm: ruby-head + fast_finish: true +sudo: false diff --git a/Gemfile b/Gemfile index bee8b9d..4fefd93 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,13 @@ -source "https://rubygems.org" +# frozen_string_literal: true -# Specify your gem's dependencies in omniauth-rails.gemspec -gemspec +source 'https://rubygems.org' + +gem 'rake' -gem "rake" -gem "rubocop" +group :test do + gem 'coveralls', :require => false + gem 'rspec', '~> 3.5.0' + gem 'rubocop' +end + +gemspec diff --git a/Rakefile b/Rakefile index 4cb030a..5a62f05 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ -require "bundler/gem_tasks" -require "rubocop/rake_task" +# frozen_string_literal: true +require 'bundler/gem_tasks' +require 'rspec/core/rake_task' -RuboCop::RakeTask.new - -task :default => :rubocop +RSpec::Core::RakeTask.new(:spec) +task :default => :spec diff --git a/lib/omiauth-rails.rb b/lib/omiauth-rails.rb new file mode 100644 index 0000000..02b82ca --- /dev/null +++ b/lib/omiauth-rails.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +require 'omniauth-rails/version' +require 'omniauth-rails/railtie' diff --git a/lib/omniauth-rails/railtie.rb b/lib/omniauth-rails/railtie.rb new file mode 100644 index 0000000..305786a --- /dev/null +++ b/lib/omniauth-rails/railtie.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true +require 'rails' + +module OmniAuth + module Rails + class Railtie < ::Rails::Railtie + initializer 'OmniAuth request_forgery_protection' do + OmniAuth.config.allowed_request_methods = [:post] + OmniAuth.config.before_request_phase do |env| + OmniAuth::Rails::RequestForgeryProtection.call(env) + end + end + end + end +end diff --git a/lib/omniauth-rails/request_forgery_protection.rb b/lib/omniauth-rails/request_forgery_protection.rb new file mode 100644 index 0000000..fcbd747 --- /dev/null +++ b/lib/omniauth-rails/request_forgery_protection.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true +require 'action_controller' + +module OmniAuth + module Rails + module RequestForgeryProtection + class Controller < ActionController::Base + protect_from_forgery :with => :exception, :prepend => true + + rescue_from ActionController::InvalidAuthenticityToken do |e| + # Log warning + raise e + end + + def index + head :ok + end + end + + def self.app + @app ||= Controller.action(:index) + end + + def self.call(env) + app.call(env) + end + + def self.verified?(env) + call(env) + + true + rescue ActionController::InvalidAuthenticityToken + false + end + end + end +end diff --git a/lib/omniauth-rails/version.rb b/lib/omniauth-rails/version.rb index d29f060..ceb8711 100644 --- a/lib/omniauth-rails/version.rb +++ b/lib/omniauth-rails/version.rb @@ -1,3 +1,7 @@ -module OmniAuthRails - VERSION = "1.0.0" +# frozen_string_literal: true + +module OmniAuth + module Rails + VERSION = '1.0.0' + end end diff --git a/omniauth-rails.gemspec b/omniauth-rails.gemspec index eb43f80..a264dd8 100644 --- a/omniauth-rails.gemspec +++ b/omniauth-rails.gemspec @@ -1,23 +1,27 @@ -# coding: utf-8 -lib = File.expand_path("../lib", __FILE__) +# frozen_string_literal: true +lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "omniauth-rails/version" -Gem::Specification.new do |spec| - spec.name = "omniauth-rails" - spec.version = OmniAuthRails::VERSION - spec.authors = ["Erik Michaels-Ober", "Douwe Maan"] - spec.email = ["sferik@gmail.com", "douwe@gitlab.com"] +require 'omniauth-rails/version' - spec.description = "Ruby on Rails extensions to OmniAuth" - spec.summary = spec.description - spec.homepage = "https://github.com/intridea/omniauth-rails" - spec.license = "MIT" +Gem::Specification.new do |gem| + gem.authors = ['Tom Milewski'] + gem.email = ['tmilewski@gmail.com'] + gem.description = 'Official Rails OmniAuth gem.' + gem.summary = gem.description + gem.homepage = 'https://github.com/omniauth/omniauth-rails' + gem.license = 'MIT' - spec.files = `git ls-files -z`.split("\x0") - spec.require_paths = ["lib"] + gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } + gem.files = `git ls-files`.split("\n") + gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + gem.name = 'omniauth-rails' + gem.require_paths = %w[lib] + gem.version = OmniAuth::Rails::VERSION - spec.add_dependency "omniauth" - spec.add_dependency "rails" - spec.add_development_dependency "bundler", "~> 1.9" + gem.add_dependency 'omniauth', '~> 1.0' + gem.add_dependency 'rails' + gem.add_development_dependency 'rack-test' + gem.add_development_dependency 'rspec', '~> 3.5' + gem.add_development_dependency 'simplecov' end diff --git a/spec/omniauth-rails/railtie_spec.rb b/spec/omniauth-rails/railtie_spec.rb new file mode 100644 index 0000000..7043c3b --- /dev/null +++ b/spec/omniauth-rails/railtie_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe OmniAuth::Rails::Railtie do + before do + OmniAuth::Rails::Railtie.initializers.each(&:run) + end + + it 'should only allow POST requests' do + expect(OmniAuth.config.allowed_request_methods).to eq([:post]) + end + + it 'should only allow POST requests' do + env = {} + expect(OmniAuth::Rails::RequestForgeryProtection).to receive(:call).with(env) + OmniAuth.config.before_request_phase.call(env) + end +end diff --git a/spec/omniauth-rails/request_forgery_protection_spec.rb b/spec/omniauth-rails/request_forgery_protection_spec.rb new file mode 100644 index 0000000..fc31082 --- /dev/null +++ b/spec/omniauth-rails/request_forgery_protection_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe OmniAuth::Rails::RequestForgeryProtection do + let(:csrf_token) { SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH) } + let(:env) do + { + 'rack.input' => '', + 'rack.session' => { + :_csrf_token => csrf_token, + }, + } + end + + describe '.call' do + context 'when the request method is GET' do + before do + env['REQUEST_METHOD'] = 'GET' + end + + it 'does not raise an exception' do + expect { described_class.call(env) }.not_to raise_exception + end + end + + context 'when the request method is POST' do + before do + env['REQUEST_METHOD'] = 'POST' + end + + context 'when the CSRF token is valid' do + before do + env['HTTP_X_CSRF_TOKEN'] = csrf_token + end + + it 'does not raise an exception' do + expect { described_class.call(env) }.not_to raise_exception + end + end + + context 'when the CSRF token is invalid' do + before do + env['HTTP_X_CSRF_TOKEN'] = 'foo' + end + + it 'raises an ActionController::InvalidAuthenticityToken exception' do + expect { described_class.call(env) }.to raise_exception(ActionController::InvalidAuthenticityToken) + end + end + end + end + + describe '.verified?' do + context 'when the request method is GET' do + before do + env['REQUEST_METHOD'] = 'GET' + end + + it 'returns true' do + expect(described_class.verified?(env)).to be_truthy + end + end + + context 'when the request method is POST' do + before do + env['REQUEST_METHOD'] = 'POST' + end + + context 'when the CSRF token is valid' do + before do + env['HTTP_X_CSRF_TOKEN'] = csrf_token + end + + it 'returns true' do + expect(described_class.verified?(env)).to be_truthy + end + end + + context 'when the CSRF token is invalid' do + before do + env['HTTP_X_CSRF_TOKEN'] = 'foo' + end + + it 'returns false' do + expect(described_class.verified?(env)).to be_falsey + end + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..c13d213 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +$:.unshift File.expand_path('..', __FILE__) +$:.unshift File.expand_path('../../lib', __FILE__) + +require 'simplecov' +SimpleCov.start + +require 'rspec' +require 'rack/test' +require 'omniauth' + +require 'omniauth-rails/railtie' +require 'omniauth-rails/request_forgery_protection'