devise-pwned_password 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be89bb3c81bab360c6d6037b19467554f64351de218448a82cd6b0b1b539b5ae
4
- data.tar.gz: 4c53a8b3a1d26d3810b1a85af91c8aecc53f6d42f22c50ea7d29a6942e137cc7
3
+ metadata.gz: 366fc1a14fb5abd102a74ce7a814219815c3ab764ae7c2d3c14296fb72679f76
4
+ data.tar.gz: 682e24df4e1a6cbf674c58c34cac5a16f4a233d351f52f7400aa8f35a83e7f72
5
5
  SHA512:
6
- metadata.gz: aebdde0d629534140a161ef2c0e5390aefd731253e0753ce833b616b89da8c0e74a1b0e8e7ecf02cd379460a3c856da1c922fbff057d347304ccbed1ad6c77e5
7
- data.tar.gz: 384175a042d38bf567c27aec57563398f8b0f6768eb17e6dcddf208e26db19180cf72ee332f2cc1b0e005d44bf870f189264a85d84468c34c220fe42002b1eee
6
+ metadata.gz: 89f437434e88bc07874002f0baed66f210a15e4a7b9fa3d4377d4c9005c63d3b5a9f5476bf8ccb63ced1d34e81c1f8d3ab7d9f2137d332e6d3557fe4dad53456
7
+ data.tar.gz: de00ba890a8edad1bdac2281332f72570521794616666bd0efa1b50d0f138dbec1d852ba8de1639822caf7a8743130efe5318a8c94db57a2b48d97fac75e95aa
data/README.md CHANGED
@@ -1,19 +1,23 @@
1
1
  # Devise::PwnedPassword
2
- Devise extension that checks user passwords against the PwnedPasswords dataset https://haveibeenpwned.com/Passwords
2
+ Devise extension that checks user passwords against the PwnedPasswords dataset (https://haveibeenpwned.com/Passwords).
3
3
 
4
- Based on
4
+ Checks for compromised ("pwned") passwords in 2 different places/ways:
5
+ 1. As a standard model validation using [pwned](https://github.com/philnash/pwned). This:
6
+ - prevents new users from being created (signing up) with a compromised password
7
+ - prevents existing users from changing their password to a password that is known to be compromised
8
+ 2. (Optionally) Whenever a user signs in, checks if their current password is compromised and shows a warning if it is.
5
9
 
6
- https://github.com/HCLarsen/devise-uncommon_password
10
+ Based on [devise-uncommon_password](https://github.com/HCLarsen/devise-uncommon_password).
7
11
 
8
- Recently the HaveIBeenPwned API has moved to a authenticated/paid [model](https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/) , this does not effect the PwnedPasswords API, no payment or authentication is required.
12
+ Recently the HaveIBeenPwned API has moved to an [authenticated/paid model](https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/), but this does not affect the PwnedPasswords API; no payment or authentication is required.
9
13
 
10
14
 
11
15
  ## Usage
12
- Add the :pwned_password module to your existing Devise model.
16
+ Add the `:pwned_password` module to your existing Devise model.
13
17
 
14
18
  ```ruby
15
19
  class AdminUser < ApplicationRecord
16
- devise :database_authenticatable,
20
+ devise :database_authenticatable,
17
21
  :recoverable, :rememberable, :trackable, :validatable, :pwned_password
18
22
  end
19
23
  ```
@@ -25,6 +29,8 @@ PwnedPasswords dataset:
25
29
  Password has previously appeared in a data breach and should never be used. Please choose something harder to guess.
26
30
  ```
27
31
 
32
+ ## Configuration
33
+
28
34
  You can customize this error message by modifying the `devise` YAML file.
29
35
 
30
36
  ```yml
@@ -35,13 +41,71 @@ en:
35
41
  pwned_password: "has previously appeared in a data breach and should never be used. If you've ever used it anywhere before, change it immediately!"
36
42
  ```
37
43
 
38
- You can optionally warn existing users when they sign in if they are using a password from the PwnedPasswords dataset. The default message is:
44
+ By default passwords are rejected if they appear at all in the data set.
45
+ Optionally, you can add the following snippet to `config/initializers/devise.rb`
46
+ if you want the error message to be displayed only when the password is present
47
+ a certain number of times in the data set:
48
+
49
+ ```ruby
50
+ # Minimum number of times a pwned password must exist in the data set in order
51
+ # to be reject.
52
+ config.min_password_matches = 10
53
+ ```
54
+
55
+ By default responses from the PwnedPasswords API are timed out after 5 seconds
56
+ to reduce potential latency problems.
57
+ Optionally, you can add the following snippet to `config/initializers/devise.rb`
58
+ to control the timeout settings:
59
+
60
+ ```ruby
61
+ config.pwned_password_open_timeout = 1
62
+ config.pwned_password_read_timeout = 2
63
+ ```
64
+
65
+
66
+ ### How to warn existing users when they sign in
67
+
68
+ You can optionally warn existing users when they sign in if they are using a password from the PwnedPasswords dataset.
69
+
70
+ To enable this, you _must_ override `after_sign_in_path_for`, like this:
71
+
72
+ ```ruby
73
+ # app/controllers/application_controller.rb
74
+
75
+ def after_sign_in_path_for(resource)
76
+ set_flash_message! :alert, :warn_pwned if resource.respond_to?(:pwned?) && resource.pwned?
77
+ super
78
+ end
79
+ ```
80
+
81
+ For an [Active Admin](https://github.com/activeadmin/activeadmin) application the following monkey patch is needed:
82
+
83
+ ```ruby
84
+ # config/initializers/active_admin_devise_sessions_controller.rb
85
+ class ActiveAdmin::Devise::SessionsController
86
+ def after_sign_in_path_for(resource)
87
+ set_flash_message! :alert, :warn_pwned if resource.respond_to?(:pwned?) && resource.pwned?
88
+ super
89
+ end
90
+ end
91
+ ```
92
+
93
+ To prevent the default call to the HaveIBeenPwned API on user sign-in (only
94
+ really useful if you're going to check `pwned?` after sign-in as used above),
95
+ add the following to `config/initializers/devise.rb`:
96
+
97
+ ```ruby
98
+ config.pwned_password_check_on_sign_in = false
99
+ ```
100
+
101
+ #### Customize warning message
39
102
 
103
+ The default message is:
40
104
  ```
41
105
  Your password has previously appeared in a data breach and should never be used. We strongly recommend you change your password.
42
106
  ```
43
107
 
44
- You can customize this message by modifying the `devise` YAML file.
108
+ You can customize this message by modifying the `devise.en.yml` locale file.
45
109
 
46
110
  ```yml
47
111
  # config/locales/devise.en.yml
@@ -51,22 +115,15 @@ en:
51
115
  warn_pwned: "Your password has previously appeared in a data breach and should never be used. We strongly recommend you change your password everywhere you have used it."
52
116
  ```
53
117
 
54
- By default passwords are rejected if they appear at all in the data set.
55
- Optionally, you can add the following snippet to `config/initializers/devise.rb`
56
- if you want the error message to be displayed only when the password is present
57
- a certain number of times in the data set:
118
+ #### Customize the warning threshold
58
119
 
59
- ```ruby
60
- # Minimum number of times a pwned password must exist in the data set in order
61
- # to be reject.
62
- config.min_password_matches = 10
63
- ```
120
+ By default the same value, `config.min_password_matches` is used as the threshold for rejecting a passwords for _new_ user sign-ups and for warning existing users.
64
121
 
65
- By default the value set above is used to reject passwords and warn users.
66
- Optionally, you can add the following snippet to `config/initializers/devise.rb`
67
- if you want to use different thresholds for rejecting the password and warning
122
+ If you want to use different thresholds for rejecting the password and warning
68
123
  the user (for example you may only want to reject passwords that are common but
69
- warn if the password occurs at all in the list):
124
+ warn if the password occurs at all in the list), you can set a different value for each.
125
+
126
+ To change the threshold used for the warning _only_, add to `config/initializers/devise.rb`
70
127
 
71
128
  ```ruby
72
129
  # Minimum number of times a pwned password must exist in the data set in order
@@ -74,15 +131,11 @@ warn if the password occurs at all in the list):
74
131
  config.min_password_matches_warn = 1
75
132
  ```
76
133
 
77
- By default responses from the PwnedPasswords API are timed out after 5 seconds
78
- to reduce potential latency problems.
79
- Optionally, you can add the following snippet to `config/initializers/devise.rb`
80
- to control the timeout settings:
81
-
82
- ```ruby
83
- config.pwned_password_open_timeout = 1
84
- config.pwned_password_read_timeout = 2
85
- ```
134
+ Note: If you do have a different warning threshold, that threshold will also be used
135
+ when a user changes their password (added as an _error_!) so that they don't
136
+ continue to be warned if they choose another password that is in the pwned list
137
+ but occurs with a frequency below the main threshold that is used for *new*
138
+ user registrations (`config.min_password_matches`).
86
139
 
87
140
  ### Disabling in test environments
88
141
 
@@ -107,32 +160,6 @@ And then execute:
107
160
  $ bundle install
108
161
  ```
109
162
 
110
- Optionally, if you also want to warn existing users when they sign in, override `after_sign_in_path_for`
111
- ```ruby
112
- def after_sign_in_path_for(resource)
113
- set_flash_message! :alert, :warn_pwned if resource.respond_to?(:pwned?) && resource.pwned?
114
- super
115
- end
116
- ```
117
-
118
- This should generally be added in ```app/controllers/application_controller.rb``` for a rails app. For an Active Admin application the following monkey patch is needed.
119
-
120
- ```ruby
121
- # config/initializers/active_admin_devise_sessions_controller.rb
122
- class ActiveAdmin::Devise::SessionsController
123
- def after_sign_in_path_for(resource)
124
- set_flash_message! :alert, :warn_pwned if resource.respond_to?(:pwned?) && resource.pwned?
125
- super
126
- end
127
- end
128
- ```
129
-
130
- To prevent the default call to the HaveIBeenPwned API on user sign in, add the following to `config/initializers/devise.rb`:
131
-
132
- ```ruby
133
- config.pwned_password_check_on_sign_in = false
134
- ```
135
-
136
163
  ## Considerations
137
164
 
138
165
  A few things to consider/understand when using this gem:
@@ -144,18 +171,19 @@ A few things to consider/understand when using this gem:
144
171
  to a third party. More implementation details and important caveats can be
145
172
  found in https://blog.cloudflare.com/validating-leaked-passwords-with-k-anonymity/
146
173
 
147
- * This puts an external API in the request path of users signing up to your
148
- application. This could potentially add some latency to this operation. The
149
- gem is designed to fail silently if the PwnedPasswords service is unavailable.
174
+ * This puts an external API in the request path of users signing up to your application. This could
175
+ potentially add some latency to this operation. The gem is designed to silently swallows errors if
176
+ the PwnedPasswords service is unavailable, allowing users to use compromised passwords during the
177
+ time when it is unavailable.
150
178
 
151
179
  ## Contributing
152
180
 
153
- To contribute
181
+ To contribute:
154
182
 
155
183
  * Check the [issue tracker](https://github.com/michaelbanfield/devise-pwned_password/issues) and [pull requests](https://github.com/michaelbanfield/devise-pwned_password/pulls) for anything similar
156
184
  * Fork the repository
157
185
  * Make your changes
158
- * Run bin/test to make sure the unit tests still run
186
+ * Run `bin/test` to make sure the unit tests still run
159
187
  * Send a pull request
160
188
 
161
189
  ## License
@@ -14,7 +14,8 @@ module Devise
14
14
  extend ActiveSupport::Concern
15
15
 
16
16
  included do
17
- validate :not_pwned_password, if: :password_required?
17
+ validate :not_pwned_password,
18
+ if: Devise.activerecord51? ? :will_save_change_to_encrypted_password? : :encrypted_password_changed?
18
19
  end
19
20
 
20
21
  module ClassMethods
@@ -46,9 +47,20 @@ module Devise
46
47
  pwned_password = Pwned::Password.new(password.to_s, options)
47
48
  begin
48
49
  @pwned_count = pwned_password.pwned_count
49
- @pwned = @pwned_count >= (persisted? ? self.class.min_password_matches_warn || self.class.min_password_matches : self.class.min_password_matches)
50
+ @pwned = @pwned_count >= (
51
+ if persisted?
52
+ # If you do have a different warning threshold, that threshold will also be used
53
+ # when a user changes their password so that they don't continue to be warned if they
54
+ # choose another password that is in the pwned list but occurs with a frequency below
55
+ # the main threshold that is used for *new* user registrations.
56
+ self.class.min_password_matches_warn || self.class.min_password_matches
57
+ else
58
+ self.class.min_password_matches
59
+ end
60
+ )
50
61
  return @pwned
51
62
  rescue Pwned::Error
63
+ # This deliberately silently swallows errors and returns false (valid) if there was an error. Most apps won't want to tie the ability to sign up users to the availability of a third-party API.
52
64
  return false
53
65
  end
54
66
 
@@ -58,9 +70,8 @@ module Devise
58
70
  private
59
71
 
60
72
  def not_pwned_password
61
- # This deliberately fails silently on 500's etc. Most apps wont want to tie the ability to sign up customers to the availability of a third party API
62
73
  if password_pwned?(password)
63
- errors.add(:password, :pwned_password)
74
+ errors.add(:password, :pwned_password, count: @pwned_count)
64
75
  end
65
76
  end
66
77
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Devise
4
4
  module PwnedPassword
5
- VERSION = "0.1.8"
5
+ VERSION = "0.1.9"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-pwned_password
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Banfield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-10 00:00:00.000000000 Z
11
+ date: 2020-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise
@@ -39,21 +39,21 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.0.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: rails
42
+ name: byebug
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 5.1.2
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 5.1.2
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: sqlite3
56
+ name: capybara
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 5.1.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 5.1.2
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rubocop
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: 0.52.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: sqlite3
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  description: Devise extension that checks user passwords against the PwnedPasswords
84
112
  dataset https://haveibeenpwned.com/Passwords.
85
113
  email: