faraday_middleware-escher 0.2.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -13
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/faraday_middleware-escher.gemspec +4 -0
- data/lib/faraday/middleware/escher/base.rb +2 -2
- data/lib/faraday/middleware/escher/request_signer.rb +14 -2
- data/lib/faraday/middleware/escher/response_validator.rb +39 -1
- data/lib/faraday/middleware/escher.rb +1 -0
- data/lib/faraday_middleware/escher.rb +1 -2
- data/prototype/client.rb +33 -0
- data/prototype/config.ru +78 -0
- data/prototype/credentials.rb +8 -0
- data/spec/escher/base_spec.rb +1 -4
- data/spec/escher/request_signer_spec.rb +9 -12
- metadata +48 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 309400c40fea573a439eb25d11507914f2647b40
|
4
|
+
data.tar.gz: 613bb193f0e441cb8a57a30ad58591fca1fa4497
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0413f1b8ac0506c3565263967b74c32653d9a637bed589deb0f15bac9aa2db53e3738ce751fa4e07267f542cac7f4ddcb6a0aa57da2baa1f99f9281e9e13689
|
7
|
+
data.tar.gz: 62872e747ddb40fc8df37fb2a686c8c44d9495cd9e40dae3a6b527f3e51fcc9ad6ffa1d4a1c357bc3a1956969854a9b8b401c0d7bc3a48c3f24a59bb424a02b8
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# FaradayMiddleware
|
1
|
+
# FaradayMiddleware for Escher secure authorization
|
2
2
|
|
3
3
|
escher sign and validation for faraday http rest client
|
4
4
|
|
@@ -23,25 +23,73 @@ Or install it yourself as:
|
|
23
23
|
The FaradayMiddleware::Escher::RequestSigner will help you sign your requests before sending them
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
|
27
|
-
|
28
|
-
require 'faraday_middleware/escher'
|
29
|
-
conn = Faraday.new do |builder|
|
30
|
-
|
31
|
-
builder.use Faraday::Middleware::Escher::RequestSigner, credential_scope: 'example/credential/scope' do
|
32
|
-
{api_key_id: 'EscherExample', api_secret: 'TheBeginningOfABeautifulFriendship'}
|
33
|
-
end
|
34
26
|
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
require 'faraday_middleware/escher'
|
28
|
+
|
29
|
+
conn = Faraday.new do |builder|
|
30
|
+
|
31
|
+
builder.use FaradayMiddleware::Escher::RequestSigner,
|
32
|
+
credential_scope: CredentialScope,
|
33
|
+
options: AuthOptions,
|
34
|
+
active_key: -> { Escher::Keypool.new.get_active_key('EscherExample') }
|
35
|
+
|
36
|
+
builder.adapter :net_http
|
37
|
+
|
38
|
+
|
39
|
+
end
|
38
40
|
|
39
41
|
```
|
40
42
|
|
41
43
|
|
42
44
|
### Response Validator
|
43
45
|
|
44
|
-
|
46
|
+
The FaradayMiddleware::Escher::ResponseValidator will help you authenticate responses on receiving
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
|
50
|
+
require 'faraday_middleware/escher'
|
51
|
+
|
52
|
+
conn = Faraday.new do |builder|
|
53
|
+
|
54
|
+
builder.use FaradayMiddleware::Escher::ResponseValidator,
|
55
|
+
credential_scope: CredentialScope,
|
56
|
+
options: AuthOptions,
|
57
|
+
keydb_constructor: -> { Escher::Keypool.new.get_key_db }
|
58
|
+
|
59
|
+
builder.adapter :net_http
|
60
|
+
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
```
|
65
|
+
|
66
|
+
### You can mix the two in one case
|
67
|
+
|
68
|
+
Who loves Man in the Middle?
|
69
|
+
If you not, this is your setup!
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
|
73
|
+
require 'faraday_middleware/escher'
|
74
|
+
|
75
|
+
conn = Faraday.new do |builder|
|
76
|
+
|
77
|
+
builder.use FaradayMiddleware::Escher::RequestSigner,
|
78
|
+
credential_scope: CredentialScope,
|
79
|
+
options: AuthOptions,
|
80
|
+
active_key: -> { Escher::Keypool.new.get_active_key('EscherExample') }
|
81
|
+
|
82
|
+
builder.use FaradayMiddleware::Escher::ResponseValidator,
|
83
|
+
credential_scope: CredentialScope,
|
84
|
+
options: AuthOptions,
|
85
|
+
keydb_constructor: -> { Escher::Keypool.new.get_key_db }
|
86
|
+
|
87
|
+
builder.adapter :net_http
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
```
|
45
93
|
|
46
94
|
## Contributing
|
47
95
|
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.1
|
@@ -20,6 +20,10 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_development_dependency('rspec')
|
21
21
|
spec.add_development_dependency('webmock')
|
22
22
|
|
23
|
+
spec.add_development_dependency('rack')
|
24
|
+
spec.add_development_dependency('escher-keypool')
|
25
|
+
spec.add_development_dependency('escher-rack_middleware')
|
26
|
+
|
23
27
|
spec.add_dependency('faraday')
|
24
28
|
spec.add_dependency('escher')
|
25
29
|
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'faraday/middleware/escher'
|
2
3
|
class Faraday::Middleware::Escher::Base < Faraday::Middleware
|
3
4
|
|
4
|
-
def initialize(app,options={}
|
5
|
+
def initialize(app,options={})
|
5
6
|
|
6
7
|
super(app)
|
7
8
|
@host = options[:host] || Socket.gethostname
|
8
9
|
|
9
10
|
@escher_options = options[:options] || {}
|
10
11
|
@escher_credential_scope = options[:credential_scope] || raise(ArgumentError,'missing escher credential scope!')
|
11
|
-
@escher_keydb_constructor = escher_keydb_constructor || raise(ArgumentError,'missing escher constructor')
|
12
12
|
|
13
13
|
end
|
14
14
|
|
@@ -1,14 +1,26 @@
|
|
1
|
+
require 'faraday/middleware/escher'
|
1
2
|
class Faraday::Middleware::Escher::RequestSigner < Faraday::Middleware::Escher::Base
|
2
3
|
|
4
|
+
def initialize(app,options={},&active_key)
|
5
|
+
|
6
|
+
super(app,options)
|
7
|
+
|
8
|
+
active_key_cons = active_key || options[:active_key] || options[:key]
|
9
|
+
raise('Escher active key constructor must be a lambda/block') unless active_key_cons.is_a?(Proc)
|
10
|
+
@escher_active_key_constructor = active_key_cons
|
11
|
+
|
12
|
+
end
|
13
|
+
|
3
14
|
def call(env)
|
4
15
|
|
5
16
|
escher = ::Escher::Auth.new(@escher_credential_scope, @escher_options)
|
6
17
|
|
7
18
|
uri_path = env[:url].path
|
8
19
|
endpoint = uri_path.empty? ? '/' : uri_path
|
20
|
+
endpoint_with_query = [endpoint,env[:url].query].join('?')
|
9
21
|
|
10
22
|
request_data = {
|
11
|
-
uri:
|
23
|
+
uri: endpoint_with_query,
|
12
24
|
method: env[:method].to_s.upcase,
|
13
25
|
headers: env[:request_headers].map{|k,v| [k,v] }.push(['host',@host])
|
14
26
|
}
|
@@ -17,7 +29,7 @@ class Faraday::Middleware::Escher::RequestSigner < Faraday::Middleware::Escher::
|
|
17
29
|
|
18
30
|
escher.sign!(
|
19
31
|
request_data,
|
20
|
-
@
|
32
|
+
@escher_active_key_constructor.call,
|
21
33
|
request_data[:headers].map{|ary| ary[0] }
|
22
34
|
)
|
23
35
|
|
@@ -1,2 +1,40 @@
|
|
1
|
-
|
1
|
+
require 'faraday/middleware/escher'
|
2
|
+
class Faraday::Middleware::Escher::ResponseValidator < Faraday::Middleware::Escher::Base
|
3
|
+
|
4
|
+
def initialize(app,options={},&keydb_as_block)
|
5
|
+
|
6
|
+
super(app,options)
|
7
|
+
|
8
|
+
keydb_constructor = keydb_as_block || options[:keydb_constructor] || options[:keydb]
|
9
|
+
raise('Key DB constuctor must be a lambda/block') unless keydb_constructor.is_a?(Proc)
|
10
|
+
@escher_active_key_constructor = keydb_constructor
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(request_env)
|
15
|
+
@app.call(request_env).on_complete do |env_on_response|
|
16
|
+
authenticate_env!(env_on_response)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def authenticate_env!(env_on_response)
|
23
|
+
|
24
|
+
escher = ::Escher::Auth.new(@escher_credential_scope, @escher_options)
|
25
|
+
|
26
|
+
url_path = env_on_response[:url].path
|
27
|
+
url_path = '/' if url_path.empty?
|
28
|
+
|
29
|
+
escher_hash_env = {
|
30
|
+
uri: url_path,
|
31
|
+
method: env_on_response[:method].to_s.upcase,
|
32
|
+
headers: env_on_response[:response_headers].map{|k,v| [k,v] }
|
33
|
+
}
|
34
|
+
|
35
|
+
escher_hash_env[:body] = env_on_response[:body] if env_on_response[:body]
|
36
|
+
escher.authenticate(escher_hash_env,@escher_active_key_constructor.call)
|
37
|
+
|
38
|
+
end
|
39
|
+
|
2
40
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
#backwardCompatibility
|
2
|
-
require 'faraday/middleware/escher'
|
3
|
-
|
4
2
|
begin
|
5
3
|
require 'faraday_middleware'
|
6
4
|
rescue LoadError
|
@@ -11,4 +9,5 @@ unless defined?(FaradayMiddleware)
|
|
11
9
|
end
|
12
10
|
end
|
13
11
|
|
12
|
+
require 'faraday/middleware/escher'
|
14
13
|
FaradayMiddleware::Escher ||= ::Faraday::Middleware::Escher
|
data/prototype/client.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.absolute_path(File.join(__dir__, '..', 'lib')))
|
2
|
+
|
3
|
+
require_relative 'credentials'
|
4
|
+
|
5
|
+
require 'faraday_middleware/escher'
|
6
|
+
|
7
|
+
conn = Faraday.new do |builder|
|
8
|
+
|
9
|
+
builder.use FaradayMiddleware::Escher::RequestSigner,
|
10
|
+
credential_scope: CredentialScope,
|
11
|
+
options: AuthOptions,
|
12
|
+
active_key: -> { Escher::Keypool.new.get_active_key('EscherExample') }
|
13
|
+
|
14
|
+
# builder.use FaradayMiddleware::Escher::ResponseValidator,
|
15
|
+
# credential_scope: CredentialScope,
|
16
|
+
# options: AuthOptions,
|
17
|
+
# keydb_constructor: -> { Escher::Keypool.new.get_key_db }
|
18
|
+
|
19
|
+
builder.adapter :net_http
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'json'
|
25
|
+
|
26
|
+
puts "\nResponse:",
|
27
|
+
conn.get { |r|
|
28
|
+
r.url('http://localhost:9292')
|
29
|
+
r.body='{ "name": "Unagi" }'
|
30
|
+
r.headers['X-Origin'] = JSON.generate(sender: 'cat', host: 'suite42')
|
31
|
+
r.params['kutya1']= 'cica1'
|
32
|
+
r.params['kutya2']= 'cica2'
|
33
|
+
}.body.inspect
|
data/prototype/config.ru
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative 'credentials'
|
2
|
+
|
3
|
+
require 'rack'
|
4
|
+
require 'escher/rack_middleware'
|
5
|
+
Escher::RackMiddleware.config do |c|
|
6
|
+
c.add_escher_authenticator { Escher::Auth.new(CredentialScope, AuthOptions) }
|
7
|
+
c.add_credential_updater { Escher::Keypool.new.get_key_db }
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'socket'
|
11
|
+
class YourAwesomeApp
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
|
15
|
+
response = Rack::Response.new
|
16
|
+
response_payload = 'OK'
|
17
|
+
|
18
|
+
escher = ::Escher::Auth.new(CredentialScope, AuthOptions)
|
19
|
+
|
20
|
+
request_data = {
|
21
|
+
|
22
|
+
uri: '/',
|
23
|
+
method: 'GET',
|
24
|
+
headers: [['host',Socket.gethostname]],
|
25
|
+
body: response_payload
|
26
|
+
|
27
|
+
}
|
28
|
+
|
29
|
+
escher.sign!(
|
30
|
+
request_data,
|
31
|
+
Escher::Keypool.new.get_active_key( env['escher.request.api_key_id'] ),
|
32
|
+
response.headers.map { |k, _| k }
|
33
|
+
)
|
34
|
+
|
35
|
+
request_data[:headers].each do |key,value|
|
36
|
+
response.headers[key]=value
|
37
|
+
end
|
38
|
+
|
39
|
+
response.headers['kutya']='cica'
|
40
|
+
|
41
|
+
response.write response_payload
|
42
|
+
response.status = 200
|
43
|
+
response.finish
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
require 'yaml'
|
50
|
+
class EscherResponseSigner
|
51
|
+
|
52
|
+
def initialize(app,options={})
|
53
|
+
@app = app
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
def call(env)
|
59
|
+
rstatus,rheaders,rbody = @app.call(env)
|
60
|
+
response = Rack::Response.new(rbody,rstatus,rheaders)
|
61
|
+
|
62
|
+
<<-YAML
|
63
|
+
|
64
|
+
YAML
|
65
|
+
|
66
|
+
puts YAML.dump response
|
67
|
+
# puts YAML.dump response
|
68
|
+
|
69
|
+
|
70
|
+
response
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
use EscherResponseSigner
|
76
|
+
use Escher::RackMiddleware
|
77
|
+
|
78
|
+
run YourAwesomeApp.new
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'escher-keypool'
|
2
|
+
|
3
|
+
ENV['KEY_POOL'] = '[{"keyId":"EscherExample","secret":"TheBeginningOfABeautifulFriendship","acceptOnly":0}]'
|
4
|
+
ENV['ESCHEREXAMPLE_KEYID'] = 'EscherExample'
|
5
|
+
|
6
|
+
CredentialScope = 'example/credential/scope'
|
7
|
+
AuthOptions = {}
|
8
|
+
ESCHER_KEY = {api_key_id: 'EscherExample', api_secret: 'TheBeginningOfABeautifulFriendship'}
|
data/spec/escher/base_spec.rb
CHANGED
@@ -14,10 +14,7 @@ describe FaradayMiddleware::Escher::Base do
|
|
14
14
|
}
|
15
15
|
}
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
subject{ self.described_class.new(app,options) {key_db} }
|
17
|
+
subject{ self.described_class.new(app,options) }
|
21
18
|
|
22
19
|
before do
|
23
20
|
allow(Socket).to receive(:gethostname).and_return(host)
|
@@ -2,6 +2,8 @@ require_relative '../spec_helper'
|
|
2
2
|
describe Faraday::Middleware::Escher::RequestSigner do
|
3
3
|
describe 'this is a faraday middleware witch instance will response to call method' do
|
4
4
|
|
5
|
+
let(:key_db){{api_key_id: 'EscherExample', api_secret: 'TheBeginningOfABeautifulFriendship'}}
|
6
|
+
|
5
7
|
let(:api_key) { 'superKey' }
|
6
8
|
let(:api_secret) { 'superSecret' }
|
7
9
|
let(:host) { 'localhost' }
|
@@ -9,8 +11,13 @@ describe Faraday::Middleware::Escher::RequestSigner do
|
|
9
11
|
let(:target_url) { "http://api-with-escher.example.com" }
|
10
12
|
let(:stubs) { Faraday::Adapter::Test::Stubs.new }
|
11
13
|
|
12
|
-
let(:request_expectations){ -> env {} }
|
13
|
-
let(:response_expectations){ -> env {} }
|
14
|
+
let(:request_expectations){ -> env { @request_env = env } }
|
15
|
+
let(:response_expectations){ -> env { @response_env = env } }
|
16
|
+
|
17
|
+
before do
|
18
|
+
@request_env = nil
|
19
|
+
@response_env = nil
|
20
|
+
end
|
14
21
|
|
15
22
|
subject do
|
16
23
|
|
@@ -35,16 +42,6 @@ describe Faraday::Middleware::Escher::RequestSigner do
|
|
35
42
|
|
36
43
|
describe '#call' do
|
37
44
|
|
38
|
-
before do
|
39
|
-
@env = nil
|
40
|
-
end
|
41
|
-
|
42
|
-
let(:request_expectations) do
|
43
|
-
-> env do
|
44
|
-
@request_env = env
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
45
|
it 'should insert escher request headers for the call' do
|
49
46
|
|
50
47
|
expect( subject.get(target_url).status ).to eq 200
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday_middleware-escher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Luzsi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,48 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: escher-keypool
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: escher-rack_middleware
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: faraday
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +156,9 @@ files:
|
|
114
156
|
- lib/faraday/middleware/escher/request_signer.rb
|
115
157
|
- lib/faraday/middleware/escher/response_validator.rb
|
116
158
|
- lib/faraday_middleware/escher.rb
|
159
|
+
- prototype/client.rb
|
160
|
+
- prototype/config.ru
|
161
|
+
- prototype/credentials.rb
|
117
162
|
- spec/escher/base_spec.rb
|
118
163
|
- spec/escher/request_signer_spec.rb
|
119
164
|
- spec/spec_helper.rb
|
@@ -145,3 +190,4 @@ test_files:
|
|
145
190
|
- spec/escher/base_spec.rb
|
146
191
|
- spec/escher/request_signer_spec.rb
|
147
192
|
- spec/spec_helper.rb
|
193
|
+
has_rdoc:
|