faraday_csrf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9e3c3f8f9e0e8bce5cf6e116ec115c2741ee1e44
4
+ data.tar.gz: fd5624762051970efca4212b3e6022b3332af389
5
+ SHA512:
6
+ metadata.gz: 9aa73632ba3154af1acb07d4788de366b69df48af51894d494ce9cf35015daaa84244b85833e740b8e1980c34e702ff4d52a5819c6958ecb14386829ebd1f681
7
+ data.tar.gz: 04ab1e08705cf52287375721f8a9207a27d05fcfc467f9f890f7dea5658822c8c4088668965eb748263fc769f0a10bea7e40643c8007c460f09dcddc9db50b31
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /vcr_cassettes
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --order rand
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ Style/MethodDefParentheses:
2
+ Enabled: false
3
+
4
+ Style/Documentation:
5
+ Enabled: false
6
+
7
+ Style/SignalException:
8
+ Enabled: false
9
+
10
+ Style/MultilineOperationIndentation:
11
+ Enabled: false
12
+
13
+ Style/RaiseArgs:
14
+ EnforcedStyle: compact
15
+
16
+ Style/IfUnlessModifier:
17
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.2.2
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in faraday_csrf.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ [![Build Status](https://travis-ci.org/unmanbearpig/faraday_csrf.svg?branch=master)](https://travis-ci.org/unmanbearpig/faraday_csrf)
2
+ [![Code Climate](https://codeclimate.com/github/unmanbearpig/faraday_csrf/badges/gpa.svg)](https://codeclimate.com/github/unmanbearpig/faraday_csrf)
3
+
4
+ # Faraday CSRF middleware
5
+
6
+ Transparently handles Rails (and maybe not only Rails) CSRF protection, in case you need to send requests to an app that doesn't provide an API.
7
+ It tries to extract a CSRF token from each request and later inserts it into (POST, PUT, DELETE, etc.) requests that probably require it.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'faraday_csrf'
15
+ ```
16
+ You need to add it to your stack, you would also need a cookie_jar
17
+ (gem 'faraday-cookie_jar').
18
+
19
+
20
+ ## Usage
21
+
22
+ Create a Faraday connection like this:
23
+
24
+ ```ruby
25
+ conn = Faraday.new url: 'https://a-rails-app.example.com/' do |conn|
26
+ conn.use :csrf
27
+ conn.request :url_encoded
28
+ conn.use :cookie_jar
29
+ conn.adapter Faraday.default_adapter
30
+ end
31
+ ```
32
+
33
+ When you would make a get request, the CSRF thingy would try to
34
+ parse the page and extract the token from it.
35
+ When you make a POST request after that, it would add the token to it.
36
+
37
+ You have to use faraday-cookie_jar gem for handling cookies, and use :url_encoded middleware or something of that nature to allow this middleware to insert tokens.
38
+
39
+ You can get the token it extracted by accessing response_env[:csrf_token].
40
+
41
+ ## Contributing
42
+
43
+ Bug reports and pull requests are welcome on GitHub at https://github.com/unmanbearpig/faraday_csrf.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+ rescue LoadError
9
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "faraday_csrf"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'faraday_csrf/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "faraday_csrf"
8
+ spec.version = FaradayCsrf::VERSION
9
+ spec.authors = ["unmanbearpig"]
10
+ spec.email = ["unmanbearpig@gmail.com"]
11
+
12
+ spec.summary = %q{Faraday middleware that automatically adds CSRF tokens to requests}
13
+ spec.homepage = 'https://github.com/unmanbearpig/faraday_csrf'
14
+
15
+ spec.description = "Transparently handles Rails (and maybe not only Rails) CSRF protection, in case you need to send requests to an app that doesn't provide an API"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+ spec.add_dependency "faraday"
22
+ spec.add_dependency "nokogiri"
23
+
24
+
25
+ spec.add_development_dependency "bundler", "> 1.9"
26
+ spec.add_development_dependency "rake", "~> 10.4.2"
27
+ spec.add_development_dependency "rspec", "~> 3.3"
28
+ spec.add_development_dependency "rspec-expectations", "~> 3.3"
29
+ spec.add_development_dependency "webmock", "~> 1.21"
30
+ spec.add_development_dependency "vcr", "~> 2.9"
31
+ spec.add_development_dependency "faraday-cookie_jar", "~> 0.0.6"
32
+ end
@@ -0,0 +1,46 @@
1
+ require 'faraday_csrf/token_handler'
2
+ require 'faraday_csrf/token_extractors/first_successful_extractor'
3
+ require 'faraday_csrf/token_extractors/meta_tag_regex_extractor'
4
+ require 'faraday_csrf/token_extractors/meta_tag_nokogiri_extractor'
5
+
6
+ module Faraday
7
+ class CSRF
8
+ class CreatesTokenHandler
9
+ def initialize(app:, fetch_token_from_url: nil)
10
+ @app = app
11
+ @fetch_token_from_url = fetch_token_from_url
12
+ end
13
+
14
+ def self.create *args
15
+ new(*args).token_handler
16
+ end
17
+
18
+ def token_handler
19
+ TokenHandler.new extractor: extractor,
20
+ injector: injector,
21
+ fetcher: fetcher
22
+ end
23
+
24
+ def extractors_to_try
25
+ [MetaTagRegexExtractor,
26
+ MetaTagNokogiriExtractor]
27
+ end
28
+
29
+ def extractor
30
+ FirstSuccessfulExtractor.new(extractors_to_try)
31
+ end
32
+
33
+ def injector
34
+ InjectsTokenIntoBody.new
35
+ end
36
+
37
+ def fetcher
38
+ if @fetch_token_from_url
39
+ TokenFetcher.new app: @app, url: @fetch_token_from_url
40
+ else
41
+ Proc.new {}
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ require 'faraday_csrf/token'
2
+
3
+ module Faraday
4
+ class CSRF
5
+ class InjectsTokenIntoBody
6
+ class MissingToken < Exception
7
+ end
8
+
9
+ DEFAULT_IGNORE_METHODS = [:get, :head]
10
+
11
+ attr_reader :ignore_methods
12
+
13
+ def initialize(ignore_methods: DEFAULT_IGNORE_METHODS)
14
+ @ignore_methods = ignore_methods
15
+ end
16
+
17
+ def inject(token, into:)
18
+ return unless should_inject?(into)
19
+
20
+ raise MissingToken unless token
21
+
22
+ inject!(token, env: into)
23
+ end
24
+
25
+ def inject!(token, env:)
26
+ env.body.merge! token.to_h
27
+ token.expire!
28
+ end
29
+
30
+ def should_inject? env
31
+ return false if ignore_methods.include?(env.method)
32
+ return false unless env.body.respond_to? :merge!
33
+ true
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,55 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class CSRF
5
+ class Token
6
+ class NotFound < RuntimeError; end
7
+
8
+ attr_reader :name, :value
9
+ protected :name, :value
10
+
11
+ def initialize(name: nil, value:)
12
+ unless value
13
+ raise ArgumentError.new 'Token must have a value'
14
+ end
15
+
16
+ @name = name || self.class.default_name
17
+ @value = value
18
+ @expired = false
19
+ end
20
+
21
+ def self.default_name
22
+ 'authenticity_token'
23
+ end
24
+
25
+ def expire!
26
+ @name = nil
27
+ @value = nil
28
+ @expired = true
29
+ self
30
+ end
31
+
32
+ def expired?
33
+ @expired
34
+ end
35
+
36
+ def ==(other)
37
+ name == other.name &&
38
+ value == other.value &&
39
+ expired? == other.expired?
40
+ end
41
+
42
+ alias_method :to_s, :value
43
+
44
+ def inspect
45
+ return "CSRF::Token(~expired~)" if expired?
46
+ "CSRF::Token('#{name}' => '#{value}')"
47
+ end
48
+
49
+ def to_h
50
+ return {} if expired?
51
+ { name => value }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,36 @@
1
+ require 'faraday_csrf/token'
2
+
3
+ module Faraday
4
+ class CSRF
5
+ class FirstSuccessfulExtractor
6
+ attr_reader :extractors
7
+
8
+ def initialize(extractors_to_try)
9
+ @extractors = extractors_to_try
10
+ unless extractors.any?
11
+ raise ArgumentError.new "Pass at least one extractor into FirstSuccessfulExtractor"
12
+ end
13
+ end
14
+
15
+ def extract_from input_data
16
+ results = extractors.lazy
17
+ .map { |x| call_it x, input_data }
18
+ .reject(&:nil?)
19
+
20
+ if results.any?
21
+ results.first
22
+ else
23
+ raise Token::NotFound.new "None of the extractors #{extractors} could find a token"
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def call_it extractor, input_data
30
+ extractor.extract_from(input_data)
31
+ rescue Token::NotFound
32
+ # just skip it
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ require 'faraday_csrf/token_extractors/nokogiri_extractor'
2
+
3
+ module Faraday
4
+ class CSRF
5
+ class MetaTagNokogiriExtractor < NokogiriExtractor
6
+ protected
7
+
8
+ def name
9
+ find('meta[name=csrf-param]').attr('content').text
10
+ rescue Token::NotFound
11
+ nil
12
+ end
13
+
14
+ def value
15
+ find('meta[name=csrf-token]').attr('content').text
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ require 'faraday_csrf/token'
2
+
3
+ module Faraday
4
+ class CSRF
5
+ # Much faster than using Nokogiri
6
+ # use it in combination with Nokogiri extractor,
7
+ # since it might be not as robust
8
+ class MetaTagRegexExtractor
9
+ attr_reader :html
10
+
11
+ class ExtractionError < RuntimeError; end
12
+
13
+ def initialize(html)
14
+ @html = html
15
+ end
16
+
17
+ def value
18
+ content_from_meta_tag('csrf-token')
19
+ end
20
+
21
+ def name
22
+ content_from_meta_tag('csrf-param')
23
+ rescue ExtractionError
24
+ nil
25
+ end
26
+
27
+ def token
28
+ Token.new value: value, name: name
29
+ rescue RuntimeError
30
+ raise Token::NotFound.new 'Could not find CSRF token'
31
+ end
32
+
33
+ private
34
+
35
+ def content_from_meta_tag tag_name
36
+ content_from_tag(find_meta_tag(tag_name))
37
+ end
38
+
39
+ def find_meta_tag(name)
40
+ html.match(/<meta [^>]*name="#{name}"[^>]+>/)[0]
41
+ rescue NoMethodError
42
+ raise ExtractionError.new "Could not find meta tag with name '#{name}'"
43
+ end
44
+
45
+ def content_from_tag token_string
46
+ token_string.match(/ content="([^"]+)"/)[1]
47
+ rescue NoMethodError
48
+ raise ExtractionError.new "Could not find content inside the html tag '#{token_string}'"
49
+ end
50
+
51
+ class << self
52
+ def extract_from html
53
+ new(html).token
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,44 @@
1
+ require 'nokogiri'
2
+
3
+ module Faraday
4
+ class CSRF
5
+ class NokogiriExtractor
6
+ attr_reader :document
7
+ protected :document
8
+
9
+ def initialize(document)
10
+ @document = document
11
+ end
12
+
13
+ def self.extract_from html
14
+ new(Nokogiri::HTML(html)).token
15
+ end
16
+
17
+ def token
18
+ Token.new name: name,
19
+ value: value
20
+ end
21
+
22
+ protected
23
+
24
+ def name
25
+ raise NotImplementedError
26
+ end
27
+
28
+ def value
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def find(css)
33
+ search_result = document.css(css)
34
+
35
+ unless search_result.any?
36
+ raise Token::NotFound.new(
37
+ "Could not find element with selector '#{css}'")
38
+ end
39
+
40
+ search_result
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,20 @@
1
+ module Faraday
2
+ class CSRF
3
+ class TokenFetcher
4
+ def initialize(app:, url:)
5
+ @app = app
6
+ @url = url
7
+ end
8
+
9
+ def call request_env
10
+ new_env = request_env.dup
11
+ new_env.url = request_env.url.dup
12
+ new_env.url.path = @url
13
+
14
+ new_env.method = :get
15
+
16
+ @app.call(new_env)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ require "faraday_csrf/token_fetcher"
2
+ require "faraday_csrf/injects_token_into_body"
3
+
4
+ module Faraday
5
+ class CSRF
6
+ class TokenHandler
7
+ attr_accessor :token
8
+
9
+ def initialize(extractor:, injector:, fetcher:)
10
+ @extractor = extractor
11
+ @injector = injector
12
+ @fetcher = fetcher
13
+ end
14
+
15
+ def handle_request request_env
16
+ @injector.inject(@token, into: request_env)
17
+ rescue InjectsTokenIntoBody::MissingToken
18
+ @fetcher.call request_env
19
+ retry
20
+ end
21
+
22
+ def handle_response response_env
23
+ @token = @extractor.extract_from(response_env.body)
24
+ rescue Token::NotFound
25
+ nil
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module FaradayCsrf
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,27 @@
1
+ require "faraday_csrf/version"
2
+ require 'faraday_csrf/creates_token_handler'
3
+
4
+ module Faraday
5
+ class CSRF
6
+ attr_reader :app
7
+
8
+ def initialize(app, options = {})
9
+ @app = app
10
+ @handler = options.fetch(:token_handler) do
11
+ CreatesTokenHandler.create(options.merge(app: self))
12
+ end
13
+ end
14
+
15
+ def call request_env
16
+ @handler.handle_request request_env
17
+
18
+ app.call(request_env).on_complete do |response_env|
19
+ @handler.handle_response response_env
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ if Faraday::Middleware.respond_to? :register_middleware
26
+ Faraday::Middleware.register_middleware :csrf => Faraday::CSRF
27
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: faraday_csrf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - unmanbearpig
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 10.4.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 10.4.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-expectations
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.21'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.21'
111
+ - !ruby/object:Gem::Dependency
112
+ name: vcr
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.9'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.9'
125
+ - !ruby/object:Gem::Dependency
126
+ name: faraday-cookie_jar
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.0.6
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.0.6
139
+ description: Transparently handles Rails (and maybe not only Rails) CSRF protection,
140
+ in case you need to send requests to an app that doesn't provide an API
141
+ email:
142
+ - unmanbearpig@gmail.com
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".rubocop.yml"
150
+ - ".ruby-version"
151
+ - ".travis.yml"
152
+ - Gemfile
153
+ - README.md
154
+ - Rakefile
155
+ - bin/console
156
+ - bin/setup
157
+ - faraday_csrf.gemspec
158
+ - lib/faraday_csrf.rb
159
+ - lib/faraday_csrf/creates_token_handler.rb
160
+ - lib/faraday_csrf/injects_token_into_body.rb
161
+ - lib/faraday_csrf/token.rb
162
+ - lib/faraday_csrf/token_extractors/first_successful_extractor.rb
163
+ - lib/faraday_csrf/token_extractors/meta_tag_nokogiri_extractor.rb
164
+ - lib/faraday_csrf/token_extractors/meta_tag_regex_extractor.rb
165
+ - lib/faraday_csrf/token_extractors/nokogiri_extractor.rb
166
+ - lib/faraday_csrf/token_fetcher.rb
167
+ - lib/faraday_csrf/token_handler.rb
168
+ - lib/faraday_csrf/version.rb
169
+ homepage: https://github.com/unmanbearpig/faraday_csrf
170
+ licenses: []
171
+ metadata: {}
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.4.8
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: Faraday middleware that automatically adds CSRF tokens to requests
192
+ test_files: []
193
+ has_rdoc: