auther 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65a58c9e0dbe816215f33e5daa86064c83a06185
4
- data.tar.gz: 276515d8c4cf3b4fcc96e6dd548400f362270d03
3
+ metadata.gz: 18370adb7c20520b5fe1a95290e6d0ebc387e26f
4
+ data.tar.gz: 83be7320485a4b859bd51ba040145baad8bfd597
5
5
  SHA512:
6
- metadata.gz: f85b9b1dd51400d5a52aa18f006e9c06bc8a5f5c91e1757bda195c323e6df33e8b9709b6d3fbd0586a94466154b2e1be388960b9741ed765251b76262ace07ef
7
- data.tar.gz: 4e8e0a69cb00fa91133f3c074517643c9affa4c6970edcc65609ec6d4e48e9540ab2055ea208640f8c54f0bfb2c4c4f0616a3e86087c2eb8c3f037301fe47814
6
+ metadata.gz: c83a3d37bebb80fe575e2961b4ba54c775cf2f9af45275d8f135417620b0e767255b85233ec542caf16d22f031c8b7491235d13dd6deccba1a47a8b5018ee94a
7
+ data.tar.gz: 2a0ed3ede21308c3870e038a4bdad28a8a041fe5777114b3f115996a1371b95da7a549f437b2bab9e88a5c984c0d85a25593b8f6c605ca4db1f221cd01a67311
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1 @@
1
- �{k=��&53����Ђǃ��5�q^�<����}XyJ���#�F���:6��}��al���%i A��r�4�Kqs�
2
- �}��9s
1
+ +�MsVykGD�1�&UE�\�x5�N n���63ˋ �X�~\fTD���{PuWn%3w�dEߕm���Hk�i�*��55_1�jԧ�PD5r���3o �.y���3(�8���W?wKx������C��A
data.tar.gz.sig CHANGED
Binary file
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 [Red Alchemist](http://www.redalchemist.com).
1
+ Copyright (c) 2014 [Alchemists](http://www.alchemists.io).
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/auther.png)](http://badge.fury.io/rb/auther)
4
4
  [![Code Climate GPA](https://codeclimate.com/github/bkuhlmann/auther.png)](https://codeclimate.com/github/bkuhlmann/auther)
5
+ [![Code Climate Coverage](https://codeclimate.com/github/bkuhlmann/auther/coverage.png)](https://codeclimate.com/github/bkuhlmann/auther)
5
6
  [![Gemnasium Status](https://gemnasium.com/bkuhlmann/auther.png)](https://gemnasium.com/bkuhlmann/auther)
6
7
  [![Travis CI Status](https://secure.travis-ci.org/bkuhlmann/auther.png)](http://travis-ci.org/bkuhlmann/auther)
7
- [![Coverage Status](https://coveralls.io/repos/bkuhlmann/auther/badge.png)](https://coveralls.io/r/bkuhlmann/auther)
8
+ [![Gittip](http://img.shields.io/gittip/bkuhlmann.svg)](https://www.gittip.com/bkuhlmann)
8
9
 
9
10
  Provides simple, form-based authentication for apps that need security but don't want to deal with the clunky UI
10
11
  of HTTP Basic Authentication or something as heavyweight as [Devise](https://github.com/plataformatec/devise). It
@@ -22,9 +23,9 @@ making for a pleasent user experience.
22
23
  * Multiple account support with account specific blacklisted paths.
23
24
  * Auto-redirection to requested path (once credentials have been verified).
24
25
  * Log filtering for account credentials (login and password).
25
- * Customizable logger support.
26
26
  * Customizable view support.
27
27
  * Customizable controller support.
28
+ * Customizable logger support.
28
29
 
29
30
  # Requirements
30
31
 
@@ -38,7 +39,7 @@ making for a pleasent user experience.
38
39
 
39
40
  For a secure install, type the following from the command line (recommended):
40
41
 
41
- gem cert --add <(curl -Ls http://www.redalchemist.com/gem-public.pem)
42
+ gem cert --add <(curl -Ls http://www.alchemists.io/gem-public.pem)
42
43
  gem install auther --trust-policy MediumSecurity
43
44
 
44
45
  NOTE: A HighSecurity trust policy would be best but MediumSecurity enables signed gem verification while
@@ -52,79 +53,106 @@ Add the following to your Gemfile:
52
53
 
53
54
  gem "auther"
54
55
 
55
- Edit your routes.rb as follows:
56
+ Run the generator to configure and initialize your application:
56
57
 
57
- Rails.application.routes.draw do
58
- mount Auther::Engine => "/auther"
59
- get "/login", to: "auther/session#new"
60
- end
58
+ bin/rails generate auther:install
59
+
60
+ # Usage
61
+
62
+ Using the setup examples, from above, launch your Rails application and visit either of the following routes:
63
+
64
+ http://localhost:3000/login
65
+ http://localhost:3000/admin/example # Assumes this route exists. Will redirect to /login if not authorized.
66
+
67
+ Use the following credentials to login:
68
+
69
+ * Login: test@test.com
70
+ * Password: password
71
+
72
+ To encrypt/decrypt account credentials, launch a rails console and type the following:
61
73
 
62
- Add a config/initializers/auther.rb to your application with the following content:
74
+ # Best if more than 150 characters and gibberish to read. Must be the same as defined in auther settings.
75
+ cipher = Auther::Cipher.new "vuKrwD9XWoYuv@s99?tR(9VqryiL,KV{W7wFnejUa4QcVBP+D{2rD4JfuD(mXgA=$tNK4Pfn#NeGs3o3TZ3CqNc^Qb"
76
+
77
+ # Do this to encrypt an unecrypted value.
78
+ cipher.encrypt "test@test.com"
79
+
80
+ # Do this to decrypt an encrypted value.
81
+ cipher.decrypt "N3JzR213WlBISDZsMjJQNkRXbEVmYVczbVdnMHRYVHRud29lOWRCekp6ST0tLWpFMkROekUvWDBkOHZ4ZngxZHV6clE9PQ==--cd863c39991fa4bb9a35de918aa16da54514e331"
82
+
83
+ # Customization
84
+
85
+ ## Initializer
86
+
87
+ The initializer (installed during setup) can be found here:
88
+
89
+ config/initializers/auther.rb
90
+
91
+ The initializer comes installed with the following settings:
63
92
 
64
93
  Rails.application.config.auther_settings = {
65
94
  secret: "vuKrwD9XWoYuv@s99?tR(9VqryiL,KV{W7wFnejUa4QcVBP+D{2rD4JfuD(mXgA=$tNK4Pfn#NeGs3o3TZ3CqNc^Qb",
66
95
  accounts: [
67
96
  name: "admin",
68
- login: "N3JzR213WlBISDZsMjJQNkRXbEVmYVczbVdnMHRYVHRud29lOWRCekp6ST0tLWpFMkROekUvWDBkOHZ4ZngxZHV6clE9PQ==--cd863c39991fa4bb9a35de918aa16da54514e331",
69
- password: "cHhFSStjRm9KbEYwK3ZJVlF2MmpTTWVVZU5acEdlejZsZEhjWFJoQWxKND0tLTE3cmpXZVBQdW5VUW1jK0ZSSDdLUnc9PQ==--f51171174fa77055540420f205e0dd9d499cfeb6",
97
+ encrypted_login: "N3JzR213WlBISDZsMjJQNkRXbEVmYVczbVdnMHRYVHRud29lOWRCekp6ST0tLWpFMkROekUvWDBkOHZ4ZngxZHV6clE9PQ==--cd863c39991fa4bb9a35de918aa16da54514e331",
98
+ encrypted_password: "cHhFSStjRm9KbEYwK3ZJVlF2MmpTTWVVZU5acEdlejZsZEhjWFJoQWxKND0tLTE3cmpXZVBQdW5VUW1jK0ZSSDdLUnc9PQ==--f51171174fa77055540420f205e0dd9d499cfeb6",
70
99
  paths: ["/admin"]
71
- ],
72
- auth_url: "/login"
100
+ ]
73
101
  }
74
102
 
75
- The purpose of each setting is as follows:
103
+ The initializer can be customized as follows:
76
104
 
77
105
  * *title* - Optional. The HTML page title (as rendered within a browser tab). Default: "Authorization".
78
106
  * *label* - Optional. The page label (what would appear above the form). Default: "Authorization".
79
107
  * *secret* - Required. The secret passphrase used to encrypt/decrypt account credentials.
80
108
  * *accounts* - Required. The array of accounts with different or similar access to the application.
81
109
  * *name* - Required. The account name. The name that uniquely identifies each account.
82
- * *login* - Required. The encrypted account login. For example, the above decrypts to: *test@test.com*.
83
- * *password* - Required. The encrypted account password. For example, the above decrypts to: *password*.
110
+ * *encrypted_login* - Required. The encrypted account login. For example, the above decrypts to: *test@test.com*.
111
+ * *encrypted_password* - Required. The encrypted account password. For example, the above decrypts to: *password*.
84
112
  * *paths* - Required. The array of blacklisted paths for which only this account has access to.
85
- * *success_url* - Optional. The URL to redirect to upon successful authorization. Success redirection works
113
+ * *authorized_url* - Optional. The URL to redirect to upon successful authorization. Authorized redirection works
86
114
  as follows (in the order defined):
87
- 0. The blacklisted path (if requested prior to authorization but now authorized).
88
- 0. The success URL (if defined and the blacklisted path wasn't requested).
89
- 0. The root path (if none of the above).
90
- * *auth_url* - Required. The URL to redirect to when enforcing authentication to a blacklisted path.
115
+ 0. The blacklisted path (if requested prior to authorization but now authorized).
116
+ 0. The authorized URL (if defined and the blacklisted path wasn't requested).
117
+ 0. The root path (if none of the above).
118
+ * *deauthorized_url* - Optional. The URL to redirect to upon successful deauthorization (i.e. logout). Deauthorized
119
+ redirections works as follows (in the order defined):
120
+ 0. The deauthorized URL (if defined).
121
+ 0. The auth URL.
122
+ * *auth_url* - Optional. The URL to redirect to when enforcing authentication. Default: “/login”.
91
123
  * *logger* - Optional. The logger used to log path/account authorization messages. Default: Auther::NullLogger.
92
124
 
93
- # Usage
94
-
95
- Using the setup examples, from above, launch your Rails application and visit either of the following routes:
96
-
97
- http://localhost:3000/login
98
- http://localhost:3000/admin # Will redirect to /login if not authorized.
125
+ ## Routes
99
126
 
100
- To encrypt/decrypt account credentials, launch a rails console and type the following:
127
+ The routes can be customized as follows (installed, by default, via the install generator):
101
128
 
102
- # Best if more than 150 characters and gibberish to read. Must be the same as defined in auther settings.
103
- cipher = Auther::Cipher.new "vuKrwD9XWoYuv@s99?tR(9VqryiL,KV{W7wFnejUa4QcVBP+D{2rD4JfuD(mXgA=$tNK4Pfn#NeGs3o3TZ3CqNc^Qb"
104
-
105
- # Do this to encrypt an unecrypted value.
106
- cipher.encrypt "test@test.com"
129
+ Rails.application.routes.draw do
130
+ mount Auther::Engine => "/auther"
131
+ get "/login", to: "auther/session#new", as: "login"
132
+ delete "/logout", to: "auther/session#destroy", as: "logout"
133
+ end
107
134
 
108
- # Do this to decrypt an encrypted value.
109
- cipher.decrypt "N3JzR213WlBISDZsMjJQNkRXbEVmYVczbVdnMHRYVHRud29lOWRCekp6ST0tLWpFMkROekUvWDBkOHZ4ZngxZHV6clE9PQ==--cd863c39991fa4bb9a35de918aa16da54514e331"
135
+ ## Model
110
136
 
111
- # Customization
137
+ The [Auther::Account](app/models/auther/account.rb) is a plain old Ruby object that uses ActiveModel validations to aid
138
+ in attribute validation. This model could potentially be replaced with a database-backed object (would require
139
+ controller customization)...but you might want to question if you have outgrown the use of this gem and need a different
140
+ solution altogether if it comes to that.
112
141
 
113
- ## Model
142
+ ## Presenter
114
143
 
115
- The [Auther::Account](app/models/auther/account.rb) is a plain old Ruby object that uses ActiveRecord validations
116
- to aid in form/credential validation. This model could potentially be replaced with a database-backed object
117
- (would require controller customization)...but you might want to question if you have outgrown the use of this
118
- gem and need a different solution altogether if it comes to that.
144
+ The [Auther::Presenter::Account](app/presenters/auther/account.rb) is a plain old Ruby object that uses ActiveModel
145
+ validations to aid in form validation. This presenter makes it easy to construct form data for input and validation.
119
146
 
120
- ## Views
147
+ ## View
121
148
 
122
149
  The view can be customized by creating the following file within your Rails application (assumes that the
123
150
  default Auther::SessionController implementation is sufficient):
124
151
 
125
152
  app/views/auther/session/new.html
126
153
 
127
- The form can be stylized by attaching new styles to the .authorization class (see
154
+ The form uses `@account_presenter` instance variable which is an instance of the Auther::Presenter::Account presenter
155
+ (as mentioned above). The form can be stylized by attaching new styles to the .authorization class (see
128
156
  [auther.scss](app/assets/stylesheets/auther/auther.scss) for details).
129
157
 
130
158
  ## Controller
@@ -141,23 +169,21 @@ you add a controller to your app that inherits from the Auther::BaseController.
141
169
  This allows complete customization of session controller behavior to serve any special business needs. See the
142
170
  Auther::BaseController for additional details or the Auther::SessionController for default implementation.
143
171
 
144
- ## Routes
145
-
146
- As mentioned in the setup above, the routes can be customized as follows:
147
-
148
- Rails.application.routes.draw do
149
- mount Auther::Engine => "/auther"
150
- get "/login", to: "auther/session#new"
151
- delete "/logout", to: "auther/session#destroy"
152
- end
153
-
154
172
  ## Logging
155
173
 
156
174
  As mentioned in the setup above, the logger can be customized as follows:
157
175
 
158
176
  Auther::NullLogger.new # This is the default logger (which is no logging at all).
159
177
  ActiveSupport::Logger.new("log/#{Rails.env}.log") # Can be used to log to the environment log.
160
- Logger.new($stdout) # Can be used to log to standard output.
178
+ Logger.new(STDOUT) # Can be used to log to standard output.
179
+
180
+ When logging is enabled, you'll be able to see the following information in the server logs to help debug custom
181
+ Auther settings:
182
+
183
+ * Requested path and blacklist path detection.
184
+ * Finding (or not finding) of account.
185
+ * Account authentication pass/fail.
186
+ * Account and path authorization pass/fail.
161
187
 
162
188
  # Tests
163
189
 
@@ -167,10 +193,18 @@ To test, do the following:
167
193
  0. bundle install
168
194
  0. bundle exec rspec spec
169
195
 
196
+ # Troubleshooting
197
+
198
+ * If upgrading Rails, changing the cookie/session settings, generating a new secret base key, etc. this might
199
+ cause Auther authentication to fail. Make sure to clear your browser cookies in this situation or use Google
200
+ Chrome (incognito mode) to verify.
201
+
170
202
  # Resources
171
203
 
172
204
  * [Simplest Auth](https://github.com/vigetlabs/simplest_auth) - For situations where you need user and email reset
173
205
  support beyond what this engine can provide.
206
+ * [Devise](https://github.com/plataformatec/devise) - For complex situations where you need persisted user objects,
207
+ email support, social media support, and much more.
174
208
 
175
209
  # Contributions
176
210
 
@@ -178,11 +212,11 @@ Read CONTRIBUTING for details.
178
212
 
179
213
  # Credits
180
214
 
181
- Developed by [Brooke Kuhlmann](http://www.redalchemist.com) at [Red Alchemist](http://www.redalchemist.com).
215
+ Developed by [Brooke Kuhlmann](http://www.alchemists.io) at [Alchemists](http://www.alchemists.io).
182
216
 
183
217
  # License
184
218
 
185
- Copyright (c) 2014 [Red Alchemist](http://www.redalchemist.com).
219
+ Copyright (c) 2014 [Alchemists](http://www.alchemists.io).
186
220
  Read the LICENSE for details.
187
221
 
188
222
  # History
@@ -1,57 +1,49 @@
1
1
  module Auther
2
2
  class BaseController < ActionController::Base
3
3
  def show
4
- redirect_to settings[:auth_url]
4
+ redirect_to settings.auth_url
5
5
  end
6
6
 
7
7
  def new
8
- @account = Auther::Account.new
8
+ @account_presenter = Auther::Presenter::Account.new
9
9
  end
10
10
 
11
11
  def create
12
- if account.valid?
13
- store_credentials
14
- redirect_to redirect_url
12
+ @account_presenter = Auther::Presenter::Account.new params[:account]
13
+ account_model = Auther::Account.new settings.find_account(@account_presenter.name)
14
+ authenticator = Auther::Authenticator.new settings.secret, account_model, @account_presenter
15
+
16
+ if authenticator.authenticated?
17
+ store_credentials account_model
18
+ redirect_to authorized_url(account_model)
15
19
  else
16
- remove_credentials account.name
20
+ remove_credentials account_model
17
21
  render template: new_template_path
18
22
  end
19
23
  end
20
24
 
21
25
  def destroy
22
- remove_credentials params[:name]
23
- redirect_to settings[:auth_url]
26
+ account_model = Auther::Account.new settings.find_account(params[:name])
27
+ remove_credentials account_model
28
+ redirect_to deauthorized_url(account_model)
24
29
  end
25
30
 
26
31
  private
27
32
 
28
- def load_title
29
- @title = settings.fetch :title, "Authorization"
30
- end
31
-
32
- def load_label
33
- @label = settings.fetch :label, "Authorization"
34
- end
35
-
36
33
  def settings
37
- Rails.application.config.auther_settings
34
+ Auther::Settings.new Rails.application.config.auther_settings
38
35
  end
39
36
 
40
- def account
41
- account_params = params.fetch :account
42
- account_settings = find_account account_params.fetch(:name)
37
+ def load_title
38
+ @title = settings.title
39
+ end
43
40
 
44
- @account ||= Auther::Account.new name: account_params.fetch(:name),
45
- login: account_params.fetch(:login),
46
- secure_login: account_settings.fetch(:login),
47
- password: account_params.fetch(:password),
48
- secure_password: account_settings.fetch(:password),
49
- secret: settings.fetch(:secret),
50
- success_url: account_settings.fetch(:success_url, nil)
41
+ def load_label
42
+ @label = settings.label
51
43
  end
52
44
 
53
- def name_options
54
- @name_options = settings.fetch(:accounts).map do |account|
45
+ def load_account_options
46
+ @account_options = settings.accounts.map do |account|
55
47
  name = account.fetch :name
56
48
  [name.capitalize, name]
57
49
  end
@@ -61,22 +53,22 @@ module Auther
61
53
  raise NotImplementedError, "The method, #new_template_path, is not implemented."
62
54
  end
63
55
 
64
- def redirect_url
65
- session["auther_redirect_url"] || account.success_url || '/'
56
+ def authorized_url account_model
57
+ session["auther_redirect_url"] || account_model.authorized_url || '/'
66
58
  end
67
59
 
68
- def find_account name
69
- settings.fetch(:accounts).select { |account| account.fetch(:name) == name }.first
60
+ def deauthorized_url account_model
61
+ account_model.deauthorized_url || settings.auth_url
70
62
  end
71
63
 
72
- def store_credentials
73
- keymaster = Auther::Keymaster.new account.name
74
- session[keymaster.login_key] = account.secure_login
75
- session[keymaster.password_key] = account.secure_password
64
+ def store_credentials account_model
65
+ keymaster = Auther::Keymaster.new account_model.name
66
+ session[keymaster.login_key] = account_model.encrypted_login
67
+ session[keymaster.password_key] = account_model.encrypted_password
76
68
  end
77
69
 
78
- def remove_credentials name
79
- keymaster = Auther::Keymaster.new name
70
+ def remove_credentials account_model
71
+ keymaster = Auther::Keymaster.new account_model.name
80
72
  session.delete keymaster.login_key
81
73
  session.delete keymaster.password_key
82
74
  end
@@ -1,7 +1,7 @@
1
1
  class Auther::SessionController < Auther::BaseController
2
2
  layout "auther/auth"
3
3
  before_filter :load_title, :load_label
4
- before_filter :name_options, only: [:new, :create]
4
+ before_filter :load_account_options, only: [:new, :create]
5
5
 
6
6
  private
7
7
 
@@ -1,59 +1,21 @@
1
+ require "active_model"
2
+
1
3
  module Auther
2
4
  class Account
3
5
  include ActiveModel::Validations
4
6
 
5
- attr_accessor :name, :login, :secure_login, :password, :secure_password, :paths, :success_url
7
+ attr_accessor :name, :encrypted_login, :encrypted_password, :paths, :authorized_url, :deauthorized_url
6
8
 
7
- validates :name, presence: true
9
+ validates :name, :encrypted_login, :encrypted_password, presence: true
8
10
  validates :paths, presence: {unless: lambda { |account| account.paths.is_a? Array }, message: "must be an array"}
9
11
 
10
12
  def initialize options = {}
11
13
  @name = options.fetch :name, nil
12
- @login = options.fetch :login, nil
13
- @secure_login = options.fetch :secure_login, nil
14
- @password = options.fetch :password, nil
15
- @secure_password = options.fetch :secure_password, nil
14
+ @encrypted_login = options.fetch :encrypted_login, nil
15
+ @encrypted_password = options.fetch :encrypted_password, nil
16
16
  @paths = options.fetch :paths, []
17
- @secret = options.fetch :secret, nil
18
- @success_url = options.fetch :success_url, nil
19
- end
20
-
21
- def valid?
22
- super && authorized_login? && authorized_password?
23
- end
24
-
25
- def invalid?
26
- !valid?
27
- end
28
-
29
- private
30
-
31
- def secret
32
- @secret
33
- end
34
-
35
- def decrypt attribute
36
- if attribute.present? && secret.present?
37
- cipher = Auther::Cipher.new secret
38
- cipher.decrypt attribute
39
- end
40
- end
41
-
42
- def authorized? attribute, secure_attribute, error_name
43
- if attribute == decrypt(secure_attribute)
44
- true
45
- else
46
- errors.add error_name, "is invalid"
47
- false
48
- end
49
- end
50
-
51
- def authorized_login?
52
- authorized? login, secure_login, "login"
53
- end
54
-
55
- def authorized_password?
56
- authorized? password, secure_password, "password"
17
+ @authorized_url = options.fetch :authorized_url, nil
18
+ @deauthorized_url = options.fetch :deauthorized_url, nil
57
19
  end
58
20
  end
59
21
  end
@@ -0,0 +1,19 @@
1
+ require "active_model"
2
+
3
+ module Auther
4
+ module Presenter
5
+ class Account
6
+ include ActiveModel::Validations
7
+
8
+ attr_accessor :name, :login, :password
9
+
10
+ validates :name, :login, :password, presence: true
11
+
12
+ def initialize options = {}
13
+ @name = options[:name]
14
+ @login = options[:login]
15
+ @password = options[:password]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,12 +1,12 @@
1
1
  - content_for(:title) { @title }
2
2
 
3
- - error_keys = @account.errors.keys
3
+ - error_keys = @account_presenter.errors.keys
4
4
  - login_error = error_keys.include?(:login)
5
5
  - password_error = error_keys.include?(:password)
6
6
  - name_error = error_keys.include?(:name)
7
7
 
8
8
  .authorization
9
- = form_for @account, as: :account, url: "/auther/session" do |form|
9
+ = form_for @account_presenter, as: :account, url: "/auther/session" do |form|
10
10
  .small-12
11
11
  .row
12
12
  h1.authorization-label = @label
@@ -18,7 +18,7 @@
18
18
  = form.label :login, "Login:", class: "inline right"
19
19
  = content_tag :div, class: render_foundation_error(login_error, classes: %w(small-6 columns))
20
20
  = form.text_field :login
21
- = content_tag(:small, @account.errors.full_messages.first, class: "error") if login_error
21
+ = content_tag(:small, @account_presenter.errors.full_messages.first, class: "error") if login_error
22
22
  .row
23
23
  .small-8
24
24
  .row
@@ -26,7 +26,7 @@
26
26
  = form.label :password, "Password:", class: "inline right"
27
27
  = content_tag :div, class: render_foundation_error(password_error, classes: %w(small-6 columns))
28
28
  = form.password_field :password
29
- = content_tag(:small, @account.errors.full_messages.first, class: "error") if password_error
29
+ = content_tag(:small, @account_presenter.errors.full_messages.first, class: "error") if password_error
30
30
 
31
31
  .row
32
32
  .small-8
@@ -34,7 +34,7 @@
34
34
  .small-6.columns
35
35
  = form.label :name, "Account:", class: "inline right"
36
36
  .small-6.columns
37
- = form.select :name, @name_options
37
+ = form.select :name, @account_options
38
38
 
39
39
  .row
40
40
  .small-8
data/lib/auther.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require "slim-rails"
2
+ require "auther/version"
3
+ require "auther/settings"
2
4
  require "auther/null_logger"
3
5
  require "auther/cipher"
6
+ require "auther/authenticator"
4
7
  require "auther/keymaster"
5
8
  require "auther/gatekeeper"
6
9
  require "auther/engine"
@@ -0,0 +1,56 @@
1
+ module Auther
2
+ class Authenticator
3
+
4
+ attr_reader :logger
5
+
6
+ def initialize secret, account_model, account_presenter, logger = Auther::NullLogger.new(STDOUT)
7
+ @cipher = Auther::Cipher.new secret
8
+ @account_model = account_model
9
+ @account_presenter = account_presenter
10
+ @logger = logger
11
+ end
12
+
13
+ def authenticated?
14
+ account_model.valid? &&
15
+ account_presenter.valid? &&
16
+ authentic_name? &&
17
+ authentic_login? &&
18
+ authentic_password?
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :cipher, :account_model, :account_presenter
24
+
25
+ def log_info message
26
+ id = "[#{Auther::Keymaster.namespace}]"
27
+ logger.info [id, message].join(": ")
28
+ end
29
+
30
+ def authentic? encrypted_value, value, error_name
31
+ begin
32
+ if cipher.decrypt(encrypted_value) == value
33
+ true
34
+ else
35
+ account_presenter.errors.add error_name, "is invalid"
36
+ false
37
+ end
38
+ rescue ActiveSupport::MessageVerifier::InvalidSignature => error
39
+ log_info %(Authentication failed! Invalid credential(s) for "#{account_model.name}" account.)
40
+ false
41
+ end
42
+ end
43
+
44
+ def authentic_name?
45
+ account_presenter.name == account_model.name
46
+ end
47
+
48
+ def authentic_login?
49
+ authentic? account_model.encrypted_login, account_presenter.login, "login"
50
+ end
51
+
52
+ def authentic_password?
53
+ authentic? account_model.encrypted_password, account_presenter.password, "password"
54
+ end
55
+ end
56
+ end
data/lib/auther/engine.rb CHANGED
@@ -5,6 +5,13 @@ module Auther
5
5
  # Set defaults. Can be overwritten in app config.
6
6
  config.auther_settings = {}
7
7
 
8
+ # Autoload presenters
9
+ config.to_prepare do
10
+ Dir.glob(Engine.root + "app/presenters/**/*.rb").each do |presenter|
11
+ require_dependency presenter
12
+ end
13
+ end
14
+
8
15
  initializer "auther.initialize" do |app|
9
16
  asset_paths = app.config.assets.paths
10
17
 
@@ -1,11 +1,12 @@
1
1
  module Auther
2
2
  class Gatekeeper
3
- attr_reader :application, :environment, :settings, :logger
3
+ attr_reader :application, :environment, :settings
4
4
 
5
- def initialize application, settings = []
5
+ delegate :logger, to: :settings
6
+
7
+ def initialize application, settings = {}
6
8
  @application = application
7
- @settings = settings
8
- @logger = @settings.fetch :logger, Auther::NullLogger.new(STDOUT)
9
+ @settings = Auther::Settings.new settings
9
10
  end
10
11
 
11
12
  def call environment
@@ -16,7 +17,7 @@ module Auther
16
17
  else
17
18
  session[Auther::Keymaster.redirect_url_key] = request.path
18
19
  denied_response = response
19
- denied_response.redirect settings[:auth_url]
20
+ denied_response.redirect settings.auth_url
20
21
  denied_response.finish
21
22
  end
22
23
  end
@@ -62,7 +63,7 @@ module Auther
62
63
  def find_account
63
64
  session["auther_init"] = true # Force session to initialize.
64
65
  account_name = Auther::Keymaster.get_account_name session
65
- account = settings.fetch(:accounts).detect { |account| account.fetch(:name) == account_name }
66
+ account = settings.find_account account_name
66
67
 
67
68
  account ? log_info("Account found.") : log_info("Account unknown.")
68
69
  account
@@ -84,13 +85,13 @@ module Auther
84
85
 
85
86
  def authenticated? account
86
87
  keymaster = Auther::Keymaster.new account.fetch(:name)
87
- cipher = Auther::Cipher.new settings.fetch(:secret)
88
+ cipher = Auther::Cipher.new settings.secret
88
89
 
89
90
  begin
90
91
  session_login = cipher.decrypt session[keymaster.login_key]
91
92
  session_password = cipher.decrypt session[keymaster.password_key]
92
- account_login = cipher.decrypt account.fetch(:login)
93
- account_password = cipher.decrypt account.fetch(:password)
93
+ account_login = cipher.decrypt account.fetch(:encrypted_login)
94
+ account_password = cipher.decrypt account.fetch(:encrypted_password)
94
95
 
95
96
  authenticated = session_login == account_login && session_password == account_password
96
97
  log_authentication authenticated, account.fetch(:name)
@@ -110,8 +111,8 @@ module Auther
110
111
  end
111
112
 
112
113
  def authorized? path
113
- accounts = settings.fetch :accounts
114
- all_blacklisted_paths = blacklisted_paths settings.fetch(:accounts)
114
+ accounts = settings.accounts
115
+ all_blacklisted_paths = blacklisted_paths settings.accounts
115
116
 
116
117
  if blacklisted_matched_paths(accounts, path).any?
117
118
  log_info %(Requested path "#{request.path}" found in blacklisted paths: #{all_blacklisted_paths}.)
@@ -0,0 +1,18 @@
1
+ module Auther
2
+ class Settings
3
+ attr_reader :title, :label, :secret, :accounts, :auth_url, :logger
4
+
5
+ def initialize options = {}
6
+ @title = options.fetch :title, "Authorization"
7
+ @label = options.fetch :title, "Authorization"
8
+ @secret = options.fetch :secret, nil
9
+ @accounts = options.fetch :accounts, []
10
+ @auth_url = options.fetch :auth_url, "/login"
11
+ @logger = options.fetch :logger, Auther::NullLogger.new(STDOUT)
12
+ end
13
+
14
+ def find_account name
15
+ accounts.detect { |account| account.fetch(:name) == name }
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module Auther
2
- VERSION = "1.4.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,23 @@
1
+ module Auther
2
+ class InstallGenerator < ::Rails::Generators::Base
3
+ source_root File.join(File.dirname(__FILE__), "..", "templates")
4
+
5
+ desc "Installs Auther settings and routes."
6
+ def install
7
+ install_initializer
8
+ add_routes
9
+ end
10
+
11
+ private
12
+
13
+ def install_initializer
14
+ template File.join("config", "initializers", "auther.rb"), File.join("config", "initializers", "auther.rb")
15
+ end
16
+
17
+ def add_routes
18
+ route %(delete "/logout", to: "auther/session#destroy", as: "logout")
19
+ route %(get "/login", to: "auther/session#new", as: "login")
20
+ route %(mount Auther::Engine => "/auther")
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ Rails.application.config.auther_settings = {
2
+ secret: "vuKrwD9XWoYuv@s99?tR(9VqryiL,KV{W7wFnejUa4QcVBP+D{2rD4JfuD(mXgA=$tNK4Pfn#NeGs3o3TZ3CqNc^Qb",
3
+ accounts: [
4
+ name: "admin",
5
+ encrypted_login: "N3JzR213WlBISDZsMjJQNkRXbEVmYVczbVdnMHRYVHRud29lOWRCekp6ST0tLWpFMkROekUvWDBkOHZ4ZngxZHV6clE9PQ==--cd863c39991fa4bb9a35de918aa16da54514e331",
6
+ encrypted_password: "cHhFSStjRm9KbEYwK3ZJVlF2MmpTTWVVZU5acEdlejZsZEhjWFJoQWxKND0tLTE3cmpXZVBQdW5VUW1jK0ZSSDdLUnc9PQ==--f51171174fa77055540420f205e0dd9d499cfeb6",
7
+ paths: ["/admin"]
8
+ ]
9
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auther
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -30,7 +30,7 @@ cert_chain:
30
30
  SJpzzzZ8gO6BKn4fhd+ENNQ333Qy3nuNk07TVIaNnlgeHhowUDuD9T7Z8Lka0pt3
31
31
  4PteiTppsf0SSVAM9zSO5IuFngXMRwWgvjOfXE70f43RDuUVTCSyylc=
32
32
  -----END CERTIFICATE-----
33
- date: 2014-05-29 00:00:00.000000000 Z
33
+ date: 2014-06-12 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: pry-byebug
@@ -160,6 +160,20 @@ dependencies:
160
160
  version: '10.0'
161
161
  - !ruby/object:Gem::Dependency
162
162
  name: pry
163
+ requirement: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: 0.9.12
168
+ type: :development
169
+ prerelease: false
170
+ version_requirements: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: 0.9.12
175
+ - !ruby/object:Gem::Dependency
176
+ name: pry-remote
163
177
  requirement: !ruby/object:Gem::Requirement
164
178
  requirements:
165
179
  - - ">="
@@ -173,7 +187,7 @@ dependencies:
173
187
  - !ruby/object:Gem::Version
174
188
  version: '0'
175
189
  - !ruby/object:Gem::Dependency
176
- name: pry-remote
190
+ name: pry-rescue
177
191
  requirement: !ruby/object:Gem::Requirement
178
192
  requirements:
179
193
  - - ">="
@@ -187,7 +201,7 @@ dependencies:
187
201
  - !ruby/object:Gem::Version
188
202
  version: '0'
189
203
  - !ruby/object:Gem::Dependency
190
- name: pry-rescue
204
+ name: rspec-rails
191
205
  requirement: !ruby/object:Gem::Requirement
192
206
  requirements:
193
207
  - - ">="
@@ -201,7 +215,7 @@ dependencies:
201
215
  - !ruby/object:Gem::Version
202
216
  version: '0'
203
217
  - !ruby/object:Gem::Dependency
204
- name: rspec-rails
218
+ name: ammeter
205
219
  requirement: !ruby/object:Gem::Requirement
206
220
  requirements:
207
221
  - - ">="
@@ -243,7 +257,7 @@ dependencies:
243
257
  - !ruby/object:Gem::Version
244
258
  version: '0'
245
259
  - !ruby/object:Gem::Dependency
246
- name: coveralls
260
+ name: codeclimate-test-reporter
247
261
  requirement: !ruby/object:Gem::Requirement
248
262
  requirements:
249
263
  - - ">="
@@ -276,17 +290,22 @@ files:
276
290
  - app/controllers/auther/session_controller.rb
277
291
  - app/helpers/auther/foundation_helper.rb
278
292
  - app/models/auther/account.rb
293
+ - app/presenters/auther/account.rb
279
294
  - app/views/auther/session/new.html.slim
280
295
  - app/views/layouts/auther/auth.html.slim
281
296
  - bin/rails
282
297
  - config/routes.rb
283
298
  - lib/auther.rb
299
+ - lib/auther/authenticator.rb
284
300
  - lib/auther/cipher.rb
285
301
  - lib/auther/engine.rb
286
302
  - lib/auther/gatekeeper.rb
287
303
  - lib/auther/keymaster.rb
288
304
  - lib/auther/null_logger.rb
305
+ - lib/auther/settings.rb
289
306
  - lib/auther/version.rb
307
+ - lib/generators/auther/install/install_generator.rb
308
+ - lib/generators/auther/templates/config/initializers/auther.rb
290
309
  homepage: https://github.com/bkuhlmann/auther
291
310
  licenses:
292
311
  - MIT
@@ -307,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
307
326
  version: '0'
308
327
  requirements: []
309
328
  rubyforge_project:
310
- rubygems_version: 2.2.2
329
+ rubygems_version: 2.3.0
311
330
  signing_key:
312
331
  specification_version: 4
313
332
  summary: Enhances Rails with multi-account, form-based, database-less, application-wide
metadata.gz.sig CHANGED
Binary file