restful_api_authentication 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Change History / Release Notes
2
2
 
3
+ ## Version 0.2.0
4
+
5
+ * Added verbose error messaging; if this is enabled in the YML config file, then the response to an authentication failure will be more descriptive as to why the authentication failed.
6
+
3
7
  ## Version 0.1.2
4
8
 
5
9
  * Resolved Issue #2: UUID gem is not required and therefore throws an error when this gem is used.
data/README.md CHANGED
@@ -4,6 +4,8 @@ RestfulApiAuthentication is a gem which implements a standard api_key/secret aut
4
4
 
5
5
  With most RESTful Web API's, it is important to know which app is using your resources and that only the apps you allow access those resources. This gem allows you to easily add this layer of authentication to any Rails RESTful resource you want, and it even includes protection against various forms of attack.
6
6
 
7
+ Go here to read a more lengthy description of the problem this gem is attempting to solve: [Authentication of a Ruby on Rails RESTful Web API / Service](http://www.djkiger.com/?p=41)
8
+
7
9
  ## Requirements
8
10
 
9
11
  1. Rails 3.2.0+
@@ -1,6 +1,7 @@
1
1
  defaults: &DEFAULTS
2
- request_window: 10 # request window in minutes - between 5 and 10 is usually best; must be at least 2
3
- header_names: # names of HTTP headers that must be sent on all requests requiring authentication
2
+ request_window: 10 # request window in minutes - between 5 and 10 is usually best; must be at least 2
3
+ verbose_errors: false # if false, error response will always be "not authorized", otherwise it will be more descriptive of why authentication failed
4
+ header_names: # names of HTTP headers that must be sent on all requests requiring authentication
4
5
  timestamp: "x-timestamp"
5
6
  signature: "x-signature"
6
7
  api_key: "x-api-key"
@@ -24,24 +24,42 @@
24
24
  module RestfulApiAuthentication
25
25
  class Checker
26
26
  # Class attributes which are set when the Rails application is initialized: locally cached version of configuration settings stored in YML file.
27
- cattr_accessor :header_timestamp, :header_signature, :header_api_key, :time_window
28
- attr_accessor :http_headers, :request_uri
27
+ cattr_accessor :header_timestamp, :header_signature, :header_api_key, :time_window, :verbose_errors
28
+ attr_accessor :http_headers, :request_uri, :errors
29
29
 
30
30
  def initialize(http_headers, request_uri)
31
31
  @http_headers = http_headers
32
32
  @request_uri = request_uri
33
+ @errors = []
33
34
  end
34
35
 
35
36
  # Checks if the current request passes authorization
36
37
  def authorized?(options = {})
37
38
  raise "Configuration values not found. Please run rails g restful_api_authentication:install to generate a config file." if @@header_timestamp.nil? || @@header_signature.nil? || @@header_api_key.nil? || @@time_window.nil?
38
39
  return_val = false
39
- if headers_have_values? && in_time_window?
40
- if (options[:require_master] == true)
41
- return_val = true if test_hash == @http_headers[@@header_signature] && is_master?
40
+ if headers_have_values?
41
+ if in_time_window?
42
+ if test_hash == @http_headers[@@header_signature]
43
+ if options[:require_master] == true
44
+ if is_master?
45
+ return_val = true
46
+ else
47
+ @errors << "client does not have the required permissions"
48
+ end
49
+ else
50
+ return_val = true
51
+ end
52
+ else
53
+ @errors << "signature is invalid"
54
+ end
42
55
  else
43
- return_val = true if test_hash == @http_headers[@@header_signature]
56
+ @errors << "request is outside the required time window of #{@@time_window.to_s} minutes"
44
57
  end
58
+ else
59
+ @errors << "one or more required headers is missing"
60
+ end
61
+ if return_val == false && @errors.count == 0
62
+ @errors << "authentication failed"
45
63
  end
46
64
  return_val
47
65
  end
@@ -72,6 +90,9 @@ module RestfulApiAuthentication
72
90
  # generates the string that is hashed to produce the signature
73
91
  def str_to_hash
74
92
  client = RestClient.where(:api_key => @http_headers[@@header_api_key]).first
93
+ if client.nil?
94
+ @errors << "client is not registered"
95
+ end
75
96
  client.nil? ? "" : client.secret + @request_uri.gsub( /\?.*/, "" ) + @http_headers[@@header_timestamp]
76
97
  end
77
98
 
@@ -24,17 +24,18 @@
24
24
  module RestfulApiAuthentication
25
25
  class Railtie < Rails::Railtie
26
26
  initializer "restful_api_authentication_railtie.config_initializer" do
27
+ RestfulApiAuthentication::Checker.time_window = 4
28
+ RestfulApiAuthentication::Checker.header_timestamp = 'x-timestamp'
29
+ RestfulApiAuthentication::Checker.header_signature = 'x-signature'
30
+ RestfulApiAuthentication::Checker.header_api_key = 'x-api-key'
31
+ RestfulApiAuthentication::Checker.verbose_errors = false
27
32
  if File.exists? Rails.root.join('config', 'restful_api_authentication.yml')
28
33
  config_data = YAML::load_file(Rails.root.join('config', 'restful_api_authentication.yml'))[Rails.env]
29
- RestfulApiAuthentication::Checker.time_window = config_data['request_window']
30
- RestfulApiAuthentication::Checker.header_timestamp = config_data['header_names']['timestamp']
31
- RestfulApiAuthentication::Checker.header_signature = config_data['header_names']['signature']
32
- RestfulApiAuthentication::Checker.header_api_key = config_data['header_names']['api_key']
33
- else
34
- RestfulApiAuthentication::Checker.time_window = nil
35
- RestfulApiAuthentication::Checker.header_timestamp = nil
36
- RestfulApiAuthentication::Checker.header_signature = nil
37
- RestfulApiAuthentication::Checker.header_api_key = nil
34
+ RestfulApiAuthentication::Checker.time_window ||= config_data['request_window']
35
+ RestfulApiAuthentication::Checker.header_timestamp ||= config_data['header_names']['timestamp']
36
+ RestfulApiAuthentication::Checker.header_signature ||= config_data['header_names']['signature']
37
+ RestfulApiAuthentication::Checker.header_api_key ||= config_data['header_names']['api_key']
38
+ RestfulApiAuthentication::Checker.verbose_errors ||= config_data['verbose_errors']
38
39
  end
39
40
  end
40
41
  end
@@ -22,5 +22,5 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
24
  module RestfulApiAuthentication
25
- VERSION = "0.1.2"
25
+ VERSION = "0.2.0"
26
26
  end
@@ -39,7 +39,11 @@ module RestfulApiAuthentication
39
39
  if checker.authorized?
40
40
  return true
41
41
  else
42
- respond_with(["not authorized"], :status => 401, :location => nil)
42
+ if checker.verbose_errors
43
+ respond_with(checker.errors, :status => 401, :location => nil)
44
+ else
45
+ respond_with(["not authorized"], :status => 401, :location => nil)
46
+ end
43
47
  end
44
48
  end
45
49
 
@@ -53,7 +57,11 @@ module RestfulApiAuthentication
53
57
  if checker.authorized?({:require_master => true})
54
58
  return true
55
59
  else
56
- respond_with(["not authorized"], :status => 401, :location => nil)
60
+ if checker.verbose_errors
61
+ respond_with(checker.errors, :status => 401, :location => nil)
62
+ else
63
+ respond_with(["not authorized"], :status => 401, :location => nil)
64
+ end
57
65
  end
58
66
  end
59
67
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restful_api_authentication
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-04 00:00:00.000000000 Z
12
+ date: 2012-05-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70195976870460 !ruby/object:Gem::Requirement
16
+ requirement: &70141551581760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70195976870460
24
+ version_requirements: *70141551581760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: uuid
27
- requirement: &70195976869960 !ruby/object:Gem::Requirement
27
+ requirement: &70141551581260 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.3.5
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70195976869960
35
+ version_requirements: *70141551581260
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: chronic
38
- requirement: &70195976869480 !ruby/object:Gem::Requirement
38
+ requirement: &70141551580780 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 0.6.7
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70195976869480
46
+ version_requirements: *70141551580780
47
47
  description: A gem which implements a standard api_key / secret authentication system
48
48
  for your Ruby on Rails RESTful web services.
49
49
  email: