authlogic 3.8.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/authlogic/acts_as_authentic/base.rb +33 -36
- data/lib/authlogic/acts_as_authentic/email.rb +8 -141
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +17 -10
- data/lib/authlogic/acts_as_authentic/login.rb +14 -165
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +13 -10
- data/lib/authlogic/acts_as_authentic/password.rb +186 -254
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +30 -22
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +19 -18
- data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +83 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +94 -62
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +28 -14
- data/lib/authlogic/config.rb +29 -10
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +43 -13
- data/lib/authlogic/controller_adapters/rack_adapter.rb +11 -5
- data/lib/authlogic/controller_adapters/rails_adapter.rb +11 -29
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +8 -2
- data/lib/authlogic/cookie_credentials.rb +63 -0
- data/lib/authlogic/crypto_providers/bcrypt.rb +24 -18
- data/lib/authlogic/crypto_providers/md5/v2.rb +35 -0
- data/lib/authlogic/crypto_providers/md5.rb +8 -6
- data/lib/authlogic/crypto_providers/scrypt.rb +24 -17
- data/lib/authlogic/crypto_providers/sha1/v2.rb +41 -0
- data/lib/authlogic/crypto_providers/sha1.rb +12 -5
- data/lib/authlogic/crypto_providers/sha256/v2.rb +58 -0
- data/lib/authlogic/crypto_providers/sha256.rb +18 -9
- data/lib/authlogic/crypto_providers/sha512/v2.rb +39 -0
- data/lib/authlogic/crypto_providers/sha512.rb +9 -26
- data/lib/authlogic/crypto_providers.rb +77 -1
- data/lib/authlogic/errors.rb +35 -0
- data/lib/authlogic/i18n/translator.rb +4 -1
- data/lib/authlogic/i18n.rb +29 -20
- data/lib/authlogic/random.rb +12 -28
- data/lib/authlogic/session/base.rb +2087 -33
- data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
- data/lib/authlogic/test_case/mock_controller.rb +7 -4
- data/lib/authlogic/test_case/mock_cookie_jar.rb +19 -3
- data/lib/authlogic/test_case/mock_logger.rb +2 -0
- data/lib/authlogic/test_case/mock_request.rb +8 -3
- data/lib/authlogic/test_case/rails_request_adapter.rb +5 -2
- data/lib/authlogic/test_case.rb +74 -2
- data/lib/authlogic/version.rb +22 -0
- data/lib/authlogic.rb +33 -54
- metadata +208 -234
- data/.github/ISSUE_TEMPLATE.md +0 -13
- data/.gitignore +0 -14
- data/.rubocop.yml +0 -33
- data/.rubocop_todo.yml +0 -391
- data/.travis.yml +0 -48
- data/CHANGELOG.md +0 -5
- data/CONTRIBUTING.md +0 -60
- data/Gemfile +0 -5
- data/LICENSE +0 -20
- data/README.md +0 -294
- data/Rakefile +0 -21
- data/authlogic.gemspec +0 -27
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -70
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -32
- data/lib/authlogic/authenticates_many/association.rb +0 -50
- data/lib/authlogic/authenticates_many/base.rb +0 -65
- data/lib/authlogic/crypto_providers/aes256.rb +0 -66
- data/lib/authlogic/crypto_providers/wordpress.rb +0 -43
- data/lib/authlogic/regex.rb +0 -48
- data/lib/authlogic/session/activation.rb +0 -70
- data/lib/authlogic/session/active_record_trickery.rb +0 -61
- data/lib/authlogic/session/brute_force_protection.rb +0 -120
- data/lib/authlogic/session/callbacks.rb +0 -105
- data/lib/authlogic/session/cookies.rb +0 -244
- data/lib/authlogic/session/existence.rb +0 -93
- data/lib/authlogic/session/foundation.rb +0 -55
- data/lib/authlogic/session/http_auth.rb +0 -100
- data/lib/authlogic/session/id.rb +0 -48
- data/lib/authlogic/session/klass.rb +0 -70
- data/lib/authlogic/session/magic_columns.rb +0 -116
- data/lib/authlogic/session/magic_states.rb +0 -76
- data/lib/authlogic/session/params.rb +0 -116
- data/lib/authlogic/session/password.rb +0 -308
- data/lib/authlogic/session/perishable_token.rb +0 -23
- data/lib/authlogic/session/persistence.rb +0 -71
- data/lib/authlogic/session/priority_record.rb +0 -35
- data/lib/authlogic/session/scopes.rb +0 -119
- data/lib/authlogic/session/session.rb +0 -67
- data/lib/authlogic/session/timeout.rb +0 -103
- data/lib/authlogic/session/unauthorized_record.rb +0 -51
- data/lib/authlogic/session/validation.rb +0 -93
- data/test/acts_as_authentic_test/base_test.rb +0 -25
- data/test/acts_as_authentic_test/email_test.rb +0 -240
- data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -62
- data/test/acts_as_authentic_test/login_test.rb +0 -156
- data/test/acts_as_authentic_test/magic_columns_test.rb +0 -27
- data/test/acts_as_authentic_test/password_test.rb +0 -249
- data/test/acts_as_authentic_test/perishable_token_test.rb +0 -90
- data/test/acts_as_authentic_test/persistence_token_test.rb +0 -56
- data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -37
- data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -96
- data/test/acts_as_authentic_test/single_access_test.rb +0 -44
- data/test/authenticates_many_test.rb +0 -31
- data/test/config_test.rb +0 -36
- data/test/crypto_provider_test/aes256_test.rb +0 -14
- data/test/crypto_provider_test/bcrypt_test.rb +0 -14
- data/test/crypto_provider_test/scrypt_test.rb +0 -14
- data/test/crypto_provider_test/sha1_test.rb +0 -23
- data/test/crypto_provider_test/sha256_test.rb +0 -14
- data/test/crypto_provider_test/sha512_test.rb +0 -14
- data/test/fixtures/companies.yml +0 -5
- data/test/fixtures/employees.yml +0 -17
- data/test/fixtures/projects.yml +0 -3
- data/test/fixtures/users.yml +0 -41
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-5.0.x +0 -6
- data/test/gemfiles/Gemfile.rails-5.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-5.2.x +0 -6
- data/test/i18n/lol.yml +0 -4
- data/test/i18n_test.rb +0 -33
- data/test/libs/affiliate.rb +0 -7
- data/test/libs/company.rb +0 -6
- data/test/libs/employee.rb +0 -7
- data/test/libs/employee_session.rb +0 -2
- data/test/libs/ldaper.rb +0 -3
- data/test/libs/project.rb +0 -3
- data/test/libs/user.rb +0 -7
- data/test/libs/user_session.rb +0 -25
- data/test/random_test.rb +0 -43
- data/test/session_test/activation_test.rb +0 -43
- data/test/session_test/active_record_trickery_test.rb +0 -75
- data/test/session_test/brute_force_protection_test.rb +0 -108
- data/test/session_test/callbacks_test.rb +0 -34
- data/test/session_test/cookies_test.rb +0 -201
- data/test/session_test/credentials_test.rb +0 -0
- data/test/session_test/existence_test.rb +0 -75
- data/test/session_test/foundation_test.rb +0 -6
- data/test/session_test/http_auth_test.rb +0 -56
- data/test/session_test/id_test.rb +0 -17
- data/test/session_test/klass_test.rb +0 -40
- data/test/session_test/magic_columns_test.rb +0 -62
- data/test/session_test/magic_states_test.rb +0 -58
- data/test/session_test/params_test.rb +0 -53
- data/test/session_test/password_test.rb +0 -105
- data/test/session_test/perishability_test.rb +0 -15
- data/test/session_test/persistence_test.rb +0 -32
- data/test/session_test/scopes_test.rb +0 -60
- data/test/session_test/session_test.rb +0 -78
- data/test/session_test/timeout_test.rb +0 -82
- data/test/session_test/unauthorized_record_test.rb +0 -13
- data/test/session_test/validation_test.rb +0 -23
- data/test/test_helper.rb +0 -233
data/README.md
DELETED
@@ -1,294 +0,0 @@
|
|
1
|
-
# Authlogic
|
2
|
-
|
3
|
-
**Authlogic supports rails 3, 4 and 5. For rails 2, see the [rails2 branch](https://github.com/binarylogic/authlogic/tree/rails2).**
|
4
|
-
|
5
|
-
[![Gem Version](https://badge.fury.io/rb/authlogic.png)](http://badge.fury.io/rb/authlogic)
|
6
|
-
[![Build Status](https://travis-ci.org/binarylogic/authlogic.png?branch=master)](https://travis-ci.org/binarylogic/authlogic)
|
7
|
-
[![Code Climate](https://codeclimate.com/github/binarylogic/authlogic.png)](https://codeclimate.com/github/binarylogic/authlogic)
|
8
|
-
|
9
|
-
Authlogic is a clean, simple, and unobtrusive ruby authentication solution.
|
10
|
-
|
11
|
-
It introduces a new type of model. You can have as many as you want, and name them whatever you want, just like your other models. In this example, we want to authenticate with the User model, which is inferred by the name:
|
12
|
-
|
13
|
-
```ruby
|
14
|
-
class UserSession < Authlogic::Session::Base
|
15
|
-
# specify configuration here, such as:
|
16
|
-
# logout_on_timeout true
|
17
|
-
# ...many more options in the documentation
|
18
|
-
end
|
19
|
-
```
|
20
|
-
|
21
|
-
In a `UserSessionsController`, login the user by using it just like your other models:
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
UserSession.create(:login => "bjohnson", :password => "my password", :remember_me => true)
|
25
|
-
|
26
|
-
session = UserSession.new(:login => "bjohnson", :password => "my password", :remember_me => true)
|
27
|
-
session.save
|
28
|
-
|
29
|
-
# requires the authlogic-oid "add on" gem
|
30
|
-
UserSession.create(:openid_identifier => "identifier", :remember_me => true)
|
31
|
-
|
32
|
-
# skip authentication and log the user in directly, the true means "remember me"
|
33
|
-
UserSession.create(my_user_object, true)
|
34
|
-
```
|
35
|
-
|
36
|
-
The above handles the entire authentication process for you by:
|
37
|
-
|
38
|
-
1. authenticating (i.e. **validating** the record)
|
39
|
-
2. sets up the proper session values and cookies to persist the session (i.e. **saving** the record).
|
40
|
-
|
41
|
-
You can also log out (i.e. **destroying** the session):
|
42
|
-
|
43
|
-
``` ruby
|
44
|
-
session.destroy
|
45
|
-
```
|
46
|
-
|
47
|
-
After a session has been created, you can persist it (i.e. **finding** the record) across requests. Thus keeping the user logged in:
|
48
|
-
|
49
|
-
``` ruby
|
50
|
-
session = UserSession.find
|
51
|
-
```
|
52
|
-
|
53
|
-
To get all of the nice authentication functionality in your model just do this:
|
54
|
-
|
55
|
-
```ruby
|
56
|
-
class User < ActiveRecord::Base
|
57
|
-
acts_as_authentic do |c|
|
58
|
-
c.my_config_option = my_value
|
59
|
-
end # the configuration block is optional
|
60
|
-
end
|
61
|
-
```
|
62
|
-
|
63
|
-
This handles validations, etc. It is also "smart" in the sense that it if a login field is present it will use that to authenticate, if not it will look for an email field, etc. This is all configurable, but for 99% of cases that above is all you will need to do.
|
64
|
-
|
65
|
-
You may specify how passwords are cryptographically hashed (or encrypted) by setting the Authlogic::CryptoProvider option:
|
66
|
-
|
67
|
-
``` ruby
|
68
|
-
c.crypto_provider = Authlogic::CryptoProviders::BCrypt
|
69
|
-
```
|
70
|
-
|
71
|
-
You may validate international email addresses by enabling the provided alternate regex:
|
72
|
-
|
73
|
-
``` ruby
|
74
|
-
c.validates_format_of_email_field_options = {:with => Authlogic::Regex.email_nonascii}
|
75
|
-
```
|
76
|
-
|
77
|
-
Also, sessions are automatically maintained. You can switch this on and off with configuration, but the following will automatically log a user in after a successful registration:
|
78
|
-
|
79
|
-
``` ruby
|
80
|
-
User.create(params[:user])
|
81
|
-
```
|
82
|
-
|
83
|
-
This also updates the session when the user changes his/her password.
|
84
|
-
|
85
|
-
Authlogic is very flexible, it has a strong public API and a plethora of hooks to allow you to modify behavior and extend it. Check out the helpful links below to dig deeper.
|
86
|
-
|
87
|
-
## Upgrading to Authlogic 3.4.0
|
88
|
-
|
89
|
-
In version 3.4.0, the default crypto_provider was changed from *Sha512* to *SCrypt*.
|
90
|
-
|
91
|
-
If you never set a crypto_provider and are upgrading, your passwords will break unless you set the original:
|
92
|
-
|
93
|
-
``` ruby
|
94
|
-
c.crypto_provider = Authlogic::CryptoProviders::Sha512
|
95
|
-
```
|
96
|
-
|
97
|
-
And if you want to automatically upgrade from *Sha512* to *SCrypt* as users login:
|
98
|
-
|
99
|
-
```ruby
|
100
|
-
c.transition_from_crypto_providers = [Authlogic::CryptoProviders::Sha512]
|
101
|
-
c.crypto_provider = Authlogic::CryptoProviders::SCrypt
|
102
|
-
```
|
103
|
-
|
104
|
-
## Helpful links
|
105
|
-
|
106
|
-
* <b>Documentation:</b> http://rdoc.info/projects/binarylogic/authlogic
|
107
|
-
* <b>Repository:</b> http://github.com/binarylogic/authlogic/tree/master
|
108
|
-
* <b>Railscasts Screencast:</b> http://railscasts.com/episodes/160-authlogic
|
109
|
-
* <b>Example repository with tutorial in README:</b> http://github.com/binarylogic/authlogic_example/tree/master
|
110
|
-
* <b>Tutorial: Reset passwords with Authlogic the RESTful way:</b> http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic
|
111
|
-
* <b>Tutorial</b>: Rails Authentication with Authlogic http://www.sitepoint.com/rails-authentication-with-authlogic
|
112
|
-
* <b>Issues:</b> http://github.com/binarylogic/authlogic/issues
|
113
|
-
|
114
|
-
## Authlogic "add ons"
|
115
|
-
|
116
|
-
* <b>Authlogic OpenID addon:</b> http://github.com/binarylogic/authlogic_openid
|
117
|
-
* <b>Authlogic LDAP addon:</b> http://github.com/binarylogic/authlogic_ldap
|
118
|
-
* <b>Authlogic Facebook Connect:</b> http://github.com/kalasjocke/authlogic_facebook_connect
|
119
|
-
* <b>Authlogic Facebook Connect (New JS API):</b> http://github.com/studybyte/authlogic_facebook_connect
|
120
|
-
* <b>Authlogic Facebook Shim</b> http://github.com/james2m/authlogic_facebook_shim
|
121
|
-
* <b>Authlogic OAuth (Twitter):</b> http://github.com/jrallison/authlogic_oauth
|
122
|
-
* <b>Authlogic Oauth and OpenID:</b> http://github.com/viatropos/authlogic-connect
|
123
|
-
* <b>Authlogic PAM:</b> http://github.com/nbudin/authlogic_pam
|
124
|
-
* <b>Authlogic x509:</b> http://github.com/auth-scc/authlogic_x509
|
125
|
-
|
126
|
-
If you create one of your own, please let me know about it so I can add it to this list. Or just fork the project, add your link, and send me a pull request.
|
127
|
-
|
128
|
-
## Documentation explanation
|
129
|
-
|
130
|
-
You can find anything you want about Authlogic in the [documentation](http://rdoc.info/projects/binarylogic/authlogic), all that you need to do is understand the basic design behind it.
|
131
|
-
|
132
|
-
That being said, there are 2 models involved during authentication. Your Authlogic model and your ActiveRecord model:
|
133
|
-
|
134
|
-
1. <b>Authlogic::Session</b>, your session models that extend Authlogic::Session::Base.
|
135
|
-
2. <b>Authlogic::ActsAsAuthentic</b>, which adds in functionality to your ActiveRecord model when you call acts_as_authentic.
|
136
|
-
|
137
|
-
Each of the above has its various sub modules that contain common logic. The sub modules are responsible for including *everything* related to it: configuration, class methods, instance methods, etc.
|
138
|
-
|
139
|
-
For example, if you want to timeout users after a certain period of inactivity, you would look in <b>Authlogic::Session::Timeout</b>. To help you out, I listed the following publicly relevant modules with short descriptions. For the sake of brevity, there are more modules than listed here, the ones not listed are more for internal use, but you can easily read up on them in the [documentation](http://rdoc.info/projects/binarylogic/authlogic).
|
140
|
-
|
141
|
-
## Example migration
|
142
|
-
|
143
|
-
If you want to enable all the features of Authlogic, a migration to create a
|
144
|
-
+User+ model, for example, might look like this:
|
145
|
-
|
146
|
-
``` ruby
|
147
|
-
class CreateUser < ActiveRecord::Migration
|
148
|
-
def change
|
149
|
-
create_table :users do |t|
|
150
|
-
# Authlogic::ActsAsAuthentic::Email
|
151
|
-
t.string :email
|
152
|
-
|
153
|
-
# Authlogic::ActsAsAuthentic::Password
|
154
|
-
t.string :crypted_password
|
155
|
-
t.string :password_salt
|
156
|
-
|
157
|
-
# Authlogic::ActsAsAuthentic::PersistenceToken
|
158
|
-
t.string :persistence_token
|
159
|
-
|
160
|
-
# Authlogic::ActsAsAuthentic::SingleAccessToken
|
161
|
-
t.string :single_access_token
|
162
|
-
|
163
|
-
# Authlogic::ActsAsAuthentic::PerishableToken
|
164
|
-
t.string :perishable_token
|
165
|
-
|
166
|
-
# Authlogic::Session::MagicColumns
|
167
|
-
t.integer :login_count, default: 0, null: false
|
168
|
-
t.integer :failed_login_count, default: 0, null: false
|
169
|
-
t.datetime :last_request_at
|
170
|
-
t.datetime :current_login_at
|
171
|
-
t.datetime :last_login_at
|
172
|
-
t.string :current_login_ip
|
173
|
-
t.string :last_login_ip
|
174
|
-
|
175
|
-
# Authlogic::Session::MagicStates
|
176
|
-
t.boolean :active, default: false
|
177
|
-
t.boolean :approved, default: false
|
178
|
-
t.boolean :confirmed, default: false
|
179
|
-
|
180
|
-
t.timestamps
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
```
|
185
|
-
|
186
|
-
## Quick Rails example
|
187
|
-
|
188
|
-
What if creating sessions worked like an ORM library on the surface...
|
189
|
-
|
190
|
-
``` ruby
|
191
|
-
UserSession.create(params[:user_session])
|
192
|
-
```
|
193
|
-
|
194
|
-
What if your user sessions controller could look just like your other controllers...
|
195
|
-
|
196
|
-
```ruby
|
197
|
-
class UserSessionsController < ApplicationController
|
198
|
-
def new
|
199
|
-
@user_session = UserSession.new
|
200
|
-
end
|
201
|
-
|
202
|
-
def create
|
203
|
-
@user_session = UserSession.new(params[:user_session])
|
204
|
-
if @user_session.save
|
205
|
-
redirect_to account_url
|
206
|
-
else
|
207
|
-
render :action => :new
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
def destroy
|
212
|
-
current_user_session.destroy
|
213
|
-
redirect_to new_user_session_url
|
214
|
-
end
|
215
|
-
end
|
216
|
-
```
|
217
|
-
|
218
|
-
As you can see, this fits nicely into the RESTful development pattern. What about the view...
|
219
|
-
|
220
|
-
```erb
|
221
|
-
<%= form_for @user_session do |f| %>
|
222
|
-
<% if @user_session.errors.any? %>
|
223
|
-
<div id="error_explanation">
|
224
|
-
<h2><%= pluralize(@user_session.errors.count, "error") %> prohibited:</h2>
|
225
|
-
<ul>
|
226
|
-
<% @user_session.errors.full_messages.each do |msg| %>
|
227
|
-
<li><%= msg %></li>
|
228
|
-
<% end %>
|
229
|
-
</ul>
|
230
|
-
</div>
|
231
|
-
<% end %>
|
232
|
-
<%= f.label :login %><br />
|
233
|
-
<%= f.text_field :login %><br />
|
234
|
-
<br />
|
235
|
-
<%= f.label :password %><br />
|
236
|
-
<%= f.password_field :password %><br />
|
237
|
-
<br />
|
238
|
-
<%= f.submit "Login" %>
|
239
|
-
<% end %>
|
240
|
-
```
|
241
|
-
|
242
|
-
Or how about persisting the session...
|
243
|
-
|
244
|
-
```ruby
|
245
|
-
class ApplicationController
|
246
|
-
helper_method :current_user_session, :current_user
|
247
|
-
|
248
|
-
private
|
249
|
-
def current_user_session
|
250
|
-
return @current_user_session if defined?(@current_user_session)
|
251
|
-
@current_user_session = UserSession.find
|
252
|
-
end
|
253
|
-
|
254
|
-
def current_user
|
255
|
-
return @current_user if defined?(@current_user)
|
256
|
-
@current_user = current_user_session && current_user_session.user
|
257
|
-
end
|
258
|
-
end
|
259
|
-
```
|
260
|
-
|
261
|
-
## CSRF Protection
|
262
|
-
|
263
|
-
Because Authlogic introduces its own methods for storing user sessions, the CSRF (Cross Site Request Forgery) protection that is built into Rails will not work out of the box.
|
264
|
-
|
265
|
-
No generally applicable mitigation by the authlogic library is possible, because the instance variable you use to store a reference to the user session in `def current_user_session` will not be known to authlogic.
|
266
|
-
|
267
|
-
You will need to override `ActionController::Base#handle_unverified_request` to do something appropriate to how your app handles user sessions, e.g.:
|
268
|
-
|
269
|
-
```ruby
|
270
|
-
class ApplicationController < ActionController::Base
|
271
|
-
...
|
272
|
-
protected
|
273
|
-
|
274
|
-
def handle_unverified_request
|
275
|
-
# raise an exception
|
276
|
-
fail ActionController::InvalidAuthenticityToken
|
277
|
-
# or destroy session, redirect
|
278
|
-
if current_user_session
|
279
|
-
current_user_session.destroy
|
280
|
-
end
|
281
|
-
redirect_to root_url
|
282
|
-
end
|
283
|
-
end
|
284
|
-
```
|
285
|
-
|
286
|
-
## Testing
|
287
|
-
|
288
|
-
See [Authlogic::TestCase](https://github.com/binarylogic/authlogic/blob/master/lib/authlogic/test_case.rb)
|
289
|
-
|
290
|
-
## Tell me quickly how Authlogic works
|
291
|
-
|
292
|
-
Interested in how all of this all works? Think about an ActiveRecord model. A database connection must be established before you can use it. In the case of Authlogic, a controller connection must be established before you can use it. It uses that controller connection to modify cookies, the current session, login with HTTP basic, etc. It connects to the controller through a before filter that is automatically set in your controller which lets Authlogic know about the current controller object. Then Authlogic leverages that to do everything, it's a pretty simple design. Nothing crazy going on, Authlogic is just leveraging the tools your framework provides in the controller object.
|
293
|
-
|
294
|
-
Copyright (c) 2012 Ben Johnson of Binary Logic, released under the MIT license
|
data/Rakefile
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
|
4
|
-
Bundler.setup
|
5
|
-
|
6
|
-
require 'rake/testtask'
|
7
|
-
Rake::TestTask.new(:test) do |test|
|
8
|
-
test.libs << 'test'
|
9
|
-
test.pattern = 'test/**/*_test.rb'
|
10
|
-
test.verbose = false
|
11
|
-
|
12
|
-
# Set interpreter warning level to 1 (medium). Level 2 produces hundreds of warnings
|
13
|
-
# about uninitialized instance variables.
|
14
|
-
# TODO: Find a good way to deal with the level 2 warnings.
|
15
|
-
test.ruby_opts += ["-W1"]
|
16
|
-
end
|
17
|
-
|
18
|
-
require "rubocop/rake_task"
|
19
|
-
RuboCop::RakeTask.new
|
20
|
-
|
21
|
-
task :default => [:rubocop, :test]
|
data/authlogic.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
|
4
|
-
Gem::Specification.new do |s|
|
5
|
-
s.name = "authlogic"
|
6
|
-
s.version = "3.8.0"
|
7
|
-
s.platform = Gem::Platform::RUBY
|
8
|
-
s.authors = ["Ben Johnson"]
|
9
|
-
s.email = ["bjohnson@binarylogic.com"]
|
10
|
-
s.homepage = "http://github.com/binarylogic/authlogic"
|
11
|
-
s.summary = 'A clean, simple, and unobtrusive ruby authentication solution.'
|
12
|
-
|
13
|
-
s.license = 'MIT'
|
14
|
-
|
15
|
-
s.add_dependency 'activerecord', ['>= 3.2', '< 5.3']
|
16
|
-
s.add_dependency 'activesupport', ['>= 3.2', '< 5.3']
|
17
|
-
s.add_dependency 'request_store', '~> 1.0'
|
18
|
-
s.add_dependency 'scrypt', '>= 1.2', '< 4.0'
|
19
|
-
s.add_development_dependency 'bcrypt', '~> 3.1'
|
20
|
-
s.add_development_dependency 'timecop', '~> 0.7'
|
21
|
-
s.add_development_dependency 'rubocop', '~> 0.41.2'
|
22
|
-
|
23
|
-
s.files = `git ls-files`.split("\n")
|
24
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
26
|
-
s.require_paths = ["lib"]
|
27
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module ActsAsAuthentic
|
3
|
-
# This module is responsible for transitioning existing applications from
|
4
|
-
# the restful_authentication plugin.
|
5
|
-
module RestfulAuthentication
|
6
|
-
def self.included(klass)
|
7
|
-
klass.class_eval do
|
8
|
-
extend Config
|
9
|
-
include InstanceMethods
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
module Config
|
14
|
-
# Switching an existing app to Authlogic from restful_authentication? No
|
15
|
-
# problem, just set this true and your users won't know anything
|
16
|
-
# changed. From your database perspective nothing will change at all.
|
17
|
-
# Authlogic will continue to encrypt passwords just like
|
18
|
-
# restful_authentication, so your app won't skip a beat. Although, might
|
19
|
-
# consider transitioning your users to a newer and stronger algorithm.
|
20
|
-
# Checkout the transition_from_restful_authentication option.
|
21
|
-
#
|
22
|
-
# * <tt>Default:</tt> false
|
23
|
-
# * <tt>Accepts:</tt> Boolean
|
24
|
-
def act_like_restful_authentication(value = nil)
|
25
|
-
r = rw_config(:act_like_restful_authentication, value, false)
|
26
|
-
set_restful_authentication_config if value
|
27
|
-
r
|
28
|
-
end
|
29
|
-
alias_method :act_like_restful_authentication=, :act_like_restful_authentication
|
30
|
-
|
31
|
-
# This works just like act_like_restful_authentication except that it
|
32
|
-
# will start transitioning your users to the algorithm you specify with
|
33
|
-
# the crypto provider option. The next time they log in it will resave
|
34
|
-
# their password with the new algorithm and any new record will use the
|
35
|
-
# new algorithm as well. Make sure to update your users table if you are
|
36
|
-
# using the default migration since it will set crypted_password and
|
37
|
-
# salt columns to a maximum width of 40 characters which is not enough.
|
38
|
-
def transition_from_restful_authentication(value = nil)
|
39
|
-
r = rw_config(:transition_from_restful_authentication, value, false)
|
40
|
-
set_restful_authentication_config if value
|
41
|
-
r
|
42
|
-
end
|
43
|
-
alias_method :transition_from_restful_authentication=, :transition_from_restful_authentication
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def set_restful_authentication_config
|
48
|
-
crypto_provider_key = act_like_restful_authentication ? :crypto_provider : :transition_from_crypto_providers
|
49
|
-
self.send("#{crypto_provider_key}=", CryptoProviders::Sha1)
|
50
|
-
if !defined?(::REST_AUTH_SITE_KEY) || ::REST_AUTH_SITE_KEY.nil?
|
51
|
-
class_eval("::REST_AUTH_SITE_KEY = ''") if !defined?(::REST_AUTH_SITE_KEY)
|
52
|
-
CryptoProviders::Sha1.stretches = 1
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
module InstanceMethods
|
58
|
-
private
|
59
|
-
|
60
|
-
def act_like_restful_authentication?
|
61
|
-
self.class.act_like_restful_authentication == true
|
62
|
-
end
|
63
|
-
|
64
|
-
def transition_from_restful_authentication?
|
65
|
-
self.class.transition_from_restful_authentication == true
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module ActsAsAuthentic
|
3
|
-
# Allows you to scope everything to specific fields.
|
4
|
-
# See the Config submodule for more info.
|
5
|
-
# For information on how to scope off of a parent object see Authlogic::AuthenticatesMany
|
6
|
-
module ValidationsScope
|
7
|
-
def self.included(klass)
|
8
|
-
klass.class_eval do
|
9
|
-
extend Config
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# All configuration for the scope feature.
|
14
|
-
module Config
|
15
|
-
# Allows you to scope everything to specific field(s). Works just like validates_uniqueness_of.
|
16
|
-
# For example, let's say a user belongs to a company, and you want to scope everything to the
|
17
|
-
# company:
|
18
|
-
#
|
19
|
-
# acts_as_authentic do |c|
|
20
|
-
# c.validations_scope = :company_id
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# * <tt>Default:</tt> nil
|
24
|
-
# * <tt>Accepts:</tt> Symbol or Array of symbols
|
25
|
-
def validations_scope(value = nil)
|
26
|
-
rw_config(:validations_scope, value)
|
27
|
-
end
|
28
|
-
alias_method :validations_scope=, :validations_scope
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module AuthenticatesMany
|
3
|
-
# An object of this class is used as a proxy for the authenticates_many
|
4
|
-
# relationship. It basically allows you to "save" scope details and call
|
5
|
-
# them on an object, which allows you to do the following:
|
6
|
-
#
|
7
|
-
# @account.user_sessions.new
|
8
|
-
# @account.user_sessions.find
|
9
|
-
# # ... etc
|
10
|
-
#
|
11
|
-
# You can call all of the class level methods off of an object with a saved
|
12
|
-
# scope, so that calling the above methods scopes the user sessions down to
|
13
|
-
# that specific account. To implement this via ActiveRecord do something
|
14
|
-
# like:
|
15
|
-
#
|
16
|
-
# class User < ActiveRecord::Base
|
17
|
-
# authenticates_many :user_sessions
|
18
|
-
# end
|
19
|
-
class Association
|
20
|
-
attr_accessor :klass, :find_options, :id
|
21
|
-
|
22
|
-
# - id: Usually `nil`, but if the `scope_cookies` option is used, then
|
23
|
-
# `id` is a string like "company_123". It may seem strange to refer
|
24
|
-
# to such a string as an "id", but the naming is intentional, and
|
25
|
-
# is derived from `Authlogic::Session::Id`.
|
26
|
-
def initialize(klass, find_options, id)
|
27
|
-
self.klass = klass
|
28
|
-
self.find_options = find_options
|
29
|
-
self.id = id
|
30
|
-
end
|
31
|
-
|
32
|
-
[:create, :create!, :find, :new].each do |method|
|
33
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
34
|
-
def #{method}(*args)
|
35
|
-
klass.with_scope(scope_options) do
|
36
|
-
klass.#{method}(*args)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end_eval
|
40
|
-
end
|
41
|
-
alias_method :build, :new
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def scope_options
|
46
|
-
{ :find_options => find_options, :id => id }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
# This allows you to scope your authentication. For example, let's say all users belong
|
3
|
-
# to an account, you want to make sure only users that belong to that account can
|
4
|
-
# actually login into that account. Simple, just do:
|
5
|
-
#
|
6
|
-
# class Account < ActiveRecord::Base
|
7
|
-
# authenticates_many :user_sessions
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# Now you can scope sessions just like everything else in ActiveRecord:
|
11
|
-
#
|
12
|
-
# @account.user_sessions.new(*args)
|
13
|
-
# @account.user_sessions.create(*args)
|
14
|
-
# @account.user_sessions.find(*args)
|
15
|
-
# # ... etc
|
16
|
-
#
|
17
|
-
# Checkout the authenticates_many method for a list of options.
|
18
|
-
# You may also want to checkout Authlogic::ActsAsAuthentic::Scope to scope your model.
|
19
|
-
module AuthenticatesMany
|
20
|
-
module Base
|
21
|
-
# Allows you set essentially set up a relationship with your sessions. See module
|
22
|
-
# definition above for more details.
|
23
|
-
#
|
24
|
-
# === Options
|
25
|
-
#
|
26
|
-
# * <tt>session_class:</tt> default: "#{name}Session",
|
27
|
-
# This is the related session class.
|
28
|
-
#
|
29
|
-
# * <tt>relationship_name:</tt> default: options[:session_class].klass_name.underscore.pluralize,
|
30
|
-
# This is the name of the relationship you want to use to scope everything. For
|
31
|
-
# example an Account has many Users. There should be a relationship called :users
|
32
|
-
# that you defined with a has_many. The reason we use the relationship is so you
|
33
|
-
# don't have to repeat yourself. The relationship could have all kinds of custom
|
34
|
-
# options. So instead of repeating yourself we essentially use the scope that the
|
35
|
-
# relationship creates.
|
36
|
-
#
|
37
|
-
# * <tt>find_options:</tt> default: nil,
|
38
|
-
# By default the find options are created from the relationship you specify with
|
39
|
-
# :relationship_name. But if you want to override this and manually specify
|
40
|
-
# find_options you can do it here. Specify options just as you would in
|
41
|
-
# ActiveRecord::Base.find.
|
42
|
-
#
|
43
|
-
# * <tt>scope_cookies:</tt> default: false
|
44
|
-
# By the nature of cookies they scope themselves if you are using subdomains to
|
45
|
-
# access accounts. If you aren't using subdomains you need to have separate
|
46
|
-
# cookies for each account, assuming a user is logging into more than one account.
|
47
|
-
# Authlogic can take care of this for you by prefixing the name of the cookie and
|
48
|
-
# session with the model id. Because it affects both cookies names and session keys,
|
49
|
-
# the name `scope_cookies` is misleading. Perhaps simply `scope` or `scoped`
|
50
|
-
# would have been better.
|
51
|
-
def authenticates_many(name, options = {})
|
52
|
-
options[:session_class] ||= name.to_s.classify.constantize
|
53
|
-
options[:relationship_name] ||= options[:session_class].klass_name.underscore.pluralize
|
54
|
-
class_eval <<-"end_eval", __FILE__, __LINE__
|
55
|
-
def #{name}
|
56
|
-
find_options = #{options[:find_options].inspect} || #{options[:relationship_name]}.where(nil)
|
57
|
-
@#{name} ||= Authlogic::AuthenticatesMany::Association.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
|
58
|
-
end
|
59
|
-
end_eval
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
::ActiveRecord::Base.extend(Base) if defined?(::ActiveRecord)
|
64
|
-
end
|
65
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require "openssl"
|
2
|
-
|
3
|
-
module Authlogic
|
4
|
-
module CryptoProviders
|
5
|
-
# This encryption method is reversible if you have the supplied key. So in order to
|
6
|
-
# use this encryption method you must supply it with a key first. In an initializer,
|
7
|
-
# or before your application initializes, you should do the following:
|
8
|
-
#
|
9
|
-
# Authlogic::CryptoProviders::AES256.key = "my really long and unique key, preferably a bunch of random characters"
|
10
|
-
#
|
11
|
-
# My final comment is that this is a strong encryption method, but its main weakness
|
12
|
-
# is that it's reversible. If you do not need to reverse the hash then you should
|
13
|
-
# consider Sha512 or BCrypt instead.
|
14
|
-
#
|
15
|
-
# Keep your key in a safe place, some even say the key should be stored on a separate
|
16
|
-
# server. This won't hurt performance because the only time it will try and access the
|
17
|
-
# key on the separate server is during initialization, which only happens once. The
|
18
|
-
# reasoning behind this is if someone does compromise your server they won't have the
|
19
|
-
# key also. Basically, you don't want to store the key with the lock.
|
20
|
-
class AES256
|
21
|
-
class << self
|
22
|
-
attr_writer :key
|
23
|
-
|
24
|
-
def encrypt(*tokens)
|
25
|
-
aes.encrypt
|
26
|
-
aes.key = @key
|
27
|
-
[aes.update(tokens.join) + aes.final].pack("m").chomp
|
28
|
-
end
|
29
|
-
|
30
|
-
def matches?(crypted, *tokens)
|
31
|
-
aes.decrypt
|
32
|
-
aes.key = @key
|
33
|
-
(aes.update(crypted.unpack("m").first) + aes.final) == tokens.join
|
34
|
-
rescue OpenSSL::CipherError
|
35
|
-
false
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def aes
|
41
|
-
if @key.blank?
|
42
|
-
raise ArgumentError.new(
|
43
|
-
"You must provide a key like #{name}.key = my_key before using the #{name}"
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
@aes ||= openssl_cipher_class.new("AES-256-ECB")
|
48
|
-
end
|
49
|
-
|
50
|
-
# `::OpenSSL::Cipher::Cipher` has been deprecated since at least 2014,
|
51
|
-
# in favor of `::OpenSSL::Cipher`, but a deprecation warning was not
|
52
|
-
# printed until 2016
|
53
|
-
# (https://github.com/ruby/openssl/commit/5c20a4c014) when openssl
|
54
|
-
# became a gem. Its first release as a gem was 2.0.0, in ruby 2.4.
|
55
|
-
# (See https://github.com/ruby/ruby/blob/v2_4_0/NEWS)
|
56
|
-
def openssl_cipher_class
|
57
|
-
if ::Gem::Version.new(::OpenSSL::VERSION) < ::Gem::Version.new("2.0.0")
|
58
|
-
::OpenSSL::Cipher::Cipher
|
59
|
-
else
|
60
|
-
::OpenSSL::Cipher
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
module Authlogic
|
3
|
-
module CryptoProviders
|
4
|
-
class Wordpress
|
5
|
-
class << self
|
6
|
-
ITOA64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
7
|
-
|
8
|
-
def matches?(crypted, *tokens)
|
9
|
-
stretches = 1 << ITOA64.index(crypted[3, 1])
|
10
|
-
plain, salt = *tokens
|
11
|
-
hashed = Digest::MD5.digest(salt + plain)
|
12
|
-
stretches.times do |i|
|
13
|
-
hashed = Digest::MD5.digest(hashed + plain)
|
14
|
-
end
|
15
|
-
crypted[0, 12] + encode_64(hashed, 16) == crypted
|
16
|
-
end
|
17
|
-
|
18
|
-
def encode_64(input, length)
|
19
|
-
output = ""
|
20
|
-
i = 0
|
21
|
-
while i < length
|
22
|
-
value = input[i]
|
23
|
-
i += 1
|
24
|
-
break if value.nil?
|
25
|
-
output += ITOA64[value & 0x3f, 1]
|
26
|
-
value |= input[i] << 8 if i < length
|
27
|
-
output += ITOA64[(value >> 6) & 0x3f, 1]
|
28
|
-
|
29
|
-
i += 1
|
30
|
-
break if i >= length
|
31
|
-
value |= input[i] << 16 if i < length
|
32
|
-
output += ITOA64[(value >> 12) & 0x3f, 1]
|
33
|
-
|
34
|
-
i += 1
|
35
|
-
break if i >= length
|
36
|
-
output += ITOA64[(value >> 18) & 0x3f, 1]
|
37
|
-
end
|
38
|
-
output
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|