api-auth 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionpack (2.3.10)
5
+ activesupport (= 2.3.10)
6
+ rack (~> 1.1.0)
7
+ activeresource (2.3.10)
8
+ activesupport (= 2.3.10)
9
+ activesupport (2.3.10)
10
+ amatch (0.2.5)
11
+ curb (0.7.10)
12
+ diff-lcs (1.1.2)
13
+ git (1.2.5)
14
+ jeweler (1.5.2)
15
+ bundler (~> 1.0.0)
16
+ git (>= 1.2.5)
17
+ rake
18
+ mime-types (1.16)
19
+ rack (1.1.0)
20
+ rake (0.8.7)
21
+ rest-client (1.6.1)
22
+ mime-types (>= 1.16)
23
+ rspec (2.4.0)
24
+ rspec-core (~> 2.4.0)
25
+ rspec-expectations (~> 2.4.0)
26
+ rspec-mocks (~> 2.4.0)
27
+ rspec-core (2.4.0)
28
+ rspec-expectations (2.4.0)
29
+ diff-lcs (~> 1.1.2)
30
+ rspec-mocks (2.4.0)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ actionpack (~> 2.3.2)
37
+ activeresource (~> 2.3.2)
38
+ amatch (~> 0.2.5)
39
+ bundler (~> 1.0.0)
40
+ curb (~> 0.7.7)
41
+ jeweler (~> 1.5.2)
42
+ rest-client (~> 1.6.0)
43
+ rspec (~> 2.4.0)
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
- api-auth
2
- ========
1
+ ApiAuth
2
+ =======
3
3
 
4
4
  Logins and passwords are for humans. Communication between applications need to
5
5
  be protected through different means.
6
6
 
7
- api-auth is Ruby gem designed to be used both in your client and server
8
- HTTP-based applications. It implements the same authentication methods (HMAC)
7
+ ApiAuth is a Ruby gem designed to be used both in your client and server
8
+ HTTP-based applications. It implements the same authentication methods (HMAC-SHA1)
9
9
  used by Amazon Web Services.
10
10
 
11
11
  The gem will sign your requests on the client side and authenticate that
@@ -14,28 +14,25 @@ Rails ActiveResource, it will integrate with that. It will even generate the
14
14
  secret keys necessary for your clients to sign their requests.
15
15
 
16
16
  Since it operates entirely using HTTP headers, the server component does not
17
- have to be written in the same language as the clients. Any language with
18
- OpenSSL bindings will suffice.
17
+ have to be written in the same language as the clients.
19
18
 
20
19
  How it works
21
20
  ------------
22
21
 
23
22
  1. A canonical string is first created using your HTTP headers containing the
24
- content-type, content-MD5, request URI and the
25
- timestamp. The canonical string string is computed as follows:
23
+ content-type, content-MD5, request URI and the timestamp. If content-type or
24
+ content-MD5 are not present, then a blank string is used in their place. If the
25
+ timestamp isn't present, a valid HTTP date is automatically added to the
26
+ request. The canonical string string is computed as follows:
26
27
 
27
- canonical_string = "<content-type>,<content-MD5>,<URI>,<timestamp>"
28
-
29
- If content-type or content-MD5 are not present, then a blank string is used in
30
- their place. If the timestamp isn't present, a valid HTTP date is automatically
31
- added to the request.
28
+ canonical_string = 'content-type,content-MD5,request URI,timestamp'
32
29
 
33
30
  2. This string is then used to create the signature which is a Base64 encoded
34
31
  SHA1 HMAC, using the client's private secret key.
35
32
 
36
33
  3. This signature is then added as the `Authorization` HTTP header in the form:
37
34
 
38
- Authorization = APIAuth <client access id>:<signature from step 2>
35
+ Authorization = APIAuth 'client access id':'signature from step 2'
39
36
 
40
37
  5. On the server side, the SHA1 HMAC is computed in the same way using the
41
38
  request headers and the client's secret key, which is known to only
@@ -52,18 +49,19 @@ References
52
49
  * [HMAC algorithm](http://en.wikipedia.org/wiki/HMAC)
53
50
  * [RFC 2104 (HMAC)](http://tools.ietf.org/html/rfc2104)
54
51
 
55
- Usage
56
- -----
52
+ Install
53
+ -------
57
54
 
58
- ### Install ###
55
+ The gem doesn't have any dependencies outside of having a working OpenSSL
56
+ configuration for your Ruby VM. To install:
59
57
 
60
- [sudo] gem install api-auth
58
+ [sudo] gem install api_auth
61
59
 
62
- ### Supported Request Objects ###
60
+ Clients
61
+ -------
63
62
 
64
- ApiAuth supports most request objects. With the support of
65
- ActionController::Request, ApiAuth is fully compatible with Rails. Support for
66
- other request objects can be added as a request driver.
63
+ ApiAuth supports many popular HTTP clients. Support for other clients can be
64
+ added as a request driver.
67
65
 
68
66
  Here is the current list of supported request objects:
69
67
 
@@ -71,16 +69,100 @@ Here is the current list of supported request objects:
71
69
  * ActionController::Request
72
70
  * Curb (Curl::Easy)
73
71
  * RestClient
72
+
73
+ ### HTTP Client Objects ###
74
+
75
+ Here's a sample implementation of signing a request created with RestClient. For
76
+ more examples, please check out the ApiAuth Spec where every supported HTTP
77
+ client is tested.
78
+
79
+ Assuming you have a client access id and secret as follows:
80
+
81
+ @access_id = "1044"
82
+ @secret_key = ApiAuth.generate_secret_key
74
83
 
75
- ### ActiveResource ###
84
+ A typical RestClient PUT request may look like:
85
+
86
+ headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
87
+ 'Content-Type' => "text/plain",
88
+ 'Date' => "Mon, 23 Jan 1984 03:29:56 GMT" }
89
+ @request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
90
+ :headers => headers,
91
+ :method => :put)
92
+
93
+ To sign that request, simply call the `sign!` method as follows:
94
+
95
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key)
96
+
97
+ The proper `Authorization` request header has now been added to that request
98
+ object and it's ready to be transmitted. It's recommended that you sign the
99
+ request as one of the last steps in building the request to ensure the headers
100
+ don't change after the signing process which would cause the authentication
101
+ check to fail on the server side.
102
+
103
+ ### ActiveResource Clients ###
104
+
105
+ ApiAuth can transparently protect your ActiveResource communications with a
106
+ single configuration line:
76
107
 
77
108
  class MyResource < ActiveResource::Base
78
- with_api_auth(<access_id>, <secret_key>)
109
+ with_api_auth(access_id, secret_key)
110
+ end
111
+
112
+ This will automatically sign all outgoing ActiveResource requests from your app.
113
+
114
+ Server
115
+ ------
116
+
117
+ ApiAuth provides some built in methods to help you generate API keys for your
118
+ clients as well as verifying incoming API requests.
119
+
120
+ To generate a Base64 encoded API key for a client:
121
+
122
+ ApiAuth.generate_secret_key
123
+
124
+ To validate whether or not a request is authentic:
125
+
126
+ ApiAuth.authentic?(signed_request, secret_key)
127
+
128
+ If your server is a Rails app, the signed request will be the `request` object.
129
+
130
+ In order to obtain the secret key for the client, you first need to look up the
131
+ client's access_id. ApiAuth can pull that from the request headers for you:
132
+
133
+ ApiAuth.access_id(signed_request)
134
+
135
+ Once you've looked up the client's record via the access id, you can then verify
136
+ whether or not the request is authentic. Typically, the access id for the client
137
+ will be their record's primary key in the DB that stores the record or some other
138
+ public unique identifier for the client.
139
+
140
+ Here's a sample method that can be used in a `before_filter` if your server is a
141
+ Rails app:
142
+
143
+ before_filter :api_authenticate
144
+
145
+ def api_authenticate
146
+ @current_account = Account.find_by_access_id(ApiAuth.access_id(request))
147
+ return ApiAuth.authentic?(request, @current_account.secret_key) unless @current_account.nil?
148
+ false
79
149
  end
150
+
151
+ Development
152
+ -----------
80
153
 
81
- ### Server ###
154
+ ApiAuth uses bundler for gem dependencies and RSpec for testing. Developing the
155
+ gem requires that you have all supported HTTP clients installed. Bundler will
156
+ take care of all that for you.
82
157
 
158
+ To run the tests:
83
159
 
160
+ rake spec
161
+
162
+ If you'd like to add support for additional HTTP clients, check out the already
163
+ implemented drivers in `lib/api_auth/request_drivers` for reference. All of
164
+ the public methods for each driver are required to be implemented by your driver.
165
+
84
166
  Authors
85
167
  -------
86
168
 
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ require 'rake'
12
12
  require 'jeweler'
13
13
  Jeweler::Tasks.new do |gem|
14
14
  gem.name = "api-auth"
15
- gem.homepage = "http://github.com/geminisbs/api-auth"
15
+ gem.homepage = "http://github.com/mgomes/api_auth"
16
16
  gem.license = "MIT"
17
17
  gem.summary = %Q{Simple HMAC authentication for your APIs}
18
18
  gem.description = %Q{Full HMAC auth implementation for use in your gems and Rails apps.}
@@ -39,7 +39,7 @@ Rake::RDocTask.new do |rdoc|
39
39
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
40
 
41
41
  rdoc.rdoc_dir = 'rdoc'
42
- rdoc.title = "api-auth #{version}"
42
+ rdoc.title = "api_auth #{version}"
43
43
  rdoc.rdoc_files.include('README*')
44
44
  rdoc.rdoc_files.include('lib/**/*.rb')
45
45
  end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.1
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{api_auth}
8
+ s.version = "0.9.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Mauricio Gomes"]
12
+ s.date = %q{2011-01-30}
13
+ s.description = %q{Full HMAC auth implementation for use in your gems and Rails apps.}
14
+ s.email = %q{mgomes@geminisbs.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "Rakefile",
25
+ "lib/api_auth.rb",
26
+ "spec/api_auth_spec.rb",
27
+ "spec/spec_helper.rb"
28
+ ]
29
+ s.homepage = %q{http://github.com/geminisbs/api-auth}
30
+ s.licenses = ["MIT"]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.4.1}
33
+ s.summary = %q{Simple HMAC authentication for your APIs}
34
+ s.test_files = [
35
+ "spec/api_auth_spec.rb",
36
+ "spec/headers_spec.rb",
37
+ "spec/helpers_spec.rb",
38
+ "spec/railtie_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
47
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
48
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
49
+ s.add_development_dependency(%q<amatch>, ["~> 0.2.5"])
50
+ s.add_development_dependency(%q<curb>, ["~> 0.7.7"])
51
+ s.add_development_dependency(%q<rest-client>, ["~> 1.6.0"])
52
+ s.add_development_dependency(%q<actionpack>, ["~> 2.3.2"])
53
+ s.add_development_dependency(%q<activeresource>, ["~> 2.3.2"])
54
+ else
55
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
56
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
58
+ s.add_dependency(%q<amatch>, ["~> 0.2.5"])
59
+ s.add_dependency(%q<curb>, ["~> 0.7.7"])
60
+ s.add_dependency(%q<rest-client>, ["~> 1.6.0"])
61
+ s.add_dependency(%q<actionpack>, ["~> 2.3.2"])
62
+ s.add_dependency(%q<activeresource>, ["~> 2.3.2"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
66
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
68
+ s.add_dependency(%q<amatch>, ["~> 0.2.5"])
69
+ s.add_dependency(%q<curb>, ["~> 0.7.7"])
70
+ s.add_dependency(%q<rest-client>, ["~> 1.6.0"])
71
+ s.add_dependency(%q<actionpack>, ["~> 2.3.2"])
72
+ s.add_dependency(%q<activeresource>, ["~> 2.3.2"])
73
+ end
74
+ end
75
+
@@ -1,14 +1,2 @@
1
- require 'openssl'
2
- require 'base64'
3
-
4
- require 'api-auth/errors'
5
- require 'api-auth/helpers'
6
-
7
- require 'api-auth/request_drivers/net_http'
8
- require 'api-auth/request_drivers/curb'
9
- require 'api-auth/request_drivers/rest_client'
10
- require 'api-auth/request_drivers/action_controller'
11
-
12
- require 'api-auth/headers'
13
- require 'api-auth/base'
14
- require 'api-auth/railtie'
1
+ # So you can require "api-auth" instead of "api_auth"
2
+ require "api_auth"
@@ -0,0 +1,14 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ require 'api_auth/errors'
5
+ require 'api_auth/helpers'
6
+
7
+ require 'api_auth/request_drivers/net_http'
8
+ require 'api_auth/request_drivers/curb'
9
+ require 'api_auth/request_drivers/rest_client'
10
+ require 'api_auth/request_drivers/action_controller'
11
+
12
+ require 'api_auth/headers'
13
+ require 'api_auth/base'
14
+ require 'api_auth/railtie'
@@ -0,0 +1,81 @@
1
+ # api-auth is Ruby gem designed to be used both in your client and server
2
+ # HTTP-based applications. It implements the same authentication methods (HMAC)
3
+ # used by Amazon Web Services.
4
+
5
+ # The gem will sign your requests on the client side and authenticate that
6
+ # signature on the server side. If your server resources are implemented as a
7
+ # Rails ActiveResource, it will integrate with that. It will even generate the
8
+ # secret keys necessary for your clients to sign their requests.
9
+ module ApiAuth
10
+
11
+ class << self
12
+
13
+ include Helpers
14
+
15
+ # Signs an HTTP request using the client's access id and secret key.
16
+ # Returns the HTTP request object with the modified headers.
17
+ #
18
+ # request: The request can be a Net::HTTP, ActionController::Request,
19
+ # Curb (Curl::Easy) or a RestClient object.
20
+ #
21
+ # access_id: The public unique identifier for the client
22
+ #
23
+ # secret_key: assigned secret key that is known to both parties
24
+ def sign!(request, access_id, secret_key)
25
+ headers = Headers.new(request)
26
+ headers.sign_header auth_header(request, access_id, secret_key)
27
+ end
28
+
29
+ # Determines if the request is authentic given the request and the client's
30
+ # secret key. Returns true if the request is authentic and false otherwise.
31
+ def authentic?(request, secret_key)
32
+ return false if secret_key.nil?
33
+
34
+ headers = Headers.new(request)
35
+ if match_data = parse_auth_header(headers.authorization_header)
36
+ hmac = match_data[2]
37
+ return hmac == hmac_signature(request, secret_key)
38
+ end
39
+
40
+ false
41
+ end
42
+
43
+ # Returns the access id from the request's authorization header
44
+ def access_id(request)
45
+ headers = Headers.new(request)
46
+ if match_data = parse_auth_header(headers.authorization_header)
47
+ return match_data[1]
48
+ end
49
+
50
+ nil
51
+ end
52
+
53
+ # Generates a Base64 encoded, randomized secret key
54
+ #
55
+ # Store this key along with the access key that will be used for
56
+ # authenticating the client
57
+ def generate_secret_key
58
+ random_bytes = OpenSSL::Random.random_bytes(512)
59
+ b64_encode(Digest::SHA2.new(512).digest(random_bytes))
60
+ end
61
+
62
+ private
63
+
64
+ def hmac_signature(request, secret_key)
65
+ headers = Headers.new(request)
66
+ canonical_string = headers.canonical_string
67
+ digest = OpenSSL::Digest::Digest.new('sha1')
68
+ b64_encode(OpenSSL::HMAC.digest(digest, secret_key, canonical_string))
69
+ end
70
+
71
+ def auth_header(request, access_id, secret_key)
72
+ "APIAuth #{access_id}:#{hmac_signature(request, secret_key)}"
73
+ end
74
+
75
+ def parse_auth_header(auth_header)
76
+ Regexp.new("APIAuth ([^:]+):(.+)$").match(auth_header)
77
+ end
78
+
79
+ end # class methods
80
+
81
+ end # ApiAuth
@@ -0,0 +1,9 @@
1
+ module ApiAuth
2
+
3
+ # :nodoc:
4
+ class ApiAuthError < StandardError; end
5
+
6
+ # Raised when the HTTP request object passed is not supported
7
+ class UnknownHTTPRequest < ApiAuthError; end
8
+
9
+ end
@@ -0,0 +1,53 @@
1
+ module ApiAuth
2
+
3
+ # Builds the canonical string given a request object.
4
+ class Headers
5
+
6
+ include RequestDrivers
7
+
8
+ def initialize(request)
9
+ @original_request = request
10
+
11
+ case request.class.to_s
12
+ when /Net::HTTP/
13
+ @request = NetHttpRequest.new(request)
14
+ when /RestClient/
15
+ @request = RestClientRequest.new(request)
16
+ when /Curl::Easy/
17
+ @request = CurbRequest.new(request)
18
+ when /ActionController::Request/
19
+ @request = ActionControllerRequest.new(request)
20
+ when /ActionController::TestRequest/
21
+ @request = ActionControllerRequest.new(request)
22
+ else
23
+ raise UnknownHTTPRequest, "#{request.class.to_s} is not yet supported."
24
+ end
25
+ true
26
+ end
27
+
28
+ # Returns the canonical string computed from the request's headers
29
+ def canonical_string
30
+ [ @request.content_type,
31
+ @request.content_md5,
32
+ @request.request_uri,
33
+ @request.timestamp
34
+ ].join(",")
35
+ end
36
+
37
+ # Returns the authorization header from the request's headers
38
+ def authorization_header
39
+ @request.authorization_header
40
+ end
41
+
42
+ # Sets the request's authorization header with the passed in value.
43
+ # The header should be the ApiAuth HMAC signature.
44
+ #
45
+ # This will return the original request object with the signed Authorization
46
+ # header already in place.
47
+ def sign_header(header)
48
+ @request.set_auth_header header
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,19 @@
1
+ module ApiAuth
2
+
3
+ module Helpers # :nodoc:
4
+
5
+ # Remove the ending new line character added by default
6
+ def b64_encode(string)
7
+ Base64.encode64(string).strip
8
+ end
9
+
10
+ # Capitalizes the keys of a hash
11
+ def capitalize_keys(hsh)
12
+ capitalized_hash = {}
13
+ hsh.each_pair {|k,v| capitalized_hash[k.to_s.upcase] = v }
14
+ capitalized_hash
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,120 @@
1
+ module ApiAuth
2
+
3
+ # Integration with Rails
4
+ #
5
+ class Rails # :nodoc:
6
+
7
+ module ControllerMethods # :nodoc:
8
+
9
+ module InstanceMethods # :nodoc:
10
+
11
+ def get_api_access_id_from_request
12
+ ApiAuth.access_id(request)
13
+ end
14
+
15
+ def api_authenticated?(secret_key)
16
+ ApiAuth.authentic?(request, secret_key)
17
+ end
18
+
19
+ end
20
+
21
+ unless defined?(ActionController)
22
+ begin
23
+ require 'rubygems'
24
+ gem 'actionpack'
25
+ gem 'activesupport'
26
+ require 'action_controller'
27
+ require 'active_support'
28
+ rescue
29
+ nil
30
+ end
31
+ end
32
+
33
+ if defined?(ActionController::Base)
34
+ ActionController::Base.send(:include, ControllerMethods::InstanceMethods)
35
+ end
36
+
37
+ end # ControllerMethods
38
+
39
+ module ActiveResourceExtension # :nodoc:
40
+
41
+ module ActiveResourceApiAuth # :nodoc:
42
+
43
+ def self.included(base)
44
+ base.extend(ClassMethods)
45
+
46
+ base.class_inheritable_accessor :hmac_access_id
47
+ base.class_inheritable_accessor :hmac_secret_key
48
+ base.class_inheritable_accessor :use_hmac
49
+ end
50
+
51
+ module ClassMethods
52
+
53
+ def with_api_auth(access_id, secret_key)
54
+ self.hmac_access_id = access_id
55
+ self.hmac_secret_key = secret_key
56
+ self.use_hmac = true
57
+
58
+ class << self
59
+ alias_method_chain :connection, :auth
60
+ end
61
+ end
62
+
63
+ def connection_with_auth(refresh = false)
64
+ c = connection_without_auth(refresh)
65
+ c.hmac_access_id = self.hmac_access_id
66
+ c.hmac_secret_key = self.hmac_secret_key
67
+ c.use_hmac = self.use_hmac
68
+ c
69
+ end
70
+
71
+ end # class methods
72
+
73
+ module InstanceMethods
74
+ end
75
+
76
+ end # BaseApiAuth
77
+
78
+ module Connection
79
+
80
+ def self.included(base)
81
+ base.send :alias_method_chain, :request, :auth
82
+ base.class_eval do
83
+ attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac
84
+ end
85
+ end
86
+
87
+ def request_with_auth(method, path, *arguments)
88
+ if use_hmac && hmac_access_id && hmac_secret_key
89
+ h = arguments.last
90
+ tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
91
+ ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key)
92
+ arguments.last['DATE'] = tmp['DATE']
93
+ arguments.last['Authorization'] = tmp['Authorization']
94
+ end
95
+
96
+ request_without_auth(method, path, *arguments)
97
+ end
98
+
99
+ end # Connection
100
+
101
+ unless defined?(ActiveResource)
102
+ begin
103
+ require 'rubygems'
104
+ gem 'activeresource'
105
+ require 'active_resource'
106
+ rescue
107
+ nil
108
+ end
109
+ end
110
+
111
+ if defined?(ActiveResource)
112
+ ActiveResource::Base.send(:include, ActiveResourceApiAuth)
113
+ ActiveResource::Connection.send(:include, Connection)
114
+ end
115
+
116
+ end # ActiveResourceExtension
117
+
118
+ end # Rails
119
+
120
+ end # ApiAuth
@@ -0,0 +1,62 @@
1
+ module ApiAuth
2
+
3
+ module RequestDrivers # :nodoc:
4
+
5
+ class ActionControllerRequest # :nodoc:
6
+
7
+ include ApiAuth::Helpers
8
+
9
+ def initialize(request)
10
+ @request = request
11
+ @headers = fetch_headers
12
+ true
13
+ end
14
+
15
+ def set_auth_header(header)
16
+ @request.env["Authorization"] = header
17
+ @headers = fetch_headers
18
+ @request
19
+ end
20
+
21
+ def fetch_headers
22
+ capitalize_keys @request.env
23
+ end
24
+
25
+ def content_type
26
+ value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
27
+ value.nil? ? "" : value
28
+ end
29
+
30
+ def content_md5
31
+ value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
32
+ value.nil? ? "" : value
33
+ end
34
+
35
+ def request_uri
36
+ @request.path
37
+ end
38
+
39
+ def timestamp
40
+ value = find_header(%w(DATE HTTP_DATE))
41
+ if value.nil?
42
+ value = Time.now.utc.httpdate
43
+ @request.env['DATE'] = value
44
+ end
45
+ value
46
+ end
47
+
48
+ def authorization_header
49
+ find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
50
+ end
51
+
52
+ private
53
+
54
+ def find_header(keys)
55
+ keys.map {|key| @headers[key] }.compact.first
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,62 @@
1
+ module ApiAuth
2
+
3
+ module RequestDrivers # :nodoc:
4
+
5
+ class CurbRequest # :nodoc:
6
+
7
+ include ApiAuth::Helpers
8
+
9
+ def initialize(request)
10
+ @request = request
11
+ @headers = fetch_headers
12
+ true
13
+ end
14
+
15
+ def set_auth_header(header)
16
+ @request.headers.merge!({ "Authorization" => header })
17
+ @headers = fetch_headers
18
+ @request
19
+ end
20
+
21
+ def fetch_headers
22
+ capitalize_keys @request.headers
23
+ end
24
+
25
+ def content_type
26
+ value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
27
+ value.nil? ? "" : value
28
+ end
29
+
30
+ def content_md5
31
+ value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
32
+ value.nil? ? "" : value
33
+ end
34
+
35
+ def request_uri
36
+ @request.url
37
+ end
38
+
39
+ def timestamp
40
+ value = find_header(%w(DATE HTTP_DATE))
41
+ if value.nil?
42
+ value = Time.now.utc.httpdate
43
+ @request.headers.merge!({ "DATE" => value })
44
+ end
45
+ value
46
+ end
47
+
48
+ def authorization_header
49
+ find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
50
+ end
51
+
52
+ private
53
+
54
+ def find_header(keys)
55
+ keys.map {|key| @headers[key] }.compact.first
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,60 @@
1
+ module ApiAuth
2
+
3
+ module RequestDrivers # :nodoc:
4
+
5
+ class NetHttpRequest # :nodoc:
6
+
7
+ def initialize(request)
8
+ @request = request
9
+ @headers = fetch_headers
10
+ true
11
+ end
12
+
13
+ def set_auth_header(header)
14
+ @request["Authorization"] = header
15
+ @headers = fetch_headers
16
+ @request
17
+ end
18
+
19
+ def fetch_headers
20
+ @request
21
+ end
22
+
23
+ def content_type
24
+ value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
25
+ value.nil? ? "" : value
26
+ end
27
+
28
+ def content_md5
29
+ value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
30
+ value.nil? ? "" : value
31
+ end
32
+
33
+ def request_uri
34
+ @request.path
35
+ end
36
+
37
+ def timestamp
38
+ value = find_header(%w(DATE HTTP_DATE))
39
+ if value.nil?
40
+ value = Time.now.utc.httpdate
41
+ @request["DATE"] = value
42
+ end
43
+ value
44
+ end
45
+
46
+ def authorization_header
47
+ find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
48
+ end
49
+
50
+ private
51
+
52
+ def find_header(keys)
53
+ keys.map {|key| @headers[key] }.compact.first
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,62 @@
1
+ module ApiAuth
2
+
3
+ module RequestDrivers # :nodoc:
4
+
5
+ class RestClientRequest # :nodoc:
6
+
7
+ include ApiAuth::Helpers
8
+
9
+ def initialize(request)
10
+ @request = request
11
+ @headers = fetch_headers
12
+ true
13
+ end
14
+
15
+ def set_auth_header(header)
16
+ @request.headers.merge!({ "Authorization" => header })
17
+ @headers = fetch_headers
18
+ @request
19
+ end
20
+
21
+ def fetch_headers
22
+ capitalize_keys @request.headers
23
+ end
24
+
25
+ def content_type
26
+ value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
27
+ value.nil? ? "" : value
28
+ end
29
+
30
+ def content_md5
31
+ value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
32
+ value.nil? ? "" : value
33
+ end
34
+
35
+ def request_uri
36
+ @request.url
37
+ end
38
+
39
+ def timestamp
40
+ value = find_header(%w(DATE HTTP_DATE))
41
+ if value.nil?
42
+ value = Time.now.utc.httpdate
43
+ @request.headers.merge!({ "DATE" => value })
44
+ end
45
+ value
46
+ end
47
+
48
+ def authorization_header
49
+ find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
50
+ end
51
+
52
+ private
53
+
54
+ def find_header(keys)
55
+ keys.map {|key| @headers[key] }.compact.first
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -1,7 +1,7 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  require 'rspec'
4
- require 'api-auth'
4
+ require 'api_auth'
5
5
  require 'amatch'
6
6
  require 'rest_client'
7
7
  require 'curb'
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-auth
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
5
4
  prerelease:
6
- segments:
7
- - 0
8
- - 9
9
- - 0
10
- version: 0.9.0
5
+ version: 0.9.1
11
6
  platform: ruby
12
7
  authors:
13
8
  - Mauricio Gomes
@@ -15,137 +10,97 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-01-30 00:00:00 -05:00
13
+ date: 2011-03-12 00:00:00 -05:00
19
14
  default_executable:
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
22
- type: :development
23
- version_requirements: &id001 !ruby/object:Gem::Requirement
17
+ name: rspec
18
+ requirement: &id001 !ruby/object:Gem::Requirement
24
19
  none: false
25
20
  requirements:
26
21
  - - ~>
27
22
  - !ruby/object:Gem::Version
28
- hash: 31
29
- segments:
30
- - 2
31
- - 4
32
- - 0
33
23
  version: 2.4.0
34
- requirement: *id001
24
+ type: :development
35
25
  prerelease: false
36
- name: rspec
26
+ version_requirements: *id001
37
27
  - !ruby/object:Gem::Dependency
38
- type: :development
39
- version_requirements: &id002 !ruby/object:Gem::Requirement
28
+ name: bundler
29
+ requirement: &id002 !ruby/object:Gem::Requirement
40
30
  none: false
41
31
  requirements:
42
32
  - - ~>
43
33
  - !ruby/object:Gem::Version
44
- hash: 23
45
- segments:
46
- - 1
47
- - 0
48
- - 0
49
34
  version: 1.0.0
50
- requirement: *id002
35
+ type: :development
51
36
  prerelease: false
52
- name: bundler
37
+ version_requirements: *id002
53
38
  - !ruby/object:Gem::Dependency
54
- type: :development
55
- version_requirements: &id003 !ruby/object:Gem::Requirement
39
+ name: jeweler
40
+ requirement: &id003 !ruby/object:Gem::Requirement
56
41
  none: false
57
42
  requirements:
58
43
  - - ~>
59
44
  - !ruby/object:Gem::Version
60
- hash: 7
61
- segments:
62
- - 1
63
- - 5
64
- - 2
65
45
  version: 1.5.2
66
- requirement: *id003
46
+ type: :development
67
47
  prerelease: false
68
- name: jeweler
48
+ version_requirements: *id003
69
49
  - !ruby/object:Gem::Dependency
70
- type: :development
71
- version_requirements: &id004 !ruby/object:Gem::Requirement
50
+ name: amatch
51
+ requirement: &id004 !ruby/object:Gem::Requirement
72
52
  none: false
73
53
  requirements:
74
54
  - - ~>
75
55
  - !ruby/object:Gem::Version
76
- hash: 29
77
- segments:
78
- - 0
79
- - 2
80
- - 5
81
56
  version: 0.2.5
82
- requirement: *id004
57
+ type: :development
83
58
  prerelease: false
84
- name: amatch
59
+ version_requirements: *id004
85
60
  - !ruby/object:Gem::Dependency
86
- type: :development
87
- version_requirements: &id005 !ruby/object:Gem::Requirement
61
+ name: curb
62
+ requirement: &id005 !ruby/object:Gem::Requirement
88
63
  none: false
89
64
  requirements:
90
65
  - - ~>
91
66
  - !ruby/object:Gem::Version
92
- hash: 13
93
- segments:
94
- - 0
95
- - 7
96
- - 7
97
67
  version: 0.7.7
98
- requirement: *id005
68
+ type: :development
99
69
  prerelease: false
100
- name: curb
70
+ version_requirements: *id005
101
71
  - !ruby/object:Gem::Dependency
102
- type: :development
103
- version_requirements: &id006 !ruby/object:Gem::Requirement
72
+ name: rest-client
73
+ requirement: &id006 !ruby/object:Gem::Requirement
104
74
  none: false
105
75
  requirements:
106
76
  - - ~>
107
77
  - !ruby/object:Gem::Version
108
- hash: 15
109
- segments:
110
- - 1
111
- - 6
112
- - 0
113
78
  version: 1.6.0
114
- requirement: *id006
79
+ type: :development
115
80
  prerelease: false
116
- name: rest-client
81
+ version_requirements: *id006
117
82
  - !ruby/object:Gem::Dependency
118
- type: :development
119
- version_requirements: &id007 !ruby/object:Gem::Requirement
83
+ name: actionpack
84
+ requirement: &id007 !ruby/object:Gem::Requirement
120
85
  none: false
121
86
  requirements:
122
87
  - - ~>
123
88
  - !ruby/object:Gem::Version
124
- hash: 7
125
- segments:
126
- - 2
127
- - 3
128
- - 2
129
89
  version: 2.3.2
130
- requirement: *id007
90
+ type: :development
131
91
  prerelease: false
132
- name: actionpack
92
+ version_requirements: *id007
133
93
  - !ruby/object:Gem::Dependency
134
- type: :development
135
- version_requirements: &id008 !ruby/object:Gem::Requirement
94
+ name: activeresource
95
+ requirement: &id008 !ruby/object:Gem::Requirement
136
96
  none: false
137
97
  requirements:
138
98
  - - ~>
139
99
  - !ruby/object:Gem::Version
140
- hash: 7
141
- segments:
142
- - 2
143
- - 3
144
- - 2
145
100
  version: 2.3.2
146
- requirement: *id008
101
+ type: :development
147
102
  prerelease: false
148
- name: activeresource
103
+ version_requirements: *id008
149
104
  description: Full HMAC auth implementation for use in your gems and Rails apps.
150
105
  email: mgomes@geminisbs.com
151
106
  executables: []
@@ -159,17 +114,30 @@ files:
159
114
  - .document
160
115
  - .rspec
161
116
  - Gemfile
117
+ - Gemfile.lock
162
118
  - LICENSE.txt
119
+ - README.md
163
120
  - Rakefile
121
+ - VERSION
122
+ - api_auth.gemspec
164
123
  - lib/api-auth.rb
165
- - spec/api-auth_spec.rb
166
- - spec/spec_helper.rb
167
- - README.md
124
+ - lib/api_auth.rb
125
+ - lib/api_auth/base.rb
126
+ - lib/api_auth/errors.rb
127
+ - lib/api_auth/headers.rb
128
+ - lib/api_auth/helpers.rb
129
+ - lib/api_auth/railtie.rb
130
+ - lib/api_auth/request_drivers/action_controller.rb
131
+ - lib/api_auth/request_drivers/curb.rb
132
+ - lib/api_auth/request_drivers/net_http.rb
133
+ - lib/api_auth/request_drivers/rest_client.rb
134
+ - spec/api_auth_spec.rb
168
135
  - spec/headers_spec.rb
169
136
  - spec/helpers_spec.rb
170
137
  - spec/railtie_spec.rb
138
+ - spec/spec_helper.rb
171
139
  has_rdoc: true
172
- homepage: http://github.com/geminisbs/api-auth
140
+ homepage: http://github.com/mgomes/api_auth
173
141
  licenses:
174
142
  - MIT
175
143
  post_install_message:
@@ -182,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
182
150
  requirements:
183
151
  - - ">="
184
152
  - !ruby/object:Gem::Version
185
- hash: 3
153
+ hash: -3238234233330839898
186
154
  segments:
187
155
  - 0
188
156
  version: "0"
@@ -191,19 +159,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
159
  requirements:
192
160
  - - ">="
193
161
  - !ruby/object:Gem::Version
194
- hash: 3
195
- segments:
196
- - 0
197
162
  version: "0"
198
163
  requirements: []
199
164
 
200
165
  rubyforge_project:
201
- rubygems_version: 1.4.1
166
+ rubygems_version: 1.5.2
202
167
  signing_key:
203
168
  specification_version: 3
204
169
  summary: Simple HMAC authentication for your APIs
205
170
  test_files:
206
- - spec/api-auth_spec.rb
171
+ - spec/api_auth_spec.rb
207
172
  - spec/headers_spec.rb
208
173
  - spec/helpers_spec.rb
209
174
  - spec/railtie_spec.rb