authlogic 2.0.11 → 2.0.12
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of authlogic might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +9 -0
- data/README.rdoc +53 -23
- data/init.rb +1 -1
- data/lib/authlogic.rb +1 -0
- data/lib/authlogic/acts_as_authentic/base.rb +1 -1
- data/lib/authlogic/acts_as_authentic/email.rb +6 -15
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +1 -1
- data/lib/authlogic/acts_as_authentic/login.rb +6 -6
- data/lib/authlogic/acts_as_authentic/password.rb +14 -14
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +2 -2
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +4 -3
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +3 -3
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +1 -1
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +1 -1
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +8 -0
- data/lib/authlogic/i18n.rb +1 -1
- data/lib/authlogic/session/brute_force_protection.rb +9 -6
- data/lib/authlogic/session/cookies.rb +3 -3
- data/lib/authlogic/session/foundation.rb +1 -1
- data/lib/authlogic/session/http_auth.rb +1 -1
- data/lib/authlogic/session/magic_columns.rb +19 -3
- data/lib/authlogic/session/magic_states.rb +1 -1
- data/lib/authlogic/session/params.rb +2 -2
- data/lib/authlogic/session/password.rb +49 -10
- data/lib/authlogic/session/session.rb +1 -1
- data/lib/authlogic/session/timeout.rb +1 -1
- data/lib/authlogic/test_case.rb +14 -0
- data/lib/authlogic/test_case/mock_request.rb +1 -1
- data/lib/authlogic/version.rb +1 -1
- data/test/acts_as_authentic_test/email_test.rb +1 -1
- data/test/acts_as_authentic_test/login_test.rb +1 -1
- data/test/acts_as_authentic_test/password_test.rb +1 -4
- data/test/session_test/password_test.rb +8 -0
- metadata +7 -5
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 2.0.12 release 2009-5-13
|
2
|
+
|
3
|
+
* Added the ability to add a last_request_update_allowed? method in your controller to pragmatically tell Authlogic when and when not to update the last_request_at field in your database. This only takes effect if the method if present.
|
4
|
+
* Extracted Authlogic's regular expressions into it's own module to allow easy use of them outside of Authlogic. See Authlogic::Regex for more info.
|
5
|
+
* Made being_brute_force_protected? true for the Authlogic::Session::BruteForceProtection module.
|
6
|
+
* Added the configuration option generalize_credentials_error_messages for the Authlogic::Session::Password module. This allows you to generalize your login / password errors messages as to not reveal was the problem was when authenticating. If enabled, when an invalid login is supplied it will use the same exact error message when an invalid password is supplied.
|
7
|
+
* Update email regular expression to use A-Z0-9 instead of /w as to not allow for diacritical marks in an email address.
|
8
|
+
* Changed config() convenience method to rw_config() to be more descriptive and less vague.
|
9
|
+
|
1
10
|
== 2.0.11 release 2009-4-25
|
2
11
|
|
3
12
|
* Fix bug when password is turned off and the SingleAccessToken module calls the after_password_set callback.
|
data/README.rdoc
CHANGED
@@ -4,33 +4,57 @@ Authlogic is a clean, simple, and unobtrusive ruby authentication solution.
|
|
4
4
|
|
5
5
|
A code example can replace a thousand words...
|
6
6
|
|
7
|
-
Authlogic 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:
|
7
|
+
Authlogic 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:
|
8
8
|
|
9
9
|
class UserSession < Authlogic::Session::Base
|
10
|
+
# specify configuration here, such as:
|
11
|
+
# logout_on_timeout true
|
12
|
+
# ...many more options in the documentation
|
10
13
|
end
|
11
14
|
|
12
|
-
Log in with any of the following.
|
15
|
+
Log in with any of the following. Create a UserSessionsController and use it just like your other models:
|
13
16
|
|
14
|
-
UserSession.create(
|
15
|
-
UserSession.
|
16
|
-
|
17
|
-
UserSession.create(
|
17
|
+
UserSession.create(:login => "bjohnson", :password => "my password", :remember_me => true)
|
18
|
+
session = UserSession.new(:login => "bjohnson", :password => "my password", :remember_me => true); session.save
|
19
|
+
UserSession.create(:openid_identifier => "identifier", :remember_me => true) # requires the authlogic-oid "add on" gem
|
20
|
+
UserSession.create(my_user_object, true) # skip authentication and log the user in directly, the true means "remember me"
|
21
|
+
|
22
|
+
The above handles the entire authentication process for you. It first authenticates, then it sets up the proper session values and cookies to persist the session. Just like you would if you rolled your own authentication solution.
|
23
|
+
|
24
|
+
You can also log out / destroy the session:
|
25
|
+
|
26
|
+
session.destroy
|
18
27
|
|
19
28
|
After a session has been created, you can persist it across requests. Thus keeping the user logged in:
|
20
29
|
|
21
30
|
session = UserSession.find
|
22
31
|
|
23
|
-
|
32
|
+
To get all of the nice authentication functionality in your model just do this:
|
24
33
|
|
25
|
-
|
34
|
+
class User < ActiveRecord::Base
|
35
|
+
acts_as_authentic do |c|
|
36
|
+
c.my_config_option = my_value
|
37
|
+
end # the configuration block is optional
|
38
|
+
end
|
39
|
+
|
40
|
+
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.
|
41
|
+
|
42
|
+
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:
|
43
|
+
|
44
|
+
User.create(params[:user])
|
45
|
+
|
46
|
+
This also updates the session when the user changes his/her password.
|
47
|
+
|
48
|
+
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.
|
26
49
|
|
27
50
|
== Helpful links
|
28
51
|
|
29
|
-
*
|
30
|
-
*
|
31
|
-
*
|
32
|
-
*
|
33
|
-
*
|
52
|
+
* <b>Documentation:</b> http://authlogic.rubyforge.org
|
53
|
+
* <b>Repository:</b> http://github.com/binarylogic/authlogic/tree/master
|
54
|
+
* <b>Railscasts Screencast:</b> http://railscasts.com/episodes/160-authlogic
|
55
|
+
* <b>Live example with OpenID "add on":</b> http://authlogicexample.binarylogic.com
|
56
|
+
* <b>Live example repository with tutorial in README:</b> http://github.com/binarylogic/authlogic_example/tree/master
|
57
|
+
* <b>Tutorial: Reset passwords with Authlogic the RESTful way:</b> http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic
|
34
58
|
* <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/18752-authlogic
|
35
59
|
* <b>Google group:</b> http://groups.google.com/group/authlogic
|
36
60
|
|
@@ -40,14 +64,18 @@ If you find a bug or a problem please post it on lighthouse. If you need help wi
|
|
40
64
|
|
41
65
|
== Authlogic "add ons"
|
42
66
|
|
43
|
-
*
|
44
|
-
*
|
67
|
+
* <b>Authlogic OpenID addon:</b> http://github.com/binarylogic/authlogic_openid
|
68
|
+
* <b>Authlogic LDAP addon:</b> http://github.com/binarylogic/authlogic_ldap
|
45
69
|
|
46
70
|
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.
|
47
71
|
|
72
|
+
== Session bugs (please read if you are having issues with logging in / out)
|
73
|
+
|
74
|
+
Apparently there is a bug with apache / passenger for v2.1.X with sessions not working properly. This is most likely your problem if you are having trouble logging in / out. This is *not* an Authlogic issue. This can be solved by updating passener or using an alternative session store solution, such as active record store.
|
75
|
+
|
48
76
|
== Documentation explanation
|
49
77
|
|
50
|
-
You can find anything you want about Authlogic in the {documentation}, all that you need to do is understand the basic design behind it.
|
78
|
+
You can find anything you want about Authlogic in the {documentation}[http://authlogic.rubyforge.org], all that you need to do is understand the basic design behind it.
|
51
79
|
|
52
80
|
That being said, there are 2 models involved during authentication. Your Authlogic model and your ActiveRecord model:
|
53
81
|
|
@@ -56,7 +84,7 @@ That being said, there are 2 models involved during authentication. Your Authlog
|
|
56
84
|
|
57
85
|
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.
|
58
86
|
|
59
|
-
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
|
87
|
+
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://authlogic.rubyforge.org].
|
60
88
|
|
61
89
|
=== Authlogic::ActsAsAuthentic sub modules
|
62
90
|
|
@@ -66,21 +94,21 @@ These modules are for the ActiveRecord side of things, the models that call acts
|
|
66
94
|
* <b>Authlogic::ActsAsAuthentic::Email</b> - Handles everything related to the email field.
|
67
95
|
* <b>Authlogic::ActsAsAuthentic::LoggedInStatus</b> - Provides handy named scopes and methods for determining if the user is logged in or out.
|
68
96
|
* <b>Authlogic::ActsAsAuthentic::Login</b> - Handles everything related to the login field.
|
69
|
-
* <b>Authlogic::ActsAsAuthentic::MagicColumns</b> - Handles everything related to the "magic" fields: login_count, failed_login_count, etc.
|
97
|
+
* <b>Authlogic::ActsAsAuthentic::MagicColumns</b> - Handles everything related to the "magic" fields: login_count, failed_login_count, last_request_at, etc.
|
70
98
|
* <b>Authlogic::ActsAsAuthentic::Password</b> - This one is important. It handles encrypting your password, salting it, etc. It also has support for transitioning password algorithms.
|
71
99
|
* <b>Authlogic::ActsAsAuthentic::PerishableToken</b> - Handles maintaining the perishable token field, also provides a class level method for finding record using the token.
|
72
100
|
* <b>Authlogic::ActsAsAuthentic::PersistenceToken</b> - Handles maintaining the persistence token. This is the token stored in cookies and sessions to persist the users session.
|
73
101
|
* <b>Authlogic::ActsAsAuthentic::RestfulAuthentication</b> - Provides configuration options to easily migrate from the restful_authentication plugin.
|
74
|
-
* <b>Authlogic::ActsAsAuthentic::SessionMaintenance</b> - Handles
|
102
|
+
* <b>Authlogic::ActsAsAuthentic::SessionMaintenance</b> - Handles automatic session maintenance. EX: a new user registers, automatically log them in. Or a user changes their password, update their session.
|
75
103
|
* <b>Authlogic::ActsAsAuthentic::SingleAccessToken</b> - Handles maintaining the single access token.
|
76
|
-
* <b>Authlogic::ActsAsAuthentic::ValidationsScope</b> - Allows you to scope validations, etc. Just like the :scope option for validates_uniqueness_of
|
104
|
+
* <b>Authlogic::ActsAsAuthentic::ValidationsScope</b> - Allows you to scope all validations, etc. Just like the :scope option for validates_uniqueness_of
|
77
105
|
|
78
106
|
=== Authlogic::Session sub modules
|
79
107
|
|
80
108
|
These modules are for the models that extend Authlogic::Session::Base.
|
81
109
|
|
82
110
|
* <b>Authlogic::Session::BruteForceProtection</b> - Disables accounts after a certain number of consecutive failed logins attempted.
|
83
|
-
* <b>Authlogic::Session::Callbacks</b> - Your tools to extend, change, or add onto Authlogic. Lets you hook in and do just about anything you want. Start here if you want to write a plugin or add
|
111
|
+
* <b>Authlogic::Session::Callbacks</b> - Your tools to extend, change, or add onto Authlogic. Lets you hook in and do just about anything you want. Start here if you want to write a plugin or add-on for Authlogic
|
84
112
|
* <b>Authlogic::Session::Cookies</b> - Authentication via cookies.
|
85
113
|
* <b>Authlogic::Session::Existence</b> - Creating, saving, and destroying objects.
|
86
114
|
* <b>Authlogic::Session::HttpAuth</b> - Authentication via basic HTTP authentication.
|
@@ -92,7 +120,7 @@ These modules are for the models that extend Authlogic::Session::Base.
|
|
92
120
|
* <b>Authlogic::Session::Persistence</b> - Persisting sessions / finding sessions.
|
93
121
|
* <b>Authlogic::Session::Session</b> - Authentication via the session, the controller session that is.
|
94
122
|
* <b>Authlogic::Session::Timeout</b> - Automatically logging out after a certain period of inactivity.
|
95
|
-
* <b>Authlogic::Session::UnauthorizedRecord</b> - Handles authentication by passing an ActiveRecord object.
|
123
|
+
* <b>Authlogic::Session::UnauthorizedRecord</b> - Handles authentication by passing an ActiveRecord object directly.
|
96
124
|
* <b>Authlogic::Session::Validation</b> - Validation / errors.
|
97
125
|
|
98
126
|
=== Miscellaneous modules
|
@@ -103,6 +131,7 @@ Miscellaneous modules that shared across the authentication process and are more
|
|
103
131
|
* <b>Authlogic::CryptoProviders</b> - Contains various encryption algorithms that Authlogic uses, allowing you to choose your encryption method.
|
104
132
|
* <b>Authlogic::I18n</b> - Acts JUST LIKE the rails I18n library, and provides internationalization to Authlogic.
|
105
133
|
* <b>Authlogic::Random</b> - A simple class to generate random tokens.
|
134
|
+
* <b>Authlogic::Regex</b> - Contains regular expressions used in Authlogic. Such as those to validate the format of the log or email.
|
106
135
|
* <b>Authlogic::TestCase</b> - Various helper methods for testing frameworks to help you test your code.
|
107
136
|
* <b>Authlogic::Version</b> - A handy class for determine the version of Authlogic in a number of ways.
|
108
137
|
|
@@ -193,7 +222,7 @@ That being said, testing your code that uses Authlogic is easy. Since everyone u
|
|
193
222
|
|
194
223
|
== Tell me quickly how Authlogic works
|
195
224
|
|
196
|
-
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.
|
225
|
+
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.
|
197
226
|
|
198
227
|
== What sets Authlogic apart and why I created it
|
199
228
|
|
@@ -203,6 +232,7 @@ What inspired me to create Authlogic was the messiness of the current authentica
|
|
203
232
|
2. <b>Easier to stay up-to-date.</b> To make my point, take a look at the commits to any other authentication solution, then look at the {commits for authlogic}[http://github.com/binarylogic/authlogic/commits/master]. How many commits could you easily start using if you already had an app using that solution? With an alternate solution, very few, if any. All of those cool new features and bug fixes are going to have be manually added or wait for your next application. Which is the main reason a generator is not suitable as an authentication solution. With Authlogic you can start using the latest code with a simple update of a gem. No generators, no mess.
|
204
233
|
3. <b>It ties everything together on the domain level.</b> Take a new user registration for example, no reason to manually log the user in, authlogic handles this for you via callbacks. The same applies to a user changing their password. Authlogic handles maintaining the session for you.
|
205
234
|
4. <b>No redundant tests.</b> Because Authlogic doesn't use generators, #1 also applies to tests. Authlogic is *thoroughly* tested for you. You don't go and test the internals of ActiveRecord in each of your apps do you? So why do the same for Authlogic? Your application tests should be for application specific code. Get rid of the noise and make your tests focused and concise, no reason to copy tests from app to app.
|
235
|
+
5. <b>Framework agnostic</b>. Authlogic can be used in *any* ruby framework you want: Rails, Merb, Sinatra, Mack, your own framework, whatever. It's not tied down to Rails. It does this by abstracting itself from these framework's controllers by using a controller adapter. Thanks to {Rack}[http://rack.rubyforge.org/], there is a defined standard for controller structure, and that's what Authlogic's abstract adapter follows. So if your controller follows the rack standards, you don't need to do anything. Any place it deviates from this is solved by a simple adapter for your framework that closes these gaps. For an example, checkout the Authlogic::ControllerAdapters::MerbAdapter.
|
206
236
|
5. <b>You are not restricted to a single session.</b> Think about Apple's me.com, where they need you to authenticate a second time before changing your billing information. Why not just create a second session for this? It works just like your initial session. Then your billing controller can require an "ultra secure" session.
|
207
237
|
6. <b>Easily extendable.</b> One of the distinct advantages of using a library is the ability to use it's API, assuming it has one. Authlogic has an *excellent* public API, meaning it can easily be extended and grow beyond the core library. Checkout the "add ons" list above to see what I mean.
|
208
238
|
|
data/init.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require "
|
1
|
+
require File.dirname(__FILE__) + "/rails/init.rb"
|
data/lib/authlogic.rb
CHANGED
@@ -3,6 +3,7 @@ require "active_support"
|
|
3
3
|
require File.dirname(__FILE__) + "/authlogic/version"
|
4
4
|
require File.dirname(__FILE__) + "/authlogic/i18n"
|
5
5
|
require File.dirname(__FILE__) + "/authlogic/random"
|
6
|
+
require File.dirname(__FILE__) + "/authlogic/regex"
|
6
7
|
|
7
8
|
require File.dirname(__FILE__) + "/authlogic/controller_adapters/abstract_adapter"
|
8
9
|
require File.dirname(__FILE__) + "/authlogic/controller_adapters/rails_adapter" if defined?(Rails)
|
@@ -68,7 +68,7 @@ module Authlogic
|
|
68
68
|
inheritable_attributes.include?(key) ? read_inheritable_attribute(key) : []
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
71
|
+
def rw_config(key, value, default_value = nil, read_value = nil)
|
72
72
|
if value == read_value
|
73
73
|
inheritable_attributes.include?(key) ? read_inheritable_attribute(key) : default_value
|
74
74
|
else
|
@@ -19,7 +19,7 @@ module Authlogic
|
|
19
19
|
# * <tt>Default:</tt> :email, if it exists
|
20
20
|
# * <tt>Accepts:</tt> Symbol
|
21
21
|
def email_field(value = nil)
|
22
|
-
|
22
|
+
rw_config(:email_field, value, first_column_to_exist(nil, :email, :email_address))
|
23
23
|
end
|
24
24
|
alias_method :email_field=, :email_field
|
25
25
|
|
@@ -28,7 +28,7 @@ module Authlogic
|
|
28
28
|
# * <tt>Default:</tt> true
|
29
29
|
# * <tt>Accepts:</tt> Boolean
|
30
30
|
def validate_email_field(value = nil)
|
31
|
-
|
31
|
+
rw_config(:validate_email_field, value, true)
|
32
32
|
end
|
33
33
|
alias_method :validate_email_field=, :validate_email_field
|
34
34
|
|
@@ -41,7 +41,7 @@ module Authlogic
|
|
41
41
|
# * <tt>Default:</tt> {:within => 6..100}
|
42
42
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
43
43
|
def validates_length_of_email_field_options(value = nil)
|
44
|
-
|
44
|
+
rw_config(:validates_length_of_email_field_options, value, {:within => 6..100})
|
45
45
|
end
|
46
46
|
alias_method :validates_length_of_email_field_options=, :validates_length_of_email_field_options
|
47
47
|
|
@@ -62,10 +62,10 @@ module Authlogic
|
|
62
62
|
# merge options into it. Checkout the convenience function merge_validates_format_of_email_field_options to merge
|
63
63
|
# options.</b>
|
64
64
|
#
|
65
|
-
# * <tt>Default:</tt> {:with =>
|
65
|
+
# * <tt>Default:</tt> {:with => Authlogic::Regex.email, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}
|
66
66
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
|
67
67
|
def validates_format_of_email_field_options(value = nil)
|
68
|
-
|
68
|
+
rw_config(:validates_format_of_email_field_options, value, {:with => Authlogic::Regex.email, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")})
|
69
69
|
end
|
70
70
|
alias_method :validates_format_of_email_field_options=, :validates_format_of_email_field_options
|
71
71
|
|
@@ -83,7 +83,7 @@ module Authlogic
|
|
83
83
|
# * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym}
|
84
84
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
|
85
85
|
def validates_uniqueness_of_email_field_options(value = nil)
|
86
|
-
|
86
|
+
rw_config(:validates_uniqueness_of_email_field_options, value, {:case_sensitive => false, :scope => validations_scope, :if => "#{email_field}_changed?".to_sym})
|
87
87
|
end
|
88
88
|
alias_method :validates_uniqueness_of_email_field_options=, :validates_uniqueness_of_email_field_options
|
89
89
|
|
@@ -91,15 +91,6 @@ module Authlogic
|
|
91
91
|
def merge_validates_uniqueness_of_email_field_options(options = {})
|
92
92
|
self.validates_uniqueness_of_email_field_options = validates_uniqueness_of_email_field_options.merge(options)
|
93
93
|
end
|
94
|
-
|
95
|
-
private
|
96
|
-
def email_regex
|
97
|
-
return @email_regex if @email_regex
|
98
|
-
email_name_regex = '[\w\.%\+\-]+'
|
99
|
-
domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
|
100
|
-
domain_tld_regex = '(?:[A-Z]{2,4}|museum|travel)'
|
101
|
-
@email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
|
102
|
-
end
|
103
94
|
end
|
104
95
|
|
105
96
|
# All methods relating to the email field
|
@@ -19,7 +19,7 @@ module Authlogic
|
|
19
19
|
# * <tt>Default:</tt> 10.minutes
|
20
20
|
# * <tt>Accepts:</tt> Fixnum
|
21
21
|
def logged_in_timeout(value = nil)
|
22
|
-
|
22
|
+
rw_config(:logged_in_timeout, (!value.nil? && value.to_i) || value, 10.minutes.to_i)
|
23
23
|
end
|
24
24
|
alias_method :logged_in_timeout=, :logged_in_timeout
|
25
25
|
end
|
@@ -16,7 +16,7 @@ module Authlogic
|
|
16
16
|
# * <tt>Default:</tt> :login or :username, if they exist
|
17
17
|
# * <tt>Accepts:</tt> Symbol
|
18
18
|
def login_field(value = nil)
|
19
|
-
|
19
|
+
rw_config(:login_field, value, first_column_to_exist(nil, :login, :username))
|
20
20
|
end
|
21
21
|
alias_method :login_field=, :login_field
|
22
22
|
|
@@ -25,7 +25,7 @@ module Authlogic
|
|
25
25
|
# * <tt>Default:</tt> true
|
26
26
|
# * <tt>Accepts:</tt> Boolean
|
27
27
|
def validate_login_field(value = nil)
|
28
|
-
|
28
|
+
rw_config(:validate_login_field, value, true)
|
29
29
|
end
|
30
30
|
alias_method :validate_login_field=, :validate_login_field
|
31
31
|
|
@@ -38,7 +38,7 @@ module Authlogic
|
|
38
38
|
# * <tt>Default:</tt> {:within => 3..100}
|
39
39
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
40
40
|
def validates_length_of_login_field_options(value = nil)
|
41
|
-
|
41
|
+
rw_config(:validates_length_of_login_field_options, value, {:within => 3..100})
|
42
42
|
end
|
43
43
|
alias_method :validates_length_of_login_field_options=, :validates_length_of_login_field_options
|
44
44
|
|
@@ -59,10 +59,10 @@ module Authlogic
|
|
59
59
|
# merge options into it. Checkout the convenience function merge_validates_format_of_login_field_options to merge
|
60
60
|
# options.</b>
|
61
61
|
#
|
62
|
-
# * <tt>Default:</tt> {:with =>
|
62
|
+
# * <tt>Default:</tt> {:with => Authlogic::Regex.login, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")}
|
63
63
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_format_of
|
64
64
|
def validates_format_of_login_field_options(value = nil)
|
65
|
-
|
65
|
+
rw_config(:validates_format_of_login_field_options, value, {:with => Authlogic::Regex.login, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")})
|
66
66
|
end
|
67
67
|
alias_method :validates_format_of_login_field_options=, :validates_format_of_login_field_options
|
68
68
|
|
@@ -80,7 +80,7 @@ module Authlogic
|
|
80
80
|
# * <tt>Default:</tt> {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym}
|
81
81
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_uniqueness_of
|
82
82
|
def validates_uniqueness_of_login_field_options(value = nil)
|
83
|
-
|
83
|
+
rw_config(:validates_uniqueness_of_login_field_options, value, {:case_sensitive => false, :scope => validations_scope, :if => "#{login_field}_changed?".to_sym})
|
84
84
|
end
|
85
85
|
alias_method :validates_uniqueness_of_login_field_options=, :validates_uniqueness_of_login_field_options
|
86
86
|
|
@@ -18,7 +18,7 @@ module Authlogic
|
|
18
18
|
# * <tt>Default:</tt> :crypted_password, :encrypted_password, :password_hash, or :pw_hash
|
19
19
|
# * <tt>Accepts:</tt> Symbol
|
20
20
|
def crypted_password_field(value = nil)
|
21
|
-
|
21
|
+
rw_config(:crypted_password_field, value, first_column_to_exist(nil, :crypted_password, :encrypted_password, :password_hash, :pw_hash))
|
22
22
|
end
|
23
23
|
alias_method :crypted_password_field=, :crypted_password_field
|
24
24
|
|
@@ -27,7 +27,7 @@ module Authlogic
|
|
27
27
|
# * <tt>Default:</tt> :password_salt, :pw_salt, :salt, nil if none exist
|
28
28
|
# * <tt>Accepts:</tt> Symbol
|
29
29
|
def password_salt_field(value = nil)
|
30
|
-
|
30
|
+
rw_config(:password_salt_field, value, first_column_to_exist(nil, :password_salt, :pw_salt, :salt))
|
31
31
|
end
|
32
32
|
alias_method :password_salt_field=, :password_salt_field
|
33
33
|
|
@@ -37,7 +37,7 @@ module Authlogic
|
|
37
37
|
# * <tt>Default:</tt> true
|
38
38
|
# * <tt>Accepts:</tt> Boolean
|
39
39
|
def require_password_confirmation(value = nil)
|
40
|
-
|
40
|
+
rw_config(:require_password_confirmation, value, true)
|
41
41
|
end
|
42
42
|
alias_method :require_password_confirmation=, :require_password_confirmation
|
43
43
|
|
@@ -53,7 +53,7 @@ module Authlogic
|
|
53
53
|
# * <tt>Default:</tt> true
|
54
54
|
# * <tt>Accepts:</tt> Boolean
|
55
55
|
def ignore_blank_passwords(value = nil)
|
56
|
-
|
56
|
+
rw_config(:ignore_blank_passwords, value, true)
|
57
57
|
end
|
58
58
|
alias_method :ignore_blank_passwords=, :ignore_blank_passwords
|
59
59
|
|
@@ -70,7 +70,7 @@ module Authlogic
|
|
70
70
|
# * <tt>Default:</tt> true
|
71
71
|
# * <tt>Accepts:</tt> Boolean
|
72
72
|
def check_passwords_against_database(value = nil)
|
73
|
-
|
73
|
+
rw_config(:check_passwords_against_database, value, true)
|
74
74
|
end
|
75
75
|
alias_method :check_passwords_against_database=, :check_passwords_against_database
|
76
76
|
|
@@ -79,7 +79,7 @@ module Authlogic
|
|
79
79
|
# * <tt>Default:</tt> true
|
80
80
|
# * <tt>Accepts:</tt> Boolean
|
81
81
|
def validate_password_field(value = nil)
|
82
|
-
|
82
|
+
rw_config(:validate_password_field, value, true)
|
83
83
|
end
|
84
84
|
alias_method :validate_password_field=, :validate_password_field
|
85
85
|
|
@@ -92,7 +92,7 @@ module Authlogic
|
|
92
92
|
# * <tt>Default:</tt> {:minimum => 4, :if => :require_password?}
|
93
93
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
94
94
|
def validates_length_of_password_field_options(value = nil)
|
95
|
-
|
95
|
+
rw_config(:validates_length_of_password_field_options, value, {:minimum => 4, :if => :require_password?})
|
96
96
|
end
|
97
97
|
alias_method :validates_length_of_password_field_options=, :validates_length_of_password_field_options
|
98
98
|
|
@@ -110,13 +110,13 @@ module Authlogic
|
|
110
110
|
# A hash of options for the validates_confirmation_of call for the password field. Allows you to change this however you want.
|
111
111
|
#
|
112
112
|
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
|
113
|
-
# merge options into it. Checkout the convenience function
|
113
|
+
# merge options into it. Checkout the convenience function merge_validates_length_of_password_field_options to merge
|
114
114
|
# options.</b>
|
115
115
|
#
|
116
|
-
# * <tt>Default:</tt> {:
|
116
|
+
# * <tt>Default:</tt> {:if => :require_password?}
|
117
117
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_confirmation_of
|
118
118
|
def validates_confirmation_of_password_field_options(value = nil)
|
119
|
-
|
119
|
+
rw_config(:validates_confirmation_of_password_field_options, value, {:if => :require_password?})
|
120
120
|
end
|
121
121
|
alias_method :validates_confirmation_of_password_field_options=, :validates_confirmation_of_password_field_options
|
122
122
|
|
@@ -128,13 +128,13 @@ module Authlogic
|
|
128
128
|
# A hash of options for the validates_length_of call for the password_confirmation field. Allows you to change this however you want.
|
129
129
|
#
|
130
130
|
# <b>Keep in mind this is ruby. I wanted to keep this as flexible as possible, so you can completely replace the hash or
|
131
|
-
# merge options into it. Checkout the convenience function
|
131
|
+
# merge options into it. Checkout the convenience function merge_validates_length_of_password_field_options to merge
|
132
132
|
# options.</b>
|
133
133
|
#
|
134
134
|
# * <tt>Default:</tt> validates_length_of_password_field_options
|
135
135
|
# * <tt>Accepts:</tt> Hash of options accepted by validates_length_of
|
136
136
|
def validates_length_of_password_confirmation_field_options(value = nil)
|
137
|
-
|
137
|
+
rw_config(:validates_length_of_password_confirmation_field_options, value, validates_length_of_password_field_options)
|
138
138
|
end
|
139
139
|
alias_method :validates_length_of_password_confirmation_field_options=, :validates_length_of_password_confirmation_field_options
|
140
140
|
|
@@ -149,7 +149,7 @@ module Authlogic
|
|
149
149
|
# * <tt>Default:</tt> CryptoProviders::Sha512
|
150
150
|
# * <tt>Accepts:</tt> Class
|
151
151
|
def crypto_provider(value = nil)
|
152
|
-
|
152
|
+
rw_config(:crypto_provider, value, CryptoProviders::Sha512)
|
153
153
|
end
|
154
154
|
alias_method :crypto_provider=, :crypto_provider
|
155
155
|
|
@@ -165,7 +165,7 @@ module Authlogic
|
|
165
165
|
# * <tt>Default:</tt> nil
|
166
166
|
# * <tt>Accepts:</tt> Class or Array
|
167
167
|
def transition_from_crypto_providers(value = nil)
|
168
|
-
|
168
|
+
rw_config(:transition_from_crypto_providers, (!value.nil? && [value].flatten.compact) || value, [])
|
169
169
|
end
|
170
170
|
alias_method :transition_from_crypto_providers=, :transition_from_crypto_providers
|
171
171
|
end
|
@@ -20,7 +20,7 @@ module Authlogic
|
|
20
20
|
# * <tt>Default:</tt> 10.minutes
|
21
21
|
# * <tt>Accepts:</tt> Fixnum
|
22
22
|
def perishable_token_valid_for(value = nil)
|
23
|
-
|
23
|
+
rw_config(:perishable_token_valid_for, (!value.nil? && value.to_i) || value, 10.minutes.to_i)
|
24
24
|
end
|
25
25
|
alias_method :perishable_token_valid_for=, :perishable_token_valid_for
|
26
26
|
|
@@ -31,7 +31,7 @@ module Authlogic
|
|
31
31
|
# * <tt>Default:</tt> false
|
32
32
|
# * <tt>Accepts:</tt> Boolean
|
33
33
|
def disable_perishable_token_maintenance(value = nil)
|
34
|
-
|
34
|
+
rw_config(:disable_perishable_token_maintenance, value, false)
|
35
35
|
end
|
36
36
|
alias_method :disable_perishable_token_maintenance=, :disable_perishable_token_maintenance
|
37
37
|
end
|
@@ -18,7 +18,7 @@ module Authlogic
|
|
18
18
|
# * <tt>Default:</tt> false
|
19
19
|
# * <tt>Accepts:</tt> Boolean
|
20
20
|
def act_like_restful_authentication(value = nil)
|
21
|
-
r =
|
21
|
+
r = rw_config(:act_like_restful_authentication, value, false)
|
22
22
|
set_restful_authentication_config if value
|
23
23
|
r
|
24
24
|
end
|
@@ -26,9 +26,10 @@ module Authlogic
|
|
26
26
|
|
27
27
|
# This works just like act_like_restful_authentication except that it will start transitioning your users to the algorithm you
|
28
28
|
# specify with the crypto provider option. The next time they log in it will resave their password with the new algorithm
|
29
|
-
# and any new record will use the new algorithm as well.
|
29
|
+
# and any new record will use the new algorithm as well. Make sure to update your users table if you are using the default
|
30
|
+
# migration since it will set crypted_password and salt columns to a maximum width of 40 characters which is not enough.
|
30
31
|
def transition_from_restful_authentication(value = nil)
|
31
|
-
r =
|
32
|
+
r = rw_config(:transition_from_restful_authentication, value, false)
|
32
33
|
set_restful_authentication_config if value
|
33
34
|
r
|
34
35
|
end
|
@@ -33,7 +33,7 @@ module Authlogic
|
|
33
33
|
# * <tt>Default:</tt> true
|
34
34
|
# * <tt>Accepts:</tt> Boolean
|
35
35
|
def maintain_sessions(value = nil)
|
36
|
-
|
36
|
+
rw_config(:maintain_sessions, value, true)
|
37
37
|
end
|
38
38
|
alias_method :maintain_sessions=, :maintain_sessions
|
39
39
|
|
@@ -44,7 +44,7 @@ module Authlogic
|
|
44
44
|
# * <tt>Default:</tt> [nil]
|
45
45
|
# * <tt>Accepts:</tt> Array
|
46
46
|
def session_ids(value = nil)
|
47
|
-
|
47
|
+
rw_config(:session_ids, value, [nil])
|
48
48
|
end
|
49
49
|
alias_method :session_ids=, :session_ids
|
50
50
|
|
@@ -54,7 +54,7 @@ module Authlogic
|
|
54
54
|
# * <tt>Accepts:</tt> Class
|
55
55
|
def session_class(value = nil)
|
56
56
|
const = "#{base_class.name}Session".constantize rescue nil
|
57
|
-
|
57
|
+
rw_config(:session_class, value, const)
|
58
58
|
end
|
59
59
|
alias_method :session_class=, :session_class
|
60
60
|
end
|
@@ -20,7 +20,7 @@ module Authlogic
|
|
20
20
|
# * <tt>Default:</tt> false
|
21
21
|
# * <tt>Accepts:</tt> Boolean
|
22
22
|
def change_single_access_token_with_password(value = nil)
|
23
|
-
|
23
|
+
rw_config(:change_single_access_token_with_password, value, false)
|
24
24
|
end
|
25
25
|
alias_method :change_single_access_token_with_password=, :change_single_access_token_with_password
|
26
26
|
end
|
@@ -23,7 +23,7 @@ module Authlogic
|
|
23
23
|
# * <tt>Default:</tt> nil
|
24
24
|
# * <tt>Accepts:</tt> Symbol or Array of symbols
|
25
25
|
def validations_scope(value = nil)
|
26
|
-
|
26
|
+
rw_config(:validations_scope, value)
|
27
27
|
end
|
28
28
|
alias_method :validations_scope=, :validations_scope
|
29
29
|
end
|
@@ -50,6 +50,14 @@ module Authlogic
|
|
50
50
|
controller.send(:single_access_allowed?)
|
51
51
|
end
|
52
52
|
|
53
|
+
def responds_to_last_request_update_allowed?
|
54
|
+
controller.respond_to?(:last_request_update_allowed?, true)
|
55
|
+
end
|
56
|
+
|
57
|
+
def last_request_update_allowed?
|
58
|
+
controller.send(:last_request_update_allowed?)
|
59
|
+
end
|
60
|
+
|
53
61
|
private
|
54
62
|
def method_missing(id, *args, &block)
|
55
63
|
controller.send(id, *args, &block)
|
data/lib/authlogic/i18n.rb
CHANGED
@@ -29,7 +29,7 @@ module Authlogic
|
|
29
29
|
# authlogic:
|
30
30
|
# error_messages:
|
31
31
|
# login_blank: can not be blank
|
32
|
-
# login_not_found:
|
32
|
+
# login_not_found: is not valid
|
33
33
|
# login_invalid: should use only letters, numbers, spaces, and .-_@ please.
|
34
34
|
# consecutive_failed_logins_limit_exceeded: Consecutive failed logins limit exceeded, account is disabled.
|
35
35
|
# email_invalid: should look like an email address.
|
@@ -37,7 +37,7 @@ module Authlogic
|
|
37
37
|
# * <tt>Default:</tt> 50
|
38
38
|
# * <tt>Accepts:</tt> Integer, set to 0 to disable
|
39
39
|
def consecutive_failed_logins_limit(value = nil)
|
40
|
-
|
40
|
+
rw_config(:consecutive_failed_logins_limit, value, 50)
|
41
41
|
end
|
42
42
|
alias_method :consecutive_failed_logins_limit=, :consecutive_failed_logins_limit
|
43
43
|
|
@@ -46,23 +46,26 @@ module Authlogic
|
|
46
46
|
# * <tt>Default:</tt> 2.hours
|
47
47
|
# * <tt>Accepts:</tt> Fixnum, set to 0 for permanent ban
|
48
48
|
def failed_login_ban_for(value = nil)
|
49
|
-
|
49
|
+
rw_config(:failed_login_ban_for, (!value.nil? && value) || value, 2.hours.to_i)
|
50
50
|
end
|
51
51
|
alias_method :failed_login_ban_for=, :failed_login_ban_for
|
52
52
|
end
|
53
53
|
|
54
54
|
# The methods available for an Authlogic::Session::Base object that make up the brute force protection feature.
|
55
55
|
module InstanceMethods
|
56
|
+
# Returns true when the consecutive_failed_logins_limit has been exceeded and is being temporarily banned.
|
57
|
+
# Notice the word temporary, the user will not be permanently banned unless you choose to do so with configuration.
|
58
|
+
# By default they will be banned for 2 hours. During that 2 hour period this method will return true.
|
59
|
+
def being_brute_force_protected?
|
60
|
+
exceeded_failed_logins_limit? && (failed_login_ban_for <= 0 || (attempted_record.respond_to?(:updated_at) && attempted_record.updated_at >= failed_login_ban_for.seconds.ago))
|
61
|
+
end
|
62
|
+
|
56
63
|
private
|
57
64
|
def exceeded_failed_logins_limit?
|
58
65
|
!attempted_record.nil? && attempted_record.respond_to?(:failed_login_count) && consecutive_failed_logins_limit > 0 &&
|
59
66
|
attempted_record.failed_login_count && attempted_record.failed_login_count >= consecutive_failed_logins_limit
|
60
67
|
end
|
61
68
|
|
62
|
-
def being_brute_force_protected?
|
63
|
-
exceeded_failed_logins_limit? && (failed_login_ban_for <= 0 || (attempted_record.respond_to?(:updated_at) && attempted_record.updated_at >= failed_login_ban_for.seconds.ago))
|
64
|
-
end
|
65
|
-
|
66
69
|
def reset_failed_login_count?
|
67
70
|
exceeded_failed_logins_limit? && !being_brute_force_protected?
|
68
71
|
end
|
@@ -26,7 +26,7 @@ module Authlogic
|
|
26
26
|
# * <tt>Default:</tt> "#{klass_name.underscore}_credentials"
|
27
27
|
# * <tt>Accepts:</tt> String
|
28
28
|
def cookie_key(value = nil)
|
29
|
-
|
29
|
+
rw_config(:cookie_key, value, "#{klass_name.underscore}_credentials")
|
30
30
|
end
|
31
31
|
alias_method :cookie_key=, :cookie_key
|
32
32
|
|
@@ -35,7 +35,7 @@ module Authlogic
|
|
35
35
|
# * <tt>Default:</tt> false
|
36
36
|
# * <tt>Accepts:</tt> Boolean
|
37
37
|
def remember_me(value = nil)
|
38
|
-
|
38
|
+
rw_config(:remember_me, value, false)
|
39
39
|
end
|
40
40
|
alias_method :remember_me=, :remember_me
|
41
41
|
|
@@ -44,7 +44,7 @@ module Authlogic
|
|
44
44
|
# * <tt>Default:</tt> 3.months
|
45
45
|
# * <tt>Accepts:</tt> Integer, length of time in seconds, such as 60 or 3.months
|
46
46
|
def remember_me_for(value = :_read)
|
47
|
-
|
47
|
+
rw_config(:remember_me_for, value, 3.months, :_read)
|
48
48
|
end
|
49
49
|
alias_method :remember_me_for=, :remember_me_for
|
50
50
|
end
|
@@ -13,7 +13,7 @@ module Authlogic
|
|
13
13
|
|
14
14
|
module ClassMethods
|
15
15
|
private
|
16
|
-
def
|
16
|
+
def rw_config(key, value, default_value = nil, read_value = nil)
|
17
17
|
if value == read_value
|
18
18
|
return read_inheritable_attribute(key) if inheritable_attributes.include?(key)
|
19
19
|
write_inheritable_attribute(key, default_value)
|
@@ -25,7 +25,7 @@ module Authlogic
|
|
25
25
|
# * <tt>Default:</tt> true
|
26
26
|
# * <tt>Accepts:</tt> Boolean
|
27
27
|
def allow_http_basic_auth(value = nil)
|
28
|
-
|
28
|
+
rw_config(:allow_http_basic_auth, value, true)
|
29
29
|
end
|
30
30
|
alias_method :allow_http_basic_auth=, :allow_http_basic_auth
|
31
31
|
end
|
@@ -31,7 +31,7 @@ module Authlogic
|
|
31
31
|
# * <tt>Default:</tt> 0
|
32
32
|
# * <tt>Accepts:</tt> integer representing time in seconds
|
33
33
|
def last_request_at_threshold(value = nil)
|
34
|
-
|
34
|
+
rw_config(:last_request_at_threshold, value, 0)
|
35
35
|
end
|
36
36
|
alias_method :last_request_at_threshold=, :last_request_at_threshold
|
37
37
|
end
|
@@ -61,8 +61,24 @@ module Authlogic
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
# This method lets authlogic know whether it should allow the last_request_at field to be updated
|
65
|
+
# with the current time (Time.now). One thing to note here is that it also checks for the existence of a
|
66
|
+
# last_request_update_allowed? method in your controller. This allows you to control this method pragmatically
|
67
|
+
# in your controller.
|
68
|
+
#
|
69
|
+
# For example, what if you had a javascript function that polled the server updating how much time is left in their
|
70
|
+
# session before it times out. Obviously you would want to ignore this request, because then the user would never time out.
|
71
|
+
# So you can do something like this in your controller:
|
72
|
+
#
|
73
|
+
# def last_request_update_allowed?
|
74
|
+
# action_name =! "update_session_time_left"
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# You can do whatever you want with that method.
|
78
|
+
def set_last_request_at? # :doc:
|
79
|
+
return false if !record || !klass.column_names.include?("last_request_at")
|
80
|
+
return controller.last_request_update_allowed? if controller.responds_to_last_request_update_allowed?
|
81
|
+
record.last_request_at.blank? || last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
|
66
82
|
end
|
67
83
|
|
68
84
|
def set_last_request_at
|
@@ -30,7 +30,7 @@ module Authlogic
|
|
30
30
|
# * <tt>Default:</tt> false
|
31
31
|
# * <tt>Accepts:</tt> Boolean
|
32
32
|
def disable_magic_states(value = nil)
|
33
|
-
|
33
|
+
rw_config(:disable_magic_states, value, false)
|
34
34
|
end
|
35
35
|
alias_method :disable_magic_states=, :disable_magic_states
|
36
36
|
end
|
@@ -43,7 +43,7 @@ module Authlogic
|
|
43
43
|
# * <tt>Default:</tt> cookie_key
|
44
44
|
# * <tt>Accepts:</tt> String
|
45
45
|
def params_key(value = nil)
|
46
|
-
|
46
|
+
rw_config(:params_key, value, cookie_key)
|
47
47
|
end
|
48
48
|
alias_method :params_key=, :params_key
|
49
49
|
|
@@ -53,7 +53,7 @@ module Authlogic
|
|
53
53
|
# * <tt>Default:</tt> ["application/rss+xml", "application/atom+xml"]
|
54
54
|
# * <tt>Accepts:</tt> String of a request type, or :all or :any to allow single access authentication for any and all request types
|
55
55
|
def single_access_allowed_request_types(value = nil)
|
56
|
-
|
56
|
+
rw_config(:single_access_allowed_request_types, value, ["application/rss+xml", "application/atom+xml"])
|
57
57
|
end
|
58
58
|
alias_method :single_access_allowed_request_types=, :single_access_allowed_request_types
|
59
59
|
end
|
@@ -29,16 +29,45 @@ module Authlogic
|
|
29
29
|
# end
|
30
30
|
# end
|
31
31
|
#
|
32
|
-
# Now just
|
32
|
+
# Now just specify the name of this method for this configuration option and you are all set. You can do anything you want here. Maybe you allow users to have multiple logins
|
33
33
|
# and you want to search a has_many relationship, etc. The sky is the limit.
|
34
34
|
#
|
35
35
|
# * <tt>Default:</tt> "find_by_smart_case_login_field"
|
36
36
|
# * <tt>Accepts:</tt> Symbol or String
|
37
37
|
def find_by_login_method(value = nil)
|
38
|
-
|
38
|
+
rw_config(:find_by_login_method, value, "find_by_smart_case_login_field")
|
39
39
|
end
|
40
40
|
alias_method :find_by_login_method=, :find_by_login_method
|
41
41
|
|
42
|
+
# The text used to identify credentials (username/password) combination when a bad login attempt occurs.
|
43
|
+
# When you show error messages for a bad login, it's considered good security practice to hide which field
|
44
|
+
# the user has entered incorrectly (the login field or the password field). For a full explanation, see
|
45
|
+
# http://www.gnucitizen.org/blog/username-enumeration-vulnerabilities/
|
46
|
+
#
|
47
|
+
# Example of use:
|
48
|
+
#
|
49
|
+
# class UserSession < Authlogic::Session::Base
|
50
|
+
# generalize_credentials_error_messages true
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# This would make the error message for bad logins and bad passwords look identical:
|
54
|
+
#
|
55
|
+
# Login/Password combination is not valid
|
56
|
+
#
|
57
|
+
# The downside to enabling this is that is can be too vague for a user that has a hard time remembering
|
58
|
+
# their username and password combinations. It also disables the ability to to highlight the field
|
59
|
+
# with the error when you use form_for.
|
60
|
+
#
|
61
|
+
# If you are developing an app where security is an extreme priority (such as a financial application),
|
62
|
+
# then you should enable this. Otherwise, leaving this off is fine.
|
63
|
+
#
|
64
|
+
# * <tt>Default</tt> false
|
65
|
+
# * <tt>Accepts:</tt> Boolean
|
66
|
+
def generalize_credentials_error_messages(value = nil)
|
67
|
+
rw_config(:generalize_credentials_error_messages, value, false)
|
68
|
+
end
|
69
|
+
alias_method :generalize_credentials_error_messages=, :generalize_credentials_error_messages
|
70
|
+
|
42
71
|
# The name of the method you want Authlogic to create for storing the login / username. Keep in mind this is just for your
|
43
72
|
# Authlogic::Session, if you want it can be something completely different than the field in your model. So if you wanted people to
|
44
73
|
# login with a field called "login" and then find users by email this is compeltely doable. See the find_by_login_method configuration
|
@@ -47,7 +76,7 @@ module Authlogic
|
|
47
76
|
# * <tt>Default:</tt> klass.login_field || klass.email_field
|
48
77
|
# * <tt>Accepts:</tt> Symbol or String
|
49
78
|
def login_field(value = nil)
|
50
|
-
|
79
|
+
rw_config(:login_field, value, klass.login_field || klass.email_field)
|
51
80
|
end
|
52
81
|
alias_method :login_field=, :login_field
|
53
82
|
|
@@ -56,7 +85,7 @@ module Authlogic
|
|
56
85
|
# * <tt>Default:</tt> :password
|
57
86
|
# * <tt>Accepts:</tt> Symbol or String
|
58
87
|
def password_field(value = nil)
|
59
|
-
|
88
|
+
rw_config(:password_field, value, login_field && :password)
|
60
89
|
end
|
61
90
|
alias_method :password_field=, :password_field
|
62
91
|
|
@@ -65,7 +94,7 @@ module Authlogic
|
|
65
94
|
# * <tt>Default:</tt> "valid_#{password_field}?"
|
66
95
|
# * <tt>Accepts:</tt> Symbol or String
|
67
96
|
def verify_password_method(value = nil)
|
68
|
-
|
97
|
+
rw_config(:verify_password_method, value, "valid_#{password_field}?")
|
69
98
|
end
|
70
99
|
alias_method :verify_password_method=, :verify_password_method
|
71
100
|
end
|
@@ -85,7 +114,7 @@ module Authlogic
|
|
85
114
|
|
86
115
|
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
87
116
|
private
|
88
|
-
# The password should not be accessible publicly. This way forms using form_for don't fill the password with the attempted password.
|
117
|
+
# The password should not be accessible publicly. This way forms using form_for don't fill the password with the attempted password. To prevent this we just create this method that is private.
|
89
118
|
def protected_#{password_field}
|
90
119
|
@#{password_field}
|
91
120
|
end
|
@@ -98,6 +127,7 @@ module Authlogic
|
|
98
127
|
super
|
99
128
|
end
|
100
129
|
|
130
|
+
# Returns the login_field / password_field credentials combination in hash form.
|
101
131
|
def credentials
|
102
132
|
if authenticating_with_password?
|
103
133
|
details = {}
|
@@ -109,6 +139,7 @@ module Authlogic
|
|
109
139
|
end
|
110
140
|
end
|
111
141
|
|
142
|
+
# Accepts the login_field / password_field credentials combination in hash form.
|
112
143
|
def credentials=(value)
|
113
144
|
super
|
114
145
|
values = value.is_a?(Array) ? value : [value]
|
@@ -126,19 +157,19 @@ module Authlogic
|
|
126
157
|
end
|
127
158
|
|
128
159
|
def validate_by_password
|
129
|
-
errors.add(login_field, I18n.t('error_messages.login_blank', :default => "
|
130
|
-
errors.add(password_field, I18n.t('error_messages.password_blank', :default => "
|
160
|
+
errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank")) if send(login_field).blank?
|
161
|
+
errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank")) if send("protected_#{password_field}").blank?
|
131
162
|
return if errors.count > 0
|
132
163
|
|
133
164
|
self.attempted_record = search_for_record(find_by_login_method, send(login_field))
|
134
165
|
|
135
166
|
if attempted_record.blank?
|
136
|
-
errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "
|
167
|
+
generalize_credentials_error_messages? ? add_general_credentials_error : errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
|
137
168
|
return
|
138
169
|
end
|
139
170
|
|
140
171
|
if !attempted_record.send(verify_password_method, send("protected_#{password_field}"))
|
141
|
-
errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
|
172
|
+
generalize_credentials_error_messages? ? add_general_credentials_error : errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
|
142
173
|
return
|
143
174
|
end
|
144
175
|
end
|
@@ -151,6 +182,14 @@ module Authlogic
|
|
151
182
|
self.class.login_field
|
152
183
|
end
|
153
184
|
|
185
|
+
def add_general_credentials_error
|
186
|
+
errors.add_to_base(I18n.t('error_messages.general_credentials_error', :default => "#{login_field.to_s.humanize}/Password combination is not valid"))
|
187
|
+
end
|
188
|
+
|
189
|
+
def generalize_credentials_error_messages?
|
190
|
+
self.class.generalize_credentials_error_messages == true
|
191
|
+
end
|
192
|
+
|
154
193
|
def password_field
|
155
194
|
self.class.password_field
|
156
195
|
end
|
@@ -20,7 +20,7 @@ module Authlogic
|
|
20
20
|
# * <tt>Default:</tt> cookie_key
|
21
21
|
# * <tt>Accepts:</tt> Symbol or String
|
22
22
|
def session_key(value = nil)
|
23
|
-
|
23
|
+
rw_config(:session_key, value, cookie_key)
|
24
24
|
end
|
25
25
|
alias_method :session_key=, :session_key
|
26
26
|
end
|
@@ -48,7 +48,7 @@ module Authlogic
|
|
48
48
|
# * <tt>Default:</tt> false
|
49
49
|
# * <tt>Accepts:</tt> Boolean
|
50
50
|
def logout_on_timeout(value = nil)
|
51
|
-
|
51
|
+
rw_config(:logout_on_timeout, value, false)
|
52
52
|
end
|
53
53
|
alias_method :logout_on_timeout=, :logout_on_timeout
|
54
54
|
end
|
data/lib/authlogic/test_case.rb
CHANGED
@@ -35,6 +35,20 @@ module Authlogic
|
|
35
35
|
# Authlogic::Session::Activation::NotActivatedError any time you try to instantiate an object without a "connection".
|
36
36
|
# So before you do anything with Authlogic, you need to activate / connect Authlogic. Let's walk through how to do this in tests:
|
37
37
|
#
|
38
|
+
# === Fixtures / Factories
|
39
|
+
#
|
40
|
+
# Creating users via fixtures / factories is easy. Here's an example of a fixture:
|
41
|
+
#
|
42
|
+
# ben:
|
43
|
+
# email: whatever@whatever.com
|
44
|
+
# password_salt: <%= salt = Authlogic::Random.hex_token %>
|
45
|
+
# crypted_password: <%= Authlogic::CryptoProviders::Sha512.encrypt("benrocks" + salt) %>
|
46
|
+
# persistence_token: <%= Authlogic::Random.hex_token %>
|
47
|
+
# single_access_token: <%= Authlogic::Random.friendly_token %>
|
48
|
+
# perishable_token: <%= Authlogic::Random.friendly_token %>
|
49
|
+
#
|
50
|
+
# Notice the crypted_password value. Just supplement that with whatever crypto provider you are using, if you are not using the default.
|
51
|
+
#
|
38
52
|
# === Functional tests
|
39
53
|
#
|
40
54
|
# Activating Authlogic isn't a problem here, because making a request will activate Authlogic for you. The problem is
|
data/lib/authlogic/version.rb
CHANGED
@@ -33,7 +33,7 @@ module ActsAsAuthenticTest
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_validates_format_of_email_field_options_config
|
36
|
-
default = {:with =>
|
36
|
+
default = {:with => Authlogic::Regex.email, :message => I18n.t('error_messages.email_invalid', :default => "should look like an email address.")}
|
37
37
|
assert_equal default, User.validates_format_of_email_field_options
|
38
38
|
assert_equal default, Employee.validates_format_of_email_field_options
|
39
39
|
|
@@ -33,7 +33,7 @@ module ActsAsAuthenticTest
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_validates_format_of_login_field_options_config
|
36
|
-
default = {:with => /\A\w[\w
|
36
|
+
default = {:with => /\A\w[\w\.+\-_@ ]+\z/, :message => I18n.t('error_messages.login_invalid', :default => "should use only letters, numbers, spaces, and .-_@ please.")}
|
37
37
|
assert_equal default, User.validates_format_of_login_field_options
|
38
38
|
assert_equal default, Employee.validates_format_of_login_field_options
|
39
39
|
|
@@ -62,7 +62,7 @@ module ActsAsAuthenticTest
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def test_validates_confirmation_of_password_field_options_config
|
65
|
-
default = {:
|
65
|
+
default = {:if => :require_password?}
|
66
66
|
assert_equal default, User.validates_confirmation_of_password_field_options
|
67
67
|
assert_equal default, Employee.validates_confirmation_of_password_field_options
|
68
68
|
|
@@ -129,9 +129,6 @@ module ActsAsAuthenticTest
|
|
129
129
|
def test_validates_length_of_password_confirmation
|
130
130
|
u = User.new
|
131
131
|
|
132
|
-
assert !u.valid?
|
133
|
-
assert u.errors.on(:password_confirmation)
|
134
|
-
|
135
132
|
u.password = "test"
|
136
133
|
u.password_confirmation = ""
|
137
134
|
assert !u.valid?
|
@@ -19,6 +19,14 @@ module SessionTest
|
|
19
19
|
assert_equal "valid_password?", UserSession.verify_password_method
|
20
20
|
end
|
21
21
|
|
22
|
+
def test_generalize_credentials_error_messages
|
23
|
+
UserSession.generalize_credentials_error_messages = true
|
24
|
+
assert UserSession.generalize_credentials_error_messages
|
25
|
+
|
26
|
+
UserSession.generalize_credentials_error_messages false
|
27
|
+
assert !UserSession.generalize_credentials_error_messages
|
28
|
+
end
|
29
|
+
|
22
30
|
def test_login_field
|
23
31
|
UserSession.configured_password_methods = false
|
24
32
|
UserSession.login_field = :saweet
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authlogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson of Binary Logic
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-05-13 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.12.
|
33
|
+
version: 1.12.2
|
34
34
|
version:
|
35
35
|
description: A clean, simple, and unobtrusive ruby authentication solution.
|
36
36
|
email: bjohnson@binarylogic.com
|
@@ -161,6 +161,8 @@ files:
|
|
161
161
|
- test/test_helper.rb
|
162
162
|
has_rdoc: true
|
163
163
|
homepage: http://github.com/binarylogic/authlogic
|
164
|
+
licenses: []
|
165
|
+
|
164
166
|
post_install_message:
|
165
167
|
rdoc_options:
|
166
168
|
- --main
|
@@ -182,9 +184,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
184
|
requirements: []
|
183
185
|
|
184
186
|
rubyforge_project: authlogic
|
185
|
-
rubygems_version: 1.3.
|
187
|
+
rubygems_version: 1.3.3
|
186
188
|
signing_key:
|
187
|
-
specification_version:
|
189
|
+
specification_version: 3
|
188
190
|
summary: A clean, simple, and unobtrusive ruby authentication solution.
|
189
191
|
test_files:
|
190
192
|
- test/authenticates_many_test.rb
|