devise_security_extension 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e458bf8839d5f8355da287f265f4a2285c2c20ef
4
+ data.tar.gz: 363210e0cc2ae02caaf74f89727557cf971efd7d
5
+ SHA512:
6
+ metadata.gz: a5dedc51cc6c3625152d3b2836103c5f2d4581322402be436e8aae13dce95818d04c46d9900c1a9a4c3b5a987b140f0719df6ce9d477237097f107e6674fc65c
7
+ data.tar.gz: 98219b8cd14bc7265cc63a2d52cfba5bdaea28a17b9854999d7fc4b0d44ce2e127f572401cbc07b7060d2d519834fca5dfe1d76fa2973db7f9fcc88b8fea6600
data/Gemfile CHANGED
@@ -10,6 +10,6 @@ group :development do
10
10
  gem "rails_email_validator"
11
11
  gem "easy_captcha"
12
12
  gem "bundler", ">= 1.0.0"
13
- gem "jeweler", "~> 1.8.4"
13
+ gem "jeweler", "~> 2.0.1"
14
14
  # gem "rcov", ">= 0"
15
15
  end
@@ -1,43 +1,45 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- actionmailer (3.2.9)
5
- actionpack (= 3.2.9)
6
- mail (~> 2.4.4)
7
- actionpack (3.2.9)
8
- activemodel (= 3.2.9)
9
- activesupport (= 3.2.9)
10
- builder (~> 3.0.0)
4
+ actionmailer (4.0.2)
5
+ actionpack (= 4.0.2)
6
+ mail (~> 2.5.4)
7
+ actionpack (4.0.2)
8
+ activesupport (= 4.0.2)
9
+ builder (~> 3.1.0)
11
10
  erubis (~> 2.7.0)
12
- journey (~> 1.0.4)
13
- rack (~> 1.4.0)
14
- rack-cache (~> 1.2)
15
- rack-test (~> 0.6.1)
16
- sprockets (~> 2.2.1)
17
- activemodel (3.2.9)
18
- activesupport (= 3.2.9)
19
- builder (~> 3.0.0)
20
- activerecord (3.2.9)
21
- activemodel (= 3.2.9)
22
- activesupport (= 3.2.9)
23
- arel (~> 3.0.2)
24
- tzinfo (~> 0.3.29)
25
- activeresource (3.2.9)
26
- activemodel (= 3.2.9)
27
- activesupport (= 3.2.9)
28
- activesupport (3.2.9)
29
- i18n (~> 0.6)
30
- multi_json (~> 1.0)
31
- arel (3.0.2)
32
- bcrypt-ruby (3.0.1)
33
- builder (3.0.4)
34
- devise (2.1.2)
11
+ rack (~> 1.5.2)
12
+ rack-test (~> 0.6.2)
13
+ activemodel (4.0.2)
14
+ activesupport (= 4.0.2)
15
+ builder (~> 3.1.0)
16
+ activerecord (4.0.2)
17
+ activemodel (= 4.0.2)
18
+ activerecord-deprecated_finders (~> 1.0.2)
19
+ activesupport (= 4.0.2)
20
+ arel (~> 4.0.0)
21
+ activerecord-deprecated_finders (1.0.3)
22
+ activesupport (4.0.2)
23
+ i18n (~> 0.6, >= 0.6.4)
24
+ minitest (~> 4.2)
25
+ multi_json (~> 1.3)
26
+ thread_safe (~> 0.1)
27
+ tzinfo (~> 0.3.37)
28
+ addressable (2.3.5)
29
+ arel (4.0.1)
30
+ atomic (1.1.14)
31
+ bcrypt-ruby (3.1.2)
32
+ builder (3.1.4)
33
+ descendants_tracker (0.0.3)
34
+ devise (3.2.2)
35
35
  bcrypt-ruby (~> 3.0)
36
36
  orm_adapter (~> 0.1)
37
- railties (~> 3.1)
38
- warden (~> 1.2.1)
39
- diff-lcs (1.1.3)
40
- easy_captcha (0.5.1)
37
+ railties (>= 3.2.6, < 5)
38
+ thread_safe (~> 0.1)
39
+ warden (~> 1.2.3)
40
+ diff-lcs (1.2.5)
41
+ docile (1.1.2)
42
+ easy_captcha (0.6.4)
41
43
  bundler (>= 1.1.0)
42
44
  rails (>= 3.0.0)
43
45
  rmagick (>= 2.13.1)
@@ -45,81 +47,111 @@ GEM
45
47
  simplecov (>= 0.3.8)
46
48
  yard (>= 0.7.0)
47
49
  erubis (2.7.0)
48
- git (1.2.5)
49
- hike (1.2.1)
50
- i18n (0.6.1)
51
- jeweler (1.8.4)
52
- bundler (~> 1.0)
50
+ faraday (0.9.0)
51
+ multipart-post (>= 1.2, < 3)
52
+ git (1.2.6)
53
+ github_api (0.11.1)
54
+ addressable (~> 2.3)
55
+ descendants_tracker (~> 0.0.1)
56
+ faraday (~> 0.8, < 0.10)
57
+ hashie (>= 1.2)
58
+ multi_json (>= 1.7.5, < 2.0)
59
+ nokogiri (~> 1.6.0)
60
+ oauth2
61
+ hashie (2.0.5)
62
+ highline (1.6.20)
63
+ hike (1.2.3)
64
+ i18n (0.6.9)
65
+ jeweler (2.0.1)
66
+ builder
67
+ bundler (>= 1.0)
53
68
  git (>= 1.2.5)
69
+ github_api
70
+ highline (>= 1.6.15)
71
+ nokogiri (>= 1.5.10)
54
72
  rake
55
73
  rdoc
56
- journey (1.0.4)
57
- json (1.7.5)
58
- mail (2.4.4)
59
- i18n (>= 0.4.0)
74
+ json (1.8.1)
75
+ jwt (0.1.11)
76
+ multi_json (>= 1.5)
77
+ mail (2.5.4)
60
78
  mime-types (~> 1.16)
61
79
  treetop (~> 1.4.8)
62
- mime-types (1.19)
63
- multi_json (1.3.7)
64
- orm_adapter (0.4.0)
80
+ mime-types (1.25.1)
81
+ mini_portile (0.5.2)
82
+ minitest (4.7.5)
83
+ multi_json (1.8.4)
84
+ multi_xml (0.5.5)
85
+ multipart-post (2.0.0)
86
+ nokogiri (1.6.1)
87
+ mini_portile (~> 0.5.0)
88
+ oauth2 (0.9.3)
89
+ faraday (>= 0.8, < 0.10)
90
+ jwt (~> 0.1.8)
91
+ multi_json (~> 1.3)
92
+ multi_xml (~> 0.5)
93
+ rack (~> 1.2)
94
+ orm_adapter (0.5.0)
65
95
  polyglot (0.3.3)
66
- rack (1.4.1)
67
- rack-cache (1.2)
68
- rack (>= 0.4)
69
- rack-ssl (1.3.2)
70
- rack
96
+ rack (1.5.2)
71
97
  rack-test (0.6.2)
72
98
  rack (>= 1.0)
73
- rails (3.2.9)
74
- actionmailer (= 3.2.9)
75
- actionpack (= 3.2.9)
76
- activerecord (= 3.2.9)
77
- activeresource (= 3.2.9)
78
- activesupport (= 3.2.9)
79
- bundler (~> 1.0)
80
- railties (= 3.2.9)
99
+ rails (4.0.2)
100
+ actionmailer (= 4.0.2)
101
+ actionpack (= 4.0.2)
102
+ activerecord (= 4.0.2)
103
+ activesupport (= 4.0.2)
104
+ bundler (>= 1.3.0, < 2.0)
105
+ railties (= 4.0.2)
106
+ sprockets-rails (~> 2.0.0)
81
107
  rails_email_validator (0.1.4)
82
108
  activemodel (>= 3.0.0)
83
- railties (3.2.9)
84
- actionpack (= 3.2.9)
85
- activesupport (= 3.2.9)
86
- rack-ssl (~> 1.3.2)
109
+ railties (4.0.2)
110
+ actionpack (= 4.0.2)
111
+ activesupport (= 4.0.2)
87
112
  rake (>= 0.8.7)
88
- rdoc (~> 3.4)
89
- thor (>= 0.14.6, < 2.0)
90
- rake (10.0.2)
91
- rdoc (3.12)
113
+ thor (>= 0.18.1, < 2.0)
114
+ rake (10.1.1)
115
+ rdoc (4.1.1)
92
116
  json (~> 1.4)
93
- rmagick (2.13.1)
94
- rspec-core (2.12.0)
95
- rspec-expectations (2.12.0)
96
- diff-lcs (~> 1.1.3)
97
- rspec-mocks (2.12.0)
98
- rspec-rails (2.12.0)
117
+ rmagick (2.13.2)
118
+ rspec-core (2.14.7)
119
+ rspec-expectations (2.14.4)
120
+ diff-lcs (>= 1.1.3, < 2.0)
121
+ rspec-mocks (2.14.4)
122
+ rspec-rails (2.14.1)
99
123
  actionpack (>= 3.0)
124
+ activemodel (>= 3.0)
100
125
  activesupport (>= 3.0)
101
126
  railties (>= 3.0)
102
- rspec-core (~> 2.12.0)
103
- rspec-expectations (~> 2.12.0)
104
- rspec-mocks (~> 2.12.0)
105
- simplecov (0.7.1)
106
- multi_json (~> 1.0)
107
- simplecov-html (~> 0.7.1)
108
- simplecov-html (0.7.1)
109
- sprockets (2.2.1)
127
+ rspec-core (~> 2.14.0)
128
+ rspec-expectations (~> 2.14.0)
129
+ rspec-mocks (~> 2.14.0)
130
+ simplecov (0.8.2)
131
+ docile (~> 1.1.0)
132
+ multi_json
133
+ simplecov-html (~> 0.8.0)
134
+ simplecov-html (0.8.0)
135
+ sprockets (2.10.1)
110
136
  hike (~> 1.2)
111
137
  multi_json (~> 1.0)
112
138
  rack (~> 1.0)
113
139
  tilt (~> 1.1, != 1.3.0)
114
- thor (0.16.0)
115
- tilt (1.3.3)
116
- treetop (1.4.12)
140
+ sprockets-rails (2.0.1)
141
+ actionpack (>= 3.0)
142
+ activesupport (>= 3.0)
143
+ sprockets (~> 2.8)
144
+ thor (0.18.1)
145
+ thread_safe (0.1.3)
146
+ atomic
147
+ tilt (1.4.1)
148
+ treetop (1.4.15)
117
149
  polyglot
118
150
  polyglot (>= 0.3.1)
119
- tzinfo (0.3.35)
120
- warden (1.2.1)
151
+ tzinfo (0.3.38)
152
+ warden (1.2.3)
121
153
  rack (>= 1.0)
122
- yard (0.8.3)
154
+ yard (0.8.7.3)
123
155
 
124
156
  PLATFORMS
125
157
  ruby
@@ -128,6 +160,6 @@ DEPENDENCIES
128
160
  bundler (>= 1.0.0)
129
161
  devise (>= 2.0.0)
130
162
  easy_captcha
131
- jeweler (~> 1.8.4)
163
+ jeweler (~> 2.0.1)
132
164
  rails (>= 3.1.1)
133
165
  rails_email_validator
@@ -0,0 +1,238 @@
1
+ # Devise Security Extension
2
+
3
+ An enterprise security extension for [Devise](https://github.com/plataformatec/devise), trying to meet industrial standard security demands for web applications.
4
+
5
+ It is composed of 6 addtional Devise modules:
6
+
7
+ * `:password_expirable` - passwords will expire after a configured time (and will need an update)
8
+ * `:secure_validatable` - better way to validate a model (email, stronger password validation). Don't use with Devise `:validatable` module!
9
+ * `:password_archivable` - save used passwords in an `old_passwords` table for history checks (don't be able to use a formerly used password)
10
+ * `:session_limitable` - ensures, that there is only one session usable per account at once
11
+ * `:expirable` - expires a user account after x days of inactivity (default 90 days)
12
+ * `:security_questionable` - as accessible substitution for captchas (security question with captcha fallback)
13
+
14
+ Configuration and database schema for each module below.
15
+
16
+ ## Additional features
17
+
18
+ * **captcha support** for `sign_up`, `sign_in`, `recover` and `unlock` (to make automated mass creation and brute forcing of accounts harder)
19
+
20
+ ## Getting started
21
+
22
+ Devise Security Extension works with Devise on Rails 3.2 onwards. You can add it to your Gemfile after you successfully set up Devise (see [Devise documentation](https://github.com/plataformatec/devise)) with:
23
+
24
+ ```ruby
25
+ gem 'devise_security_extension'
26
+ ```
27
+
28
+ Run the bundle command to install it.
29
+
30
+ After you installed Devise Security Extension you need to run the generator:
31
+
32
+ ```console
33
+ rails generate devise_security_extension:install
34
+ ```
35
+
36
+ The generator will inject the available configuration options into the **existing** Devise initializer and you MUST take a look at it (and all the Devise configuration as well). When you are done, you are ready to add Devise Security Extension modules on top of Devise modules to any of your Devise models:
37
+
38
+ ```ruby
39
+ devise :password_expirable, :secure_validatable, :password_archivable, :session_limitable, :expirable
40
+ ```
41
+
42
+ for `:secure_validatable` you need to add
43
+
44
+ ```ruby
45
+ gem 'rails_email_validator'
46
+ ```
47
+
48
+ ## Configuration
49
+
50
+ ```ruby
51
+ Devise.setup do |config|
52
+ # ==> Security Extension
53
+ # Configure security extension for devise
54
+
55
+ # Should the password expire (e.g 3.months)
56
+ # config.expire_password_after = 3.months
57
+
58
+ # Need 1 char of A-Z, a-z and 0-9
59
+ # config.password_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
60
+
61
+ # How often save old passwords in archive
62
+ # config.password_archiving_count = 5
63
+
64
+ # Deny old password (true, false, count)
65
+ # config.deny_old_passwords = true
66
+
67
+ # captcha integration for recover form
68
+ # config.captcha_for_recover = true
69
+
70
+ # captcha integration for sign up form
71
+ # config.captcha_for_sign_up = true
72
+
73
+ # captcha integration for sign in form
74
+ # config.captcha_for_sign_in = true
75
+
76
+ # captcha integration for unlock form
77
+ # config.captcha_for_unlock = true
78
+
79
+ # security_question integration for recover form
80
+ # this automatically enables captchas (captcha_for_recover, as fallback)
81
+ # config.security_question_for_recover = false
82
+
83
+ # security_question integration for unlock form
84
+ # this automatically enables captchas (captcha_for_unlock, as fallback)
85
+ # config.security_question_for_unlock = false
86
+
87
+ # security_question integration for confirmation form
88
+ # this automatically enables captchas (captcha_for_confirmation, as fallback)
89
+ # config.security_question_for_confirmation = false
90
+
91
+ # ==> Configuration for :expirable
92
+ # Time period for account expiry from last_activity_at
93
+ # config.expire_after = 90.days
94
+ end
95
+ ```
96
+
97
+ ## Captcha-Support
98
+ The captcha support depends on [EasyCaptcha](https://github.com/phatworx/easy_captcha). See further documention there.
99
+
100
+ ### Installation
101
+
102
+ 1. Add EasyCaptcha to your `Gemfile` with
103
+ ```ruby
104
+ gem 'easy_captcha'
105
+ ```
106
+ 2. Run the initializer
107
+ ```ruby
108
+ rails generate easy_captcha:install
109
+ ```
110
+ 3. Enable captcha - see "Configuration" of Devise Security Extension above.
111
+ 4. Add the captcha in the generated devise views for each controller you have activated
112
+ ```erb
113
+ <p><%= captcha_tag %></p>
114
+ <p><%= text_field_tag :captcha %></p>
115
+ ```
116
+
117
+ ## Schema
118
+
119
+ ### Password expirable
120
+ ```ruby
121
+ create_table :the_resources do |t|
122
+ # other devise fields
123
+
124
+ t.datetime :password_changed_at
125
+ end
126
+ add_index :the_resources, :password_changed_at
127
+ ```
128
+
129
+ ### Password archivable
130
+ ```ruby
131
+ create_table :old_passwords do |t|
132
+ t.string :encrypted_password, :null => false
133
+ t.string :password_salt
134
+ t.string :password_archivable_type, :null => false
135
+ t.integer :password_archivable_id, :null => false
136
+ t.datetime :created_at
137
+ end
138
+ add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
139
+ ```
140
+
141
+ ### Session limitable
142
+ ```ruby
143
+ create_table :the_resources do |t|
144
+ # other devise fields
145
+
146
+ t.string :unique_session_id, :limit => 20
147
+ end
148
+ ```
149
+
150
+ ### Expirable
151
+ ```ruby
152
+ create_table :the_resources do |t|
153
+ # other devise fields
154
+
155
+ t.datetime :last_activity_at
156
+ t.datetime :expired_at
157
+ end
158
+ add_index :the_resources, :last_activity_at
159
+ add_index :the_resources, :expired_at
160
+ ```
161
+
162
+ ### Security questionable
163
+ ```ruby
164
+ create_table :security_questions do |t|
165
+ t.string :locale, :null => false
166
+ t.string :name, :null => false
167
+ end
168
+
169
+ SecurityQuestion.create! locale: :de, name: 'Wie lautet der Geburstname Ihrer Mutter?'
170
+ SecurityQuestion.create! locale: :de, name: 'Wo sind sie geboren?'
171
+ SecurityQuestion.create! locale: :de, name: 'Wie lautet der Name Ihres ersten Haustieres?'
172
+ SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblingsfilm?'
173
+ SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblingsbuch?'
174
+ SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblingstier?'
175
+ SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblings-Reiseland?'
176
+ ```
177
+
178
+
179
+ ```ruby
180
+ add_column :the_resources, :security_question_id, :integer
181
+ add_column :the_resources, :security_question_answer, :string
182
+ ```
183
+
184
+ or
185
+
186
+ ```ruby
187
+ create_table :the_resources do |t|
188
+ # other devise fields
189
+
190
+ t.integer :security_question_id
191
+ t.string :security_question_answer
192
+ end
193
+ ```
194
+
195
+ ## Requirements
196
+
197
+ * Devise (https://github.com/plataformatec/devise)
198
+ * Rails 3.2 onwards (http://github.com/rails/rails)
199
+ * recommendations:
200
+ * `autocomplete-off` (http://github.com/phatworx/autocomplete-off)
201
+ * `easy_captcha` (http://github.com/phatworx/easy_captcha)
202
+ * `rails_email_validator` (http://github.com/phatworx/rails_email_validator)
203
+
204
+
205
+ ## Todo
206
+
207
+ * see the github issues (feature requests)
208
+
209
+ ## History
210
+ * 0.1 expire passwords
211
+ * 0.2 strong password validation
212
+ * 0.3 password archivable with validation
213
+ * 0.4 captcha support for sign_up, sign_in, recover and unlock
214
+ * 0.5 session_limitable module
215
+ * 0.6 expirable module
216
+ * 0.7 security questionable module for recover and unlock
217
+ * 0.8 Support for Rails 4 (+ variety of patches)
218
+
219
+ ## Maintainers
220
+
221
+ * Team Phatworx (http://github.com/phatworx)
222
+ * Alexander Dreher (http://github.com/alexdreher)
223
+ * Christoph Chilian (http://github.com/cc-web)
224
+ * Marco Scholl (http://github.com/traxanos)
225
+
226
+ ## Contributing to devise_security_extension
227
+
228
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
229
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
230
+ * Fork the project
231
+ * Start a feature/bugfix branch
232
+ * Commit and push until you are happy with your contribution
233
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
234
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
235
+
236
+ ## Copyright
237
+
238
+ Copyright (c) 2011-2012 Marco Scholl. See LICENSE.txt for further details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.2
1
+ 0.8.0
@@ -11,7 +11,7 @@ class Devise::PasswordExpiredController < DeviseController
11
11
  end
12
12
 
13
13
  def update
14
- if resource.update_with_password(params[resource_name])
14
+ if resource.update_with_password(resource_params)
15
15
  warden.session(scope)[:password_expired] = false
16
16
  set_flash_message :notice, :updated
17
17
  sign_in scope, resource, :bypass => true
@@ -23,6 +23,9 @@ class Devise::PasswordExpiredController < DeviseController
23
23
  end
24
24
 
25
25
  private
26
+ def resource_params
27
+ params.require(resource_name).permit!
28
+ end
26
29
 
27
30
  def scope
28
31
  resource_name.to_sym
@@ -3,6 +3,7 @@ de:
3
3
  messages:
4
4
  taken_in_past: "wurde bereits in der Vergangenheit verwendet!"
5
5
  equal_to_current_password: "darf nicht dem aktuellen Passwort entsprechen!"
6
+ password_format: "müssen große, kleine Buchstaben und Ziffern enthalten"
6
7
  devise:
7
8
  invalid_captcha: "Die Captchaeingabe ist nicht gültig!"
8
9
  password_expired:
@@ -3,6 +3,7 @@ en:
3
3
  messages:
4
4
  taken_in_past: "was already taken in the past!"
5
5
  equal_to_current_password: "must be different to the current password!"
6
+ password_format: "must contain big, small letters and digits"
6
7
  devise:
7
8
  invalid_captcha: "The captcha input is not valid!"
8
9
  password_expired:
@@ -2,26 +2,28 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: devise_security_extension 0.8.0 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "devise_security_extension"
8
- s.version = "0.7.2"
9
+ s.version = "0.8.0"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Marco Scholl", "Alexander Dreher"]
12
- s.date = "2012-11-22"
14
+ s.date = "2014-01-31"
13
15
  s.description = "An enterprise security extension for devise, trying to meet industrial standard security demands for web applications."
14
16
  s.email = "team@phatworx.de"
15
17
  s.extra_rdoc_files = [
16
18
  "LICENSE.txt",
17
- "README.rdoc"
19
+ "README.md"
18
20
  ]
19
21
  s.files = [
20
22
  ".document",
21
23
  "Gemfile",
22
24
  "Gemfile.lock",
23
25
  "LICENSE.txt",
24
- "README.rdoc",
26
+ "README.md",
25
27
  "Rakefile",
26
28
  "VERSION",
27
29
  "app/controllers/devise/password_expired_controller.rb",
@@ -61,12 +63,11 @@ Gem::Specification.new do |s|
61
63
  ]
62
64
  s.homepage = "http://github.com/phatworx/devise_security_extension"
63
65
  s.licenses = ["MIT"]
64
- s.require_paths = ["lib"]
65
- s.rubygems_version = "1.8.24"
66
+ s.rubygems_version = "2.2.1"
66
67
  s.summary = "Security extension for devise"
67
68
 
68
69
  if s.respond_to? :specification_version then
69
- s.specification_version = 3
70
+ s.specification_version = 4
70
71
 
71
72
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
72
73
  s.add_runtime_dependency(%q<rails>, [">= 3.1.1"])
@@ -74,14 +75,14 @@ Gem::Specification.new do |s|
74
75
  s.add_development_dependency(%q<rails_email_validator>, [">= 0"])
75
76
  s.add_development_dependency(%q<easy_captcha>, [">= 0"])
76
77
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
77
- s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
78
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
78
79
  else
79
80
  s.add_dependency(%q<rails>, [">= 3.1.1"])
80
81
  s.add_dependency(%q<devise>, [">= 2.0.0"])
81
82
  s.add_dependency(%q<rails_email_validator>, [">= 0"])
82
83
  s.add_dependency(%q<easy_captcha>, [">= 0"])
83
84
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
84
- s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
85
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
85
86
  end
86
87
  else
87
88
  s.add_dependency(%q<rails>, [">= 3.1.1"])
@@ -89,7 +90,7 @@ Gem::Specification.new do |s|
89
90
  s.add_dependency(%q<rails_email_validator>, [">= 0"])
90
91
  s.add_dependency(%q<easy_captcha>, [">= 0"])
91
92
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
92
- s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
93
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
93
94
  end
94
95
  end
95
96
 
@@ -17,10 +17,10 @@ Warden::Manager.after_set_user :only => :fetch do |record, warden, options|
17
17
  scope = options[:scope]
18
18
  env = warden.request.env
19
19
 
20
- if warden.authenticated?(scope) && options[:store] != false
20
+ if record.respond_to?(:unique_session_id) && warden.authenticated?(scope) && options[:store] != false
21
21
  if record.unique_session_id != warden.session(scope)['unique_session_id'] && !env['devise.skip_session_limitable']
22
22
  warden.logout(scope)
23
23
  throw :warden, :scope => scope, :message => :session_limited
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -20,8 +20,7 @@ module Devise
20
20
 
21
21
  # Updates +last_activity_at+, called from a Warden::Manager.after_set_user hook.
22
22
  def update_last_activity!
23
- self.last_activity_at = Time.now.utc
24
- save(:validate => false)
23
+ self.update_column(:last_activity_at, Time.now.utc)
25
24
  end
26
25
 
27
26
  # Tells if the account has expired
@@ -1,5 +1,3 @@
1
1
  class OldPassword < ActiveRecord::Base
2
2
  belongs_to :password_archivable, :polymorphic => true
3
-
4
- attr_accessible :encrypted_password, :password_salt
5
3
  end
@@ -17,17 +17,27 @@ module Devise
17
17
  assert_secure_validations_api!(base)
18
18
 
19
19
  base.class_eval do
20
+ # validate login in a strict way if not yet validated
21
+ unless has_uniqueness_validation_of_login?
22
+ validation_condition = "#{login_attribute}_changed?".to_sym
20
23
 
21
- # uniq login
22
- validates authentication_keys[0], :uniqueness => {:scope => authentication_keys[1..-1], :case_sensitive => (case_insensitive_keys != false)}, :if => :email_changed?
24
+ validates login_attribute, :uniqueness => {
25
+ :scope => authentication_keys[1..-1],
26
+ :case_sensitive => !!case_insensitive_keys
27
+ },
28
+ :if => validation_condition
29
+ end
23
30
 
24
- # validates email
25
- validates :email, :presence => true, :if => :email_required?
26
- validates :email, :uniqueness => true, :allow_blank => true, :if => :email_changed? # check uniq for email ever
27
- validates :email, :email => email_validation if email_validation # use rails_email_validator or similar
28
-
29
- # validates password
30
- validates :password, :presence => true, :length => password_length, :format => password_regex, :confirmation => true, :if => :password_required?
31
+ unless devise_validation_enabled?
32
+ validates :email, :presence => true, :if => :email_required?
33
+ validates :email, :uniqueness => true, :allow_blank => true, :if => :email_changed? # check uniq for email ever
34
+
35
+ validates :password, :presence => true, :length => password_length, :confirmation => true, :if => :password_required?
36
+ end
37
+
38
+ # extra validations
39
+ validates :email, :email => email_validation if email_validation # use rails_email_validator or similar
40
+ validates :password, :format => { :with => password_regex, :message => :password_format }, :if => :password_required?
31
41
 
32
42
  # don't allow use same password
33
43
  validate :current_equal_password_validation
@@ -62,6 +72,22 @@ module Devise
62
72
 
63
73
  module ClassMethods
64
74
  Devise::Models.config(self, :password_regex, :password_length, :email_validation)
75
+
76
+ private
77
+ def has_uniqueness_validation_of_login?
78
+ validators.any? do |validator|
79
+ validator.kind_of?(ActiveRecord::Validations::UniquenessValidator) &&
80
+ validator.attributes.include?(login_attribute)
81
+ end
82
+ end
83
+
84
+ def login_attribute
85
+ authentication_keys[0]
86
+ end
87
+
88
+ def devise_validation_enabled?
89
+ self.ancestors.map(&:to_s).include? 'Devise::Models::Validatable'
90
+ end
65
91
  end
66
92
  end
67
93
  end
@@ -1,3 +1,3 @@
1
1
  class SecurityQuestion < ActiveRecord::Base
2
- attr_accessible :locale, :name
2
+
3
3
  end
@@ -3,10 +3,13 @@ module Devise
3
3
  # SecurityQuestionable is an accessible add-on for visually handicapped people,
4
4
  # to ship around the captcha with screenreader compatibility.
5
5
  #
6
- # You need to add two text_field_tags to the associated form:
6
+ # You need to add two text_field_tags to the associated forms (unlock,
7
+ # password, confirmation):
7
8
  # :security_question_answer and :captcha
8
9
  #
9
10
  # And add the security_question to the register/edit form.
11
+ # f.select :security_question_id, SecurityQuestion.where(locale: I18n.locale).map{|s| [s.name, s.id]}
12
+ # f.text_field :security_question_answer
10
13
  module SecurityQuestionable
11
14
  extend ActiveSupport::Concern
12
15
 
@@ -3,25 +3,26 @@ module DeviseSecurityExtension::Patches
3
3
  extend ActiveSupport::Concern
4
4
  included do
5
5
  define_method :create do
6
- build_resource
6
+ build_resource(sign_up_params)
7
7
 
8
8
  if valid_captcha? params[:captcha]
9
9
 
10
10
  if resource.save
11
+ yield resource if block_given?
11
12
  if resource.active_for_authentication?
12
- set_flash_message :notice, :signed_up if is_navigational_format?
13
- sign_in(resource_name, resource)
13
+ set_flash_message :notice, :signed_up if is_flashing_format?
14
+ sign_up(resource_name, resource)
14
15
  respond_with resource, :location => after_sign_up_path_for(resource)
15
16
  else
16
- set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
17
- expire_session_data_after_sign_in!
17
+ set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
18
+ expire_data_after_sign_in!
18
19
  respond_with resource, :location => after_inactive_sign_up_path_for(resource)
19
20
  end
20
21
  else
21
22
  clean_up_passwords resource
22
23
  respond_with resource
23
24
  end
24
-
25
+
25
26
  else
26
27
  resource.errors.add :base, t('devise.invalid_captcha')
27
28
  clean_up_passwords resource
@@ -4,12 +4,13 @@ module DeviseSecurityExtension::Patches
4
4
  included do
5
5
  define_method :create do
6
6
  if valid_captcha? params[:captcha]
7
- resource = warden.authenticate!(auth_options)
8
- set_flash_message(:notice, :signed_in) if is_navigational_format?
7
+ self.resource = warden.authenticate!(auth_options)
8
+ set_flash_message(:notice, :signed_in) if is_flashing_format?
9
9
  sign_in(resource_name, resource)
10
+ yield resource if block_given?
10
11
  respond_with resource, :location => after_sign_in_path_for(resource)
11
12
  else
12
- flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
13
+ flash[:alert] = t('devise.invalid_captcha') if is_flashing_format?
13
14
  respond_with({}, :location => new_session_path(resource_name))
14
15
  end
15
16
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_security_extension
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
5
- prerelease:
4
+ version: 0.8.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Marco Scholl
@@ -10,104 +9,92 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2012-11-22 00:00:00.000000000 Z
12
+ date: 2014-01-31 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: rails
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - ">="
21
19
  - !ruby/object:Gem::Version
22
20
  version: 3.1.1
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - ">="
29
26
  - !ruby/object:Gem::Version
30
27
  version: 3.1.1
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: devise
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - ">="
37
33
  - !ruby/object:Gem::Version
38
34
  version: 2.0.0
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - ">="
45
40
  - !ruby/object:Gem::Version
46
41
  version: 2.0.0
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: rails_email_validator
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ! '>='
46
+ - - ">="
53
47
  - !ruby/object:Gem::Version
54
48
  version: '0'
55
49
  type: :development
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ! '>='
53
+ - - ">="
61
54
  - !ruby/object:Gem::Version
62
55
  version: '0'
63
56
  - !ruby/object:Gem::Dependency
64
57
  name: easy_captcha
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - ">="
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0'
71
63
  type: :development
72
64
  prerelease: false
73
65
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
  requirements:
76
- - - ! '>='
67
+ - - ">="
77
68
  - !ruby/object:Gem::Version
78
69
  version: '0'
79
70
  - !ruby/object:Gem::Dependency
80
71
  name: bundler
81
72
  requirement: !ruby/object:Gem::Requirement
82
- none: false
83
73
  requirements:
84
- - - ! '>='
74
+ - - ">="
85
75
  - !ruby/object:Gem::Version
86
76
  version: 1.0.0
87
77
  type: :development
88
78
  prerelease: false
89
79
  version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
80
  requirements:
92
- - - ! '>='
81
+ - - ">="
93
82
  - !ruby/object:Gem::Version
94
83
  version: 1.0.0
95
84
  - !ruby/object:Gem::Dependency
96
85
  name: jeweler
97
86
  requirement: !ruby/object:Gem::Requirement
98
- none: false
99
87
  requirements:
100
- - - ~>
88
+ - - "~>"
101
89
  - !ruby/object:Gem::Version
102
- version: 1.8.4
90
+ version: 2.0.1
103
91
  type: :development
104
92
  prerelease: false
105
93
  version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
94
  requirements:
108
- - - ~>
95
+ - - "~>"
109
96
  - !ruby/object:Gem::Version
110
- version: 1.8.4
97
+ version: 2.0.1
111
98
  description: An enterprise security extension for devise, trying to meet industrial
112
99
  standard security demands for web applications.
113
100
  email: team@phatworx.de
@@ -115,13 +102,13 @@ executables: []
115
102
  extensions: []
116
103
  extra_rdoc_files:
117
104
  - LICENSE.txt
118
- - README.rdoc
105
+ - README.md
119
106
  files:
120
- - .document
107
+ - ".document"
121
108
  - Gemfile
122
109
  - Gemfile.lock
123
110
  - LICENSE.txt
124
- - README.rdoc
111
+ - README.md
125
112
  - Rakefile
126
113
  - VERSION
127
114
  - app/controllers/devise/password_expired_controller.rb
@@ -161,29 +148,25 @@ files:
161
148
  homepage: http://github.com/phatworx/devise_security_extension
162
149
  licenses:
163
150
  - MIT
151
+ metadata: {}
164
152
  post_install_message:
165
153
  rdoc_options: []
166
154
  require_paths:
167
155
  - lib
168
156
  required_ruby_version: !ruby/object:Gem::Requirement
169
- none: false
170
157
  requirements:
171
- - - ! '>='
158
+ - - ">="
172
159
  - !ruby/object:Gem::Version
173
160
  version: '0'
174
- segments:
175
- - 0
176
- hash: 2180026344185734924
177
161
  required_rubygems_version: !ruby/object:Gem::Requirement
178
- none: false
179
162
  requirements:
180
- - - ! '>='
163
+ - - ">="
181
164
  - !ruby/object:Gem::Version
182
165
  version: '0'
183
166
  requirements: []
184
167
  rubyforge_project:
185
- rubygems_version: 1.8.24
168
+ rubygems_version: 2.2.1
186
169
  signing_key:
187
- specification_version: 3
170
+ specification_version: 4
188
171
  summary: Security extension for devise
189
172
  test_files: []
@@ -1,193 +0,0 @@
1
- = devise_security_extension
2
-
3
- An enterprise security extension for devise, trying to meet industrial standard security demands for web applications.
4
-
5
- == Features
6
-
7
- * captcha support for sign_up, sign_in, recover and unlock (to make automated mass creation and brute forcing of accounts harder)
8
-
9
- === Model modules
10
-
11
- * :password_expirable - passwords will expire after a configured time (and will need an update)
12
- * :secure_validatable - better way to validate a model (email, stronger password validation). Don't use with :validatable!
13
- * :password_archivable - save used passwords in an old_passwords table for history checks (don't be able to use a formerly used password)
14
- * :session_limitable - ensures, that there is only one session usable per account at once
15
- * :expirable - expires a user account after x days of inactivity (default 90 days)
16
- * :security_questionable - as accessible substitution for captchas (security question with captcha fallback)
17
-
18
- == Installation
19
- Add to Gemfile
20
- gem 'devise_security_extension'
21
-
22
- after bundle install
23
- rails g devise_security_extension:install
24
-
25
- for :secure_validatable you need to add
26
- gem 'rails_email_validator'
27
-
28
- == Configuration
29
-
30
- Devise.setup do |config|
31
- # Should the password expire (e.g 3.months)
32
- # config.expire_password_after = 3.months
33
-
34
- # Need 1 char of A-Z, a-z and 0-9
35
- # config.password_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
36
-
37
- # How often save old passwords in archive
38
- # config.password_archiving_count = 5
39
-
40
- # Deny old password (true, false, count)
41
- # config.deny_old_passwords = true
42
-
43
- # captcha integration for recover form
44
- # config.captcha_for_recover = true
45
-
46
- # captcha integration for sign up form
47
- # config.captcha_for_sign_up = true
48
-
49
- # captcha integration for sign in form
50
- # config.captcha_for_sign_in = true
51
-
52
- # captcha integration for unlock form
53
- # config.captcha_for_unlock = true
54
-
55
- # security_question integration for recover form
56
- # this automatically enables captchas (captcha_for_recover, as fallback)
57
- # config.security_question_for_recover = false
58
-
59
- # security_question integration for unlock form
60
- # this automatically enables captchas (captcha_for_unlock, as fallback)
61
- # config.security_question_for_unlock = false
62
-
63
- # security_question integration for confirmation form
64
- # this automatically enables captchas (captcha_for_confirmation, as fallback)
65
- # config.security_question_for_confirmation = false
66
-
67
- # ==> Configuration for :expirable
68
- # Time period for account expiry from last_activity_at
69
- config.expire_after = 90.days
70
- end
71
-
72
- == Captcha-Support
73
-
74
- === Installation
75
-
76
- 1. add to Gemfile "gem 'easy_captcha'"
77
- 2. install easy_captcha "rails g easy_captcha:install"
78
- 3. enable captcha - see "Configuration"
79
- 4. add captcha source in the devise views for each controller you have activated
80
-
81
- <p><%= captcha_tag %></p>
82
- <p><%= text_field_tag :captcha %></p>
83
-
84
- That's it!
85
-
86
-
87
- == Schema
88
-
89
- === Password expirable
90
-
91
- create_table :the_resources do |t|
92
- # other devise fields
93
-
94
- t.datetime :password_changed_at
95
- end
96
- add_index :the_resources, :password_changed_at
97
-
98
- === Password archivable
99
-
100
- create_table :old_passwords do |t|
101
- t.string :encrypted_password, :null => false
102
- t.string :password_salt
103
- t.string :password_archivable_type, :null => false
104
- t.integer :password_archivable_id, :null => false
105
- t.datetime :created_at
106
- end
107
- add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
108
-
109
- === Session limitable
110
-
111
- create_table :the_resources do |t|
112
- # other devise fields
113
-
114
- t.string :unique_session_id, :limit => 20
115
- end
116
-
117
- === Expirable
118
-
119
- create_table :the_resources do |t|
120
- # other devise fields
121
-
122
- t.datetime :last_activity_at
123
- t.datetime :expired_at
124
- end
125
- add_index :the_resources, :last_activity_at
126
- add_index :the_resources, :expired_at
127
-
128
- === Security questionable
129
-
130
- create_table :security_questions do |t|
131
- t.string :locale, :null => false
132
- t.string :name, :null => false
133
- end
134
-
135
- SecurityQuestion.create! locale: :de, name: 'Wie lautet der Geburstname Ihrer Mutter?'
136
- SecurityQuestion.create! locale: :de, name: 'Wo sind sie geboren?'
137
- SecurityQuestion.create! locale: :de, name: 'Wie lautet der Name Ihres ersten Haustieres?'
138
- SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblingsfilm?'
139
- SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblingsbuch?'
140
- SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblingstier?'
141
- SecurityQuestion.create! locale: :de, name: 'Was ist Ihr Lieblings-Reiseland?'
142
-
143
- add_column :the_resources, :security_question_id, :integer
144
- add_column :the_resources, :security_question_answer, :string
145
-
146
- or
147
-
148
- create_table :the_resources do |t|
149
- # other devise fields
150
-
151
- t.integer :security_question_id
152
- t.string :security_question_answer
153
- end
154
-
155
- == Requirements
156
-
157
- * devise (https://github.com/plataformatec/devise)
158
- * Rails 3 (http://github.com/rails/rails)
159
- * recommendation: autocomplete-off (http://github.com/phatworx/autocomplete-off)
160
-
161
- == Todo
162
-
163
- * see the github issues (feature requests)
164
-
165
- == History
166
- * 0.1 expire passwords
167
- * 0.2 strong password validation
168
- * 0.3 password archivable with validation
169
- * 0.4 captcha support for sign_up, sign_in, recover and unlock
170
- * 0.5 session_limitable module
171
- * 0.6 expirable module
172
- * 0.7 security questionable module for recover and unlock
173
-
174
- == Maintainers
175
-
176
- * Team Phatworx (http://github.com/phatworx)
177
- * Marco Scholl (http://github.com/traxanos)
178
- * Alexander Dreher (http://github.com/alexdreher)
179
- * Christoph Chilian (http://github.com/cc-web)
180
-
181
- == Contributing to devise_security_extension
182
-
183
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
184
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
185
- * Fork the project
186
- * Start a feature/bugfix branch
187
- * Commit and push until you are happy with your contribution
188
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
189
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
190
-
191
- == Copyright
192
-
193
- Copyright (c) 2011-2012 Marco Scholl. See LICENSE.txt for further details.