ey_api_hmac 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile CHANGED
@@ -8,4 +8,6 @@ gem 'json'
8
8
 
9
9
  group :test, :development do
10
10
  gem 'halorgium-auth-hmac'
11
+ gem 'rack-client'
12
+ gem 'rack-contrib'
11
13
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ey_api_hmac (0.0.1)
4
+ ey_api_hmac (0.0.5)
5
5
  json
6
6
  rack-client
7
7
 
@@ -14,6 +14,8 @@ GEM
14
14
  rack (1.3.2)
15
15
  rack-client (0.4.0)
16
16
  rack (>= 1.0.0)
17
+ rack-contrib (1.1.0)
18
+ rack (>= 0.9.1)
17
19
  rake (0.9.2)
18
20
  rspec (2.6.0)
19
21
  rspec-core (~> 2.6.0)
@@ -31,5 +33,7 @@ DEPENDENCIES
31
33
  ey_api_hmac!
32
34
  halorgium-auth-hmac
33
35
  json
36
+ rack-client
37
+ rack-contrib
34
38
  rake
35
39
  rspec
@@ -1,39 +1,58 @@
1
1
  module EY
2
2
  module ApiHMAC
3
3
  module ApiAuth
4
- CONSUMER = "ey_api_hmac.consumer_id"
5
4
 
6
- #a Server middleware to validate requests, setup with a block to lookup the auth_key based on auth_id
5
+ # Server middleware to validate requests, setup with a block that returns the auth_key given an auth_id
6
+ #
7
+ # To pass authentication information through to your app, be sure to set something in env.
8
+ # Look at EY::ApiHMAC::ApiAuth::Server for an example
9
+ #
10
+ # raise EY::ApiHMAC::HmacAuthFail, "your message" to fail authentication.
7
11
  class LookupServer
8
12
  def initialize(app, &lookup)
9
13
  @app, @lookup = app, lookup
10
14
  end
11
15
 
12
- #TODO: rescue HmacAuthFail and return 403?
13
16
  def call(env)
14
- ApiHMAC.authenticate!(env) do |auth_id|
15
- @lookup.call(env, auth_id)
17
+ begin
18
+ ApiHMAC.authenticate!(env) do |auth_id|
19
+ @lookup.call(env, auth_id)
20
+ end
21
+ rescue HmacAuthFail
22
+ return [401, {}, ["Authentication failure"]]
16
23
  end
17
24
  @app.call(env)
18
25
  end
19
26
  end
20
27
 
21
- #a Server middleware to validate requests, setup with a class that responds_to :find_by_auth_id, :id, :auth_key
28
+ # Consumer id is set to this env key when using EY::ApiHMAC::ApiAuth::Server
29
+ CONSUMER = "ey_api_hmac.consumer_id"
30
+
31
+ # Server middleware to validate requests
32
+ #
33
+ # Initialize with a class that responds_to :find_by_auth_id, :id, :auth_key
34
+ #
35
+ # Sets env['ey_api_hmac.consumer_id'] to the id of the object returned by class.find_by_auth_id(auth_id)
22
36
  class Server < LookupServer
23
37
  def initialize(app, klass)
38
+ unless klass.respond_to?(:find_by_auth_id)
39
+ raise ArgumentError, "EY::ApiHMAC::ApiAuth::Server class must respond to find_by_auth_id"
40
+ end
41
+
24
42
  lookup = Proc.new do |env, auth_id|
25
43
  if consumer = klass.find_by_auth_id(auth_id)
26
44
  env[CONSUMER] = consumer.id
27
45
  consumer.auth_key
28
46
  else
29
- raise "no #{klass} consumer #{auth_id.inspect}"
47
+ raise HmacAuthFail
30
48
  end
31
49
  end
50
+
32
51
  super(app, &lookup)
33
52
  end
34
53
  end
35
54
 
36
- #the Client middleware that's used to add authentication to requests
55
+ # Client middleware that's used to add authentication to requests.
37
56
  class Client
38
57
  def initialize(app, auth_id, auth_key)
39
58
  @app, @auth_id, @auth_key = app, auth_id, auth_key
@@ -46,4 +65,4 @@ module EY
46
65
 
47
66
  end
48
67
  end
49
- end
68
+ end
@@ -1,5 +1,5 @@
1
1
  module EY
2
2
  module ApiHMAC
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
@@ -1,5 +1,9 @@
1
+ require 'spec_helper'
2
+
1
3
  require 'ey_api_hmac'
2
4
  require 'auth-hmac'
5
+ require 'rack/contrib'
6
+ require 'time'
3
7
 
4
8
  describe EY::ApiHMAC::ApiAuth do
5
9
 
@@ -10,8 +14,8 @@ describe EY::ApiHMAC::ApiAuth do
10
14
  before(:each) do
11
15
  @env = {'PATH_INFO' => "/path/to/put",
12
16
  'QUERY_STRING' => 'foo=bar&bar=foo',
13
- 'CONTENT_TYPE' => 'text/plain',
14
- 'HTTP_CONTENT_MD5' => 'blahblah',
17
+ 'CONTENT_TYPE' => 'text/plain',
18
+ 'HTTP_CONTENT_MD5' => 'blahblah',
15
19
  'REQUEST_METHOD' => "PUT",
16
20
  'HTTP_DATE' => "Thu, 10 Jul 2008 03:29:56 GMT",
17
21
  "rack.input" => StringIO.new}
@@ -40,8 +44,8 @@ describe EY::ApiHMAC::ApiAuth do
40
44
  end
41
45
 
42
46
  it "signs as expected with AuthHMAC" do
43
- AuthHMAC.sign!(@request, "my-key-id", "secret")
44
- @request['Authorization'].should == @expected
47
+ AuthHMAC.sign!(@request, "my-key-id", "secret")
48
+ @request['Authorization'].should == @expected
45
49
  end
46
50
 
47
51
  it "signs as expected with ApiAuth" do
@@ -85,13 +89,76 @@ describe EY::ApiHMAC::ApiAuth do
85
89
  end
86
90
  end
87
91
 
92
+ describe "middleware behavior" do
93
+ MockApp = lambda do |is_found, auth_key|
94
+ Rack::Builder.new do
95
+ use EY::ApiHMAC::ApiAuth::Server, MockAuth.new(is_found, auth_key)
96
+ run lambda { |x| [200, {}, ['Success']] }
97
+ end
98
+ end
99
+
100
+ def hmac_client(client_auth_key, app)
101
+ client = Rack::Client.new('http://localhost') do
102
+ use Rack::Config do |env|
103
+ env['HTTP_DATE'] = Time.now.httpdate
104
+ end
105
+ use EY::ApiHMAC::ApiAuth::Client, 1, client_auth_key
106
+ run app
107
+ end
108
+ end
109
+
110
+ it "responds 401 Unauthorized with no authorization" do
111
+ client = Rack::Client.new('http://localhost') do
112
+ run MockApp.call(true, 'key')
113
+ end
114
+
115
+ response = client.get('/')
116
+ response.status.should == 401
117
+ response.body.should_not == 'Success'
118
+ end
119
+
120
+ it "works with correct signing" do
121
+ auth_key = 'key'
122
+ is_found = true
123
+
124
+ client = hmac_client(auth_key, MockApp.call(is_found, auth_key))
125
+
126
+ response = client.get('/')
127
+ response.status.should == 200
128
+ response.body.should == 'Success'
129
+ end
130
+
131
+ it "fails when auth_key isn't correct" do
132
+ auth_id = 1
133
+ is_found = true
134
+
135
+ client = hmac_client('wrongkey', MockApp.call(is_found, 'rightkey'))
136
+
137
+ response = client.get('/')
138
+ response.status.should == 401
139
+ response.body.should_not == 'Success'
140
+ end
141
+
142
+ it "fails when no consumer by that auth_id is found" do
143
+ auth_id = 1
144
+ is_found = false
145
+ auth_key = 'key'
146
+
147
+ client = hmac_client(auth_key, MockApp.call(is_found, auth_key))
148
+
149
+ response = client.get('/')
150
+ response.status.should == 401
151
+ response.body.should_not == 'Success'
152
+ end
153
+ end
88
154
  end
89
155
 
156
+
90
157
  describe "without CONTENT_MD5" do
91
158
  before do
92
159
  @env = {'PATH_INFO' => "/path/to/put",
93
160
  'QUERY_STRING' => 'foo=bar&bar=foo',
94
- 'CONTENT_TYPE' => 'text/plain',
161
+ 'CONTENT_TYPE' => 'text/plain',
95
162
  'REQUEST_METHOD' => "PUT",
96
163
  'HTTP_DATE' => "Thu, 10 Jul 2008 03:29:56 GMT",
97
164
  "rack.input" => StringIO.new("something, something?")}
@@ -114,7 +181,6 @@ describe EY::ApiHMAC::ApiAuth do
114
181
  end
115
182
 
116
183
  end
117
-
118
184
  end
119
185
 
120
186
  it "complains when there is no HTTP_DATE" do
@@ -128,4 +194,4 @@ describe EY::ApiHMAC::ApiAuth do
128
194
  }.should raise_error(/'HTTP_DATE' header missing and required/)
129
195
  end
130
196
 
131
- end
197
+ end
@@ -0,0 +1,20 @@
1
+ class MockAuth
2
+ def initialize(is_found, auth_key)
3
+ @is_found = is_found
4
+ @auth_key = auth_key
5
+ end
6
+
7
+ attr_reader :auth_key
8
+
9
+ def find_by_auth_id(auth_id)
10
+ if @is_found
11
+ self
12
+ else
13
+ nil
14
+ end
15
+ end
16
+
17
+ def id
18
+ 1
19
+ end
20
+ end
data/spec/sso_spec.rb CHANGED
@@ -69,5 +69,4 @@ describe EY::ApiHMAC do
69
69
  # signature – HMAC digest of the other parameters and url (using the API secret)
70
70
 
71
71
  end
72
-
73
- end
72
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ey_api_hmac
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Jacob Burkhart & Thorben Schr\xC3\xB6der & David Calavera & others"
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-17 00:00:00 Z
18
+ date: 2011-08-18 00:00:00 -07:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rack-client
@@ -69,6 +70,7 @@ extensions: []
69
70
  extra_rdoc_files: []
70
71
 
71
72
  files:
73
+ - .gitignore
72
74
  - Gemfile
73
75
  - Gemfile.lock
74
76
  - LICENSE
@@ -81,7 +83,9 @@ files:
81
83
  - lib/ey_api_hmac/sso.rb
82
84
  - lib/ey_api_hmac/version.rb
83
85
  - spec/api_auth_spec.rb
86
+ - spec/spec_helper.rb
84
87
  - spec/sso_spec.rb
88
+ has_rdoc: true
85
89
  homepage: ""
86
90
  licenses: []
87
91
 
@@ -111,10 +115,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
115
  requirements: []
112
116
 
113
117
  rubyforge_project: ey_api_hmac
114
- rubygems_version: 1.8.8
118
+ rubygems_version: 1.4.2
115
119
  signing_key:
116
120
  specification_version: 3
117
121
  summary: HMAC Rack basic implementation for Engine Yard services
118
122
  test_files:
119
123
  - spec/api_auth_spec.rb
124
+ - spec/spec_helper.rb
120
125
  - spec/sso_spec.rb