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 +4 -0
- data/README.md +2 -0
- data/lib/generators/restful_api_authentication/install/templates/restful_api_authentication.yml +3 -2
- data/lib/restful_api_authentication/checker.rb +27 -6
- data/lib/restful_api_authentication/railtie.rb +10 -9
- data/lib/restful_api_authentication/version.rb +1 -1
- data/lib/restful_api_authentication.rb +10 -2
- metadata +8 -8
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+
|
data/lib/generators/restful_api_authentication/install/templates/restful_api_authentication.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
defaults: &DEFAULTS
|
2
|
-
request_window: 10
|
3
|
-
|
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?
|
40
|
-
if
|
41
|
-
|
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
|
-
|
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
|
30
|
-
RestfulApiAuthentication::Checker.header_timestamp
|
31
|
-
RestfulApiAuthentication::Checker.header_signature
|
32
|
-
RestfulApiAuthentication::Checker.header_api_key
|
33
|
-
|
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
|
@@ -39,7 +39,11 @@ module RestfulApiAuthentication
|
|
39
39
|
if checker.authorized?
|
40
40
|
return true
|
41
41
|
else
|
42
|
-
|
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
|
-
|
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.
|
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-
|
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: &
|
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: *
|
24
|
+
version_requirements: *70141551581760
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: uuid
|
27
|
-
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: *
|
35
|
+
version_requirements: *70141551581260
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: chronic
|
38
|
-
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: *
|
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:
|