hmac-auth-rails 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 16b4a6bbc4ad9534420cc8ad5832034243d3270f
4
+ data.tar.gz: 26a5452d6f16b798cbceb6a5c9da2af853887eff
5
+ SHA512:
6
+ metadata.gz: 0828664d24a83a56a423e7d02c0fdf82ab07041f0c53a8787ad52674fedc674e2944cab1bb38cb00bd9d34a06f096ef37c8bdb36eb62d89793560759c8f0239b
7
+ data.tar.gz: 34225f01299554f461b6d02f8f50db28e2af12fd28ff8d7bce537dc7cec2ef917e5c9b5f82085de2730feacd2542f4682777342f9f14cba4a9df1d9a51ab1d84
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Justin Pye
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,216 @@
1
+ # hmac-auth-rails
2
+
3
+ #### Disclaimer: Although this is covered in the MIT license agreement, please be aware that in no way will the authors be responsible for any security issues or loss of income that may arise from using this code. Use this code at your own risk.
4
+
5
+ ## Overview
6
+
7
+ This application integrates with Rails and provides in-built SHA1 HMAC authentication. It was originally built to be used with [angular-hmac-auth](https://github.com/todopagos/angular-hmac-auth) an open-source Angular module. Currently it only supports SHA1 encryption. If you require better encryption methods please contribute.
8
+
9
+ ## Installation
10
+
11
+ ### Install the Gemfile
12
+
13
+ Add the following line to your Rails Gemfile:
14
+
15
+ `gem 'hmac-auth-rails'`
16
+
17
+ ### Make your authentication model authenticatable
18
+
19
+ Add the line below to your applications model that handles the authentication:
20
+
21
+ ```
22
+ class User < ActiveRecord::Base
23
+
24
+ hmac_authenticatable
25
+ ```
26
+
27
+ ### Built-in authentication fields
28
+
29
+ To use built-in fields you will need to ensure that your authentication model has the `auth_token` and `secret_key` string fields defined:
30
+
31
+ ```
32
+ class User < ActiveRecord::Base
33
+
34
+ hmac_authenticatable
35
+
36
+ field :auth_token, type: String
37
+ field :secret_key, type: String
38
+ ```
39
+
40
+ ### Custom authentication fields
41
+
42
+ If you do not wish to use the built-in fields you can specifiy your own custom fields in the model:
43
+
44
+ ```
45
+ class User < ActiveRecord::Base
46
+
47
+ hmac_authenticatable
48
+
49
+ self.auth_token_field = :custom_auth_token
50
+ self.secret_key_field = :custom_secret_key
51
+
52
+ field :custom_auth_token, type: String
53
+ field : custom_secret_key, type: String
54
+ ```
55
+
56
+ ### Auto-generating auth tokens and secret keys
57
+
58
+ The following snippet can help you in setting up your model to auto-generate the `auth_token` and `secret_key` when a new record is initialised.
59
+
60
+ ```
61
+ after_initialize :generate_key, :generate_token
62
+
63
+ protected
64
+ def generate_token
65
+ self.auth_token ||= loop do
66
+ random_token = SecureRandom.hex(32)
67
+ break random_token unless User.exists?(auth_token: random_token)
68
+ end
69
+ end
70
+
71
+ def generate_key
72
+ self.secret_key ||= SecureRandom.base64(64)
73
+ end
74
+ ```
75
+
76
+ ### When using devise
77
+
78
+ To ensure that you validate HMAC authentication before the `:authenticate_user!` method is called. You will want the following line.
79
+
80
+ `prepend_before_filter :hmac_auth`
81
+
82
+ To exclude certain actions from being `hmac_authenticatable` you could use the following exclude parameter.
83
+
84
+ `prepend_before_filter :hmac_auth, :except => :my_action`
85
+
86
+ ### Applying HMAC authentication globaly
87
+
88
+ A good way to apply HMAC authentication globaly is to add `:hmac_auth` to your `ApplicationController` and inherit the controller for all other sub-controllers.
89
+
90
+ ```
91
+ module Api::V1
92
+ class ApiController < ApplicationController
93
+ prepend_before_filter :hmac_auth
94
+ end
95
+ end
96
+ ```
97
+
98
+ Your sub-controller would look similar to the following:
99
+
100
+ ```
101
+ module Api::V1
102
+ class UsersController < ApiController
103
+ end
104
+ end
105
+ ```
106
+
107
+ ## Testing with Rspec
108
+
109
+ Set into the `spec/dummy` folder and run the following:
110
+
111
+ ```
112
+ bundle exec rspec
113
+ ```
114
+
115
+ ## Plays nice with
116
+
117
+ ### todopagos/angular-hmac-auth
118
+
119
+ [https://github.com/todopagos/angular-hmac-auth](https://github.com/todopagos/angular-hmac-auth)
120
+
121
+ ### plataformatec/devise
122
+
123
+ [https://github.com/plataformatec/devise](https://github.com/plataformatec/devise)
124
+
125
+ ## Putting all the "plays nice with" together
126
+
127
+ Create an API Application Controller that excludes the `auth` action:
128
+
129
+ ```
130
+ module Api::V1
131
+ class ApiController < ApplicationController
132
+ prepend_before_filter :hmac_auth, :except => :auth
133
+ end
134
+ end
135
+ ```
136
+
137
+ Setup the `auth` action to set the user as the `current_user`:
138
+
139
+ ```
140
+ def auth
141
+ @user = current_user
142
+ end
143
+ ```
144
+
145
+ The `auth` jbuilder view will look like the following:
146
+
147
+ ```
148
+ json.auth do
149
+ json.auth_token @user[@user.auth_token_field]
150
+ json.secret_key @user[@user.secret_key_field]
151
+ end
152
+ ```
153
+
154
+ And when rendered:
155
+
156
+ ```
157
+ {
158
+ "auth": {
159
+ "auth_token": "39e75f277f2edb7d9f547a8b3e21fa4c1c5fd5e213909e7c93a87539e12e60ea",
160
+ "secret_key": "wrlM6KWL0SgyCM0sBbhXfXdwKxqDxC3Df3/wmOwiw2HZOIMvi4L1m51/fhowUz5Ys8BL2vr2GezS4lK4deXGJQ=="
161
+ }
162
+ }
163
+ ```
164
+
165
+ The following is an example of how you load the `auth` details via the `angular-hmac-auth` module and intercept all `$http` calls in order to add the HMAC authencation headers:
166
+
167
+ ```
168
+ var hmacAuthApp = angular.module("hmac-auth-demo",['hmacAuthInterceptor'])
169
+
170
+ .constant('REST_PATH', "/api/v1")
171
+
172
+ .provider('configService', ['REST_PATH',function(REST_PATH) {
173
+ var loadConfig = ['$http','$q', function($http,$q) {
174
+ var deferred = $q.defer();
175
+ $http.get(REST_PATH + '/users/auth').then(function(response) {
176
+ deferred.resolve(response["data"]["auth"]);
177
+ });
178
+ return deferred.promise;
179
+ }];
180
+ this.$get = loadConfig;
181
+ }])
182
+
183
+ .config(['$httpProvider', function($httpProvider) {
184
+ $httpProvider.interceptors.push('hmacInterceptor');
185
+ }])
186
+
187
+ .run(['hmacInterceptor','REST_PATH', function(hmacInterceptor,REST_PATH){
188
+ hmacInterceptor.whitelist = REST_PATH + '/usrs/auth';
189
+ }])
190
+
191
+ .controller('DemoController', [ '$scope','$http','configService','hmacInterceptor','REST_PATH', function($scope,$http, configService, hmacInterceptor, REST_PATH){
192
+ var demo = $scope;
193
+
194
+ configService.then(function(config){
195
+ hmacInterceptor.accessId = config["auth_token"];
196
+ hmacInterceptor.secretKey = config["secret_key"];
197
+ $http.get(REST_PATH + '/users').then(function(response){
198
+ demo.users = response.data.users;
199
+ });
200
+ });
201
+ }]);
202
+ ```
203
+
204
+ An example of the headers that gets appended to the Angular HTTP requests:
205
+
206
+ ```
207
+ X_HMAC_AUTHORIZATION:APIAuth 39e75f277f2edb7d9f547a8b3e21fa4c1c5fd5e213909e7c93a87539e12e60ea:l+f5GfID1ABZm6W7zAaf+5lb9N4=
208
+ X_HMAC_CONTENT_MD5:1B2M2Y8AsgTpgAmY7PhCfg==
209
+ X_HMAC_CONTENT_TYPE:
210
+ X_HMAC_DATE:Sun, 24 Jan 2016 09:00:06 GMT
211
+ ```
212
+ The `spec/dummy` application actually has working version of the above and can be run by setting into the folder and calling `rails s`
213
+
214
+ # More information
215
+
216
+ For any more information please contact Bernie Lomax. Bernie!, Bernie!, Bernie!
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AngularHmacAuthRails'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
@@ -0,0 +1 @@
1
+ require 'hmac_auth_rails'
@@ -0,0 +1,105 @@
1
+ require 'active_record'
2
+
3
+ module HmacAuthRails
4
+
5
+ class HmacRailtie < Rails::Railtie
6
+ initializer "hmacauthrails.configure_rails_initialization" do |app|
7
+ Mongoid::Document.send :include, HmacAuthenticatable if defined? Mongoid::Document
8
+ ActiveRecord::Base.send :include, HmacAuthenticatable if defined? ActiveRecord::Base
9
+ ActionController::Base.send :include, HmacController
10
+ ActionController::Base.helper_method :hmac_auth
11
+ end
12
+ end
13
+
14
+ module HmacAuthenticatable
15
+
16
+ extend ActiveSupport::Concern
17
+
18
+ included do; end
19
+
20
+ module ClassMethods
21
+ def hmac_authenticatable(options = {})
22
+ cattr_accessor :secret_key_field
23
+ cattr_accessor :auth_token_field
24
+ self.secret_key_field = (options[:secret_key_field] || :secret_key).to_s
25
+ self.auth_token_field = (options[:auth_token_field] || :auth_token).to_s
26
+ include HmacAuthRails::HmacAuthenticatable::LocalInstanceMethods
27
+ end
28
+ end
29
+
30
+ module LocalInstanceMethods; end
31
+
32
+ end
33
+
34
+ module HmacController
35
+
36
+ def hmac_auth model="User"
37
+ @my_user
38
+ begin
39
+ raise 'Missing X_HMAC_AUTHORIZATION header' unless header_exists? :HTTP_X_HMAC_AUTHORIZATION
40
+ raise 'Missing header HTTP_X_HMAC_CONTENT_MD5 header' unless header_exists? :HTTP_X_HMAC_CONTENT_MD5
41
+ raise 'Missing header HTTP_X_HMAC_CONTENT_TYPE header' unless header_exists? :HTTP_X_HMAC_CONTENT_TYPE
42
+ raise 'Missing header HTTP_X_HMAC_DATE header' unless header_exists? :HTTP_X_HMAC_DATE
43
+ raise 'Could not determine Devise model name' unless model = Object.const_get(model)
44
+ credentials = load_header
45
+ raise "Invalid #{model.auth_token_field}" unless user = model.where("#{model.auth_token_field}" => credentials[:auth_token] ).first
46
+ raise "Invalid #{model.secret_key_field}" unless secret_key = user[model.secret_key_field]
47
+ @my_user = user
48
+ if credentials[:signature] == HmacAuthRails::HmacController.encrypt(secret_key, canonical_string)
49
+ sign_in(user, store: false)
50
+ else
51
+ raise 'Authentication failed.'
52
+ end
53
+ rescue => e
54
+ Rails.logger.error e.to_s
55
+ head :unauthorized
56
+ rescue => e
57
+ Rails.logger.error e
58
+ head :unauthorized
59
+ end
60
+ end
61
+
62
+ def self.encrypt(secret_key,string)
63
+ digest = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), secret_key, string)
64
+ if Base64.respond_to?(:strict_encode64)
65
+ Base64.strict_encode64(digest)
66
+ else
67
+ Base64.encode64(digest).gsub(/\n/, '')
68
+ end
69
+ end
70
+
71
+ private
72
+ def header_exists? header
73
+ if request.headers.env.has_key? header.to_s
74
+ true
75
+ else
76
+ false
77
+ end
78
+ end
79
+
80
+ def canonical_string
81
+ [
82
+ ( request.headers.env["HTTP_X_HMAC_CONTENT_TYPE"] != "null" ? request.headers.env["HTTP_X_HMAC_CONTENT_TYPE"] : "" ),
83
+ ( request.headers.env["HTTP_X_HMAC_CONTENT_MD5"] != "null" ? request.headers.env["HTTP_X_HMAC_CONTENT_MD5"] : "" ),
84
+ request.headers.env["PATH_INFO"],
85
+ request.headers.env["HTTP_X_HMAC_DATE"]
86
+ ].join(",")
87
+ end
88
+
89
+ def load_header
90
+ data = request.headers.env["HTTP_X_HMAC_AUTHORIZATION"].gsub(/APIAuth /, '').split(':')
91
+ raise 'Invalid HMAC auth header' if data.size != 2
92
+ raise 'Invalid token inside HMAC auth header' if data.first.empty? or data.first.nil?
93
+ raise 'Invalid secret inside HMAC auth header' if data.last.empty? or data.last.nil?
94
+ return {
95
+ :auth_token => data.first,
96
+ :signature => data.last
97
+ }
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+
104
+
105
+
@@ -0,0 +1,3 @@
1
+ module HmacAuthRails
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :hmac_auth_rails do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hmac-auth-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Justin Pye
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: devise
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jbuilder
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: factory_girl_rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '4.0'
97
+ description: Provides HMAC authentication to your Rails controllers
98
+ email:
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - MIT-LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - lib/hmac-auth-rails.rb
107
+ - lib/hmac_auth_rails.rb
108
+ - lib/hmac_auth_rails/version.rb
109
+ - lib/tasks/angular_hmac_auth_rails_tasks.rake
110
+ homepage: https://github.com/bernielomax/hmac-auth-rails
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.4.8
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Provides HMAC authentication to your Rails controllers
134
+ test_files: []