csrf protection (liquid tags + specs)
did
committed Feb 02, 2015
commit c6375256cd758c820e185eba553a5dc60bdbd54c
Showing 9
changed files with
104 additions
and 22 deletions
Gemfile.lock
+3
-0
| @@ | @@ -17,6 +17,7 @@ PATH |
| moneta (~> 0.8.0) | |
| morphine (~> 0.1.1) | |
| rack-cache (~> 1.2) | |
| + | rack_csrf (~> 2.5.0) |
| sprockets (~> 2.12.3) | |
| sprockets-sass (~> 1.3.1) | |
| @@ | @@ -128,6 +129,8 @@ GEM |
| rack (>= 0.4) | |
| rack-test (0.6.3) | |
| rack (>= 1.0) | |
| + | rack_csrf (2.5.0) |
| + | rack (>= 1.1.0) |
| rails-deprecated_sanitizer (1.0.3) | |
| activesupport (>= 4.2.0.alpha) | |
| rails-dom-testing (1.0.5) | |
locomotive/steam.rb b/lib/locomotive/steam.rb
+1
-0
| @@ | @@ -18,6 +18,7 @@ require 'haml' |
| require 'compass' | |
| require 'mimetype_fu' | |
| require 'mime-types' | |
| + | require 'rack/csrf' |
| require 'active_support' | |
| require 'active_support/concern' | |
locomotive/steam/configuration.rb b/lib/locomotive/steam/configuration.rb
+4
-0
| @@ | @@ -10,11 +10,15 @@ module Locomotive |
| attr_accessor :assets_path | |
| attr_accessor :image_resizer_secret | |
| + | attr_accessor :csrf_protection |
| + | |
| def initialize | |
| self.mode = :production | |
| self.theme_assets_checksum = false | |
| self.image_resizer_secret = 'please change it' | |
| + | |
| + | self.csrf_protection = true |
| end | |
| end | |
locomotive/steam/liquid/tags/csrf.rb b/lib/locomotive/steam/liquid/tags/csrf.rb
+16
-12
| @@ | @@ -7,11 +7,13 @@ module Locomotive |
| class Param < ::Liquid::Tag | |
| def render(context) | |
| - | controller = context.registers[:controller] |
| - | name = controller.send(:request_forgery_protection_token).to_s |
| - | value = controller.send(:form_authenticity_token) |
| + | service = context.registers[:services].csrf_protection |
| - | %(<input type="hidden" name="#{name}" value="#{value}">) |
| + | if service.enabled? |
| + | %(<input type="hidden" name="#{service.field}" value="#{service.token}" />) |
| + | else |
| + | '' |
| + | end |
| end | |
| end | |
| @@ | @@ -19,14 +21,16 @@ module Locomotive |
| class Meta < ::Liquid::Tag | |
| def render(context) | |
| - | controller = context.registers[:controller] |
| - | name = controller.send(:request_forgery_protection_token).to_s |
| - | value = controller.send(:form_authenticity_token) |
| - | |
| - | %{ |
| - | <meta name="csrf-param" content="#{name}"> |
| - | <meta name="csrf-token" content="#{value}"> |
| - | } |
| + | service = context.registers[:services].csrf_protection |
| + | |
| + | if service.enabled? |
| + | %{ |
| + | <meta name="csrf-param" content="#{service.field}" /> |
| + | <meta name="csrf-token" content="#{service.token}" /> |
| + | } |
| + | else |
| + | '' |
| + | end |
| end | |
| end | |
locomotive/steam/middlewares/stack.rb b/lib/locomotive/steam/middlewares/stack.rb
+6
-1
| @@ | @@ -25,10 +25,15 @@ module Locomotive |
| use Middlewares::StaticAssets, { | |
| urls: ['/images', '/fonts', '/samples', '/media'] | |
| } | |
| - | |
| use Middlewares::DynamicAssets | |
| end | |
| + | use Rack::Csrf, |
| + | field: 'authenticity_token', |
| + | skip_if: -> (request) { |
| + | !(request.post? && request.params[:content_type_slug].present?) |
| + | } |
| + | |
| use ::Dragonfly::Middleware, :steam | |
| use Rack::Session::Moneta, options[:moneta] | |
locomotive/steam/services.rb b/lib/locomotive/steam/services.rb
+4
-0
| @@ | @@ -42,6 +42,10 @@ module Locomotive |
| Services::ExternalAPI.new | |
| end | |
| + | register :csrf_protection do |
| + | Services::CsrfProtection.new(configuration.csrf_protection, Rack::Csrf.field, Rack::Csrf.token(request.env)) |
| + | end |
| + | |
| register :cache do | |
| Services::NoCache.new | |
| end | |
locomotive/steam/services/csrf_protection.rb b/lib/locomotive/steam/services/csrf_protection.rb
+15
-0
| @@ | @@ -0,0 +1,15 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Services |
| + | |
| + | class CsrfProtection < Struct.new(:enabled, :field, :token) |
| + | |
| + | def enabled? |
| + | !!enabled |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
locomotivecms_steam.gemspec
+9
-9
| @@ | @@ -18,31 +18,31 @@ Gem::Specification.new do |spec| |
| spec.add_development_dependency 'bundler', '~> 1.7' | |
| spec.add_development_dependency 'rake', '~> 10.4.2' | |
| - | # spec.add_development_dependency 'rspec', '~> 3.1.0' |
| - | # spec.add_development_dependency 'vcr', '~> 2.9.3' |
| - | # spec.add_development_dependency 'webmock', '~> 1.20.4' |
| - | # spec.add_development_dependency 'mocha', '~> 1.20.4' |
| - | # spec.add_development_dependency 'rack-test', '~> 0.6.3' |
| - | # spec.add_development_dependency 'i18n-spec', '~> 0.6.0' |
| spec.add_dependency 'activesupport', '~> 4.2.0' | |
| spec.add_dependency 'morphine', '~> 0.1.1' | |
| spec.add_dependency 'httparty', '~> 0.13.3' | |
| + | |
| # spec.add_dependency 'httmultiparty', '~> 0.3.10' | |
| spec.add_dependency 'rack-cache', '~> 1.2' | |
| + | spec.add_dependency 'dragonfly', '~> 1.0.7' |
| spec.add_dependency 'moneta', '~> 0.8.0' | |
| + | spec.add_dependency 'rack_csrf', '~> 2.5.0' |
| + | |
| spec.add_dependency 'sprockets', '~> 2.12.3' | |
| spec.add_dependency 'sprockets-sass', '~> 1.3.1' | |
| - | spec.add_dependency 'dragonfly', '~> 1.0.7' |
| + | spec.add_dependency 'coffee-script', '~> 2.3.0' |
| + | spec.add_dependency 'compass', '~> 1.0.3' |
| + | |
| spec.add_dependency 'kaminari', '~> 0.16.2' | |
| spec.add_dependency 'kramdown', '~> 1.5.0' | |
| spec.add_dependency 'RedCloth', '~> 4.2.9' | |
| - | spec.add_dependency 'coffee-script', '~> 2.3.0' |
| spec.add_dependency 'haml', '~> 4.0.6' | |
| - | spec.add_dependency 'compass', '~> 1.0.3' |
| spec.add_dependency 'mimetype-fu', '~> 0.1.2' | |
| + | |
| + | |
| # spec.add_dependency 'locomotivecms_models', '~> 0.0.1.pre.alpha' | |
| spec.add_dependency 'locomotivecms-solid', '~> 4.0.0.alpha' | |
| spec.add_dependency 'locomotivecms_common', '~> 0.0.2' | |
spec/unit/liquid/tags/csrf_spec.rb
+46
-0
| @@ | @@ -0,0 +1,46 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Liquid::Tags::Csrf do |
| + | |
| + | before do |
| + | allow(Rack::Csrf).to receive(:field).and_return('token') |
| + | allow(Rack::Csrf).to receive(:token).and_return(42) |
| + | end |
| + | |
| + | let(:request) { instance_double('Request', env: {}) } |
| + | let(:services) { Locomotive::Steam::Services.build_instance(request) } |
| + | let(:context) { ::Liquid::Context.new({}, {}, { services: services }) } |
| + | |
| + | subject { render_template(template, context) } |
| + | |
| + | describe 'csrf_param' do |
| + | |
| + | let(:template) { '{% csrf_param %}' } |
| + | it { is_expected.to eq '<input type="hidden" name="token" value="42" />' } |
| + | |
| + | context 'protection not enabled' do |
| + | |
| + | before { allow(services.configuration).to receive(:csrf_protection).and_return(false) } |
| + | it { is_expected.to eq '' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe 'rendering the meta tag used by ajax requests' do |
| + | |
| + | let(:template) { '{% csrf_meta %}' } |
| + | |
| + | it { is_expected.to match '<meta name="csrf-param" content="token" />' } |
| + | it { is_expected.to match '<meta name="csrf-token" content="42" />' } |
| + | |
| + | context 'protection not enabled' do |
| + | |
| + | before { allow(services.configuration).to receive(:csrf_protection).and_return(false) } |
| + | it { is_expected.to eq '' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |