two_factor_authentication 1.1.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +21 -0
  3. data/.rubocop.yml +295 -0
  4. data/.travis.yml +4 -5
  5. data/CHANGELOG.md +24 -14
  6. data/README.md +57 -65
  7. data/app/controllers/devise/two_factor_authentication_controller.rb +28 -12
  8. data/app/views/devise/two_factor_authentication/show.html.erb +10 -1
  9. data/config/locales/en.yml +1 -0
  10. data/config/locales/es.yml +8 -0
  11. data/config/locales/fr.yml +1 -0
  12. data/config/locales/ru.yml +1 -0
  13. data/lib/generators/active_record/templates/migration.rb +3 -0
  14. data/lib/two_factor_authentication.rb +9 -0
  15. data/lib/two_factor_authentication/controllers/helpers.rb +1 -1
  16. data/lib/two_factor_authentication/hooks/two_factor_authenticatable.rb +4 -23
  17. data/lib/two_factor_authentication/models/two_factor_authenticatable.rb +68 -19
  18. data/lib/two_factor_authentication/routes.rb +3 -1
  19. data/lib/two_factor_authentication/schema.rb +12 -0
  20. data/lib/two_factor_authentication/version.rb +1 -1
  21. data/spec/controllers/two_factor_authentication_controller_spec.rb +2 -2
  22. data/spec/features/two_factor_authenticatable_spec.rb +36 -73
  23. data/spec/lib/two_factor_authentication/models/two_factor_authenticatable_spec.rb +137 -80
  24. data/spec/rails_app/app/controllers/home_controller.rb +1 -1
  25. data/spec/rails_app/app/models/admin.rb +6 -0
  26. data/spec/rails_app/app/models/encrypted_user.rb +2 -1
  27. data/spec/rails_app/app/models/guest_user.rb +8 -1
  28. data/spec/rails_app/app/models/user.rb +2 -2
  29. data/spec/rails_app/config/initializers/devise.rb +2 -2
  30. data/spec/rails_app/config/routes.rb +1 -0
  31. data/spec/rails_app/db/migrate/20140403184646_devise_create_users.rb +1 -1
  32. data/spec/rails_app/db/migrate/20160209032439_devise_create_admins.rb +42 -0
  33. data/spec/rails_app/db/schema.rb +19 -1
  34. data/spec/support/authenticated_model_helper.rb +22 -15
  35. data/spec/support/controller_helper.rb +1 -1
  36. data/spec/support/totp_helper.rb +11 -0
  37. data/two_factor_authentication.gemspec +1 -1
  38. metadata +74 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75e8b63e29715336ec78a4a06db141ec2fdddf68
4
- data.tar.gz: c2b09dd1294a966ce75425efc97b6e2089e33689
3
+ metadata.gz: 780c92dea8df1f3f6d1e761562e1469cc12a96a8
4
+ data.tar.gz: 82e383a9f79a3628e9950a17da920eeed8464622
5
5
  SHA512:
6
- metadata.gz: 6d38f91cbb77148bd9c401f129d977f5fa22281ddb20ec12e4a12f02b1e35acabd04048bc88bad4d7e4cc80311e43f8720f45b0eeea116323c96fdee78cfb733
7
- data.tar.gz: e7a2a0026e4558a8e0e8efbb3257b0fec162f7d45390a7521f249332e273c53568b309044000fae9ecdfcd55c3cfe13a951d2895f5327bb54b692a4fe2723fcf
6
+ metadata.gz: 31390c4f5e6e0506fc16e502a0cfa6ea908b371819f2bee9e7e14d42cec3a1ddc28ded3e584af1d650cc6c9c731ea3f4303543605d81f910fcffceec3cfaea15
7
+ data.tar.gz: a2d5fe899017a753c7d106245d52f248b9f74260864a6a38129649e8e0148d17ea9da56779c45b936466278292305131f7e17e74ec6704fbdda07dfb00a6bff0
data/.codeclimate.yml ADDED
@@ -0,0 +1,21 @@
1
+ engines:
2
+ brakeman:
3
+ enabled: true
4
+ duplication:
5
+ enabled: true
6
+ config:
7
+ languages:
8
+ - ruby
9
+ # mass_threshold: 30
10
+ exclude_paths:
11
+ - 'spec/**/*'
12
+ fixme:
13
+ enabled: true
14
+ rubocop:
15
+ enabled: true
16
+
17
+ ratings:
18
+ paths:
19
+ - app/**
20
+ - lib/**
21
+ - '**.rb'
data/.rubocop.yml ADDED
@@ -0,0 +1,295 @@
1
+ AllCops:
2
+ Include:
3
+ - '**/Gemfile'
4
+ - '**/Rakefile'
5
+ UseCache: true
6
+
7
+ Lint/AssignmentInCondition:
8
+ Description: Don't use assignment in conditions.
9
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
10
+ Enabled: true
11
+ AllowSafeAssignment: true
12
+ Lint/EachWithObjectArgument:
13
+ Description: Check for immutable argument given to each_with_object.
14
+ Enabled: true
15
+ Lint/HandleExceptions:
16
+ Description: Don't suppress exception.
17
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
18
+ Enabled: true
19
+ Lint/LiteralInCondition:
20
+ Description: Checks of literals used in conditions.
21
+ Enabled: true
22
+ Lint/LiteralInInterpolation:
23
+ Description: Checks for literals used in interpolation.
24
+ Enabled: true
25
+ Lint/ParenthesesAsGroupedExpression:
26
+ Description: Checks for method calls with a space before the opening parenthesis.
27
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#parens-no-spaces
28
+ Enabled: true
29
+
30
+ Metrics/AbcSize:
31
+ Description: A calculated magnitude based on number of assignments, branches, and
32
+ conditions.
33
+ Enabled: true
34
+ Max: 15
35
+ Exclude:
36
+ - spec/**/*
37
+ Metrics/ClassLength:
38
+ Description: Avoid classes longer than 100 lines of code.
39
+ Enabled: true
40
+ CountComments: false
41
+ Max: 100
42
+ Exclude:
43
+ - spec/**/*
44
+ Metrics/CyclomaticComplexity:
45
+ Description: A complexity metric that is strongly correlated to the number of test
46
+ cases needed to validate a method.
47
+ Enabled: true
48
+ Max: 6
49
+ Metrics/LineLength:
50
+ Description: Limit lines to 80 characters.
51
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#80-character-limits
52
+ Enabled: true
53
+ Max: 100
54
+ AllowURI: true
55
+ URISchemes:
56
+ - http
57
+ - https
58
+ Metrics/MethodLength:
59
+ Description: Avoid methods longer than 10 lines of code.
60
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
61
+ Enabled: true
62
+ CountComments: false
63
+ Max: 10
64
+ Exclude:
65
+ - spec/**/*
66
+ Metrics/ModuleLength:
67
+ CountComments: false
68
+ Max: 100
69
+ Description: Avoid modules longer than 100 lines of code.
70
+ Enabled: true
71
+ Exclude:
72
+ - spec/**/*
73
+ Metrics/ParameterLists:
74
+ Description: Avoid parameter lists longer than three or four parameters.
75
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
76
+ Enabled: true
77
+ Max: 5
78
+ CountKeywordArgs: true
79
+ Metrics/PerceivedComplexity:
80
+ Description: A complexity metric geared towards measuring complexity for a human
81
+ reader.
82
+ Enabled: true
83
+ Max: 7
84
+
85
+ Rails/ScopeArgs:
86
+ Description: Checks the arguments of ActiveRecord scopes.
87
+ Enabled: true
88
+ Rails/TimeZone:
89
+ # The value `strict` means that `Time` should be used with `zone`.
90
+ # The value `flexible` allows usage of `in_time_zone` instead of `zone`.
91
+ Enabled: true
92
+ EnforcedStyle: flexible
93
+ SupportedStyles:
94
+ - strict
95
+ - flexible
96
+
97
+ Style/AccessorMethodName:
98
+ Description: Check the naming of accessor methods for get_/set_.
99
+ Enabled: false
100
+ Style/AndOr:
101
+ Description: Use &&/|| instead of and/or.
102
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-and-or-or
103
+ Enabled: true
104
+ EnforcedStyle: conditionals
105
+ SupportedStyles:
106
+ - always
107
+ - conditionals
108
+ Style/Alias:
109
+ Description: Use alias_method instead of alias.
110
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
111
+ Enabled: true
112
+ Style/ClassAndModuleChildren:
113
+ EnforcedStyle: nested
114
+ SupportedStyles:
115
+ - nested
116
+ - compact
117
+ Style/CollectionMethods:
118
+ Description: Preferred collection methods.
119
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
120
+ Enabled: true
121
+ PreferredMethods:
122
+ collect: map
123
+ collect!: map!
124
+ find: detect
125
+ find_all: select
126
+ reduce: inject
127
+ Style/Documentation:
128
+ Description: Document classes and non-namespace modules.
129
+ Enabled: false
130
+ Style/DotPosition:
131
+ Description: Checks the position of the dot in multi-line method calls.
132
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
133
+ Enabled: true
134
+ EnforcedStyle: trailing
135
+ SupportedStyles:
136
+ - leading
137
+ - trailing
138
+ Style/DoubleNegation:
139
+ Description: Checks for uses of double negation (!!).
140
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
141
+ Enabled: true
142
+ Style/EachWithObject:
143
+ Description: Prefer `each_with_object` over `inject` or `reduce`.
144
+ Enabled: true
145
+ Style/EmptyLiteral:
146
+ Description: Prefer literals to Array.new/Hash.new/String.new.
147
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
148
+ Enabled: true
149
+ Style/FileName:
150
+ Description: Use snake_case for source file names.
151
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
152
+ Enabled: true
153
+ Exclude: []
154
+ Style/GuardClause:
155
+ Description: Check for conditionals that can be replaced with guard clauses
156
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
157
+ Enabled: true
158
+ MinBodyLength: 1
159
+ Style/IfUnlessModifier:
160
+ Description: Favor modifier if/unless usage when you have a single-line body.
161
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
162
+ Enabled: false
163
+ MaxLineLength: 80
164
+ Style/InlineComment:
165
+ Description: Avoid inline comments.
166
+ Enabled: false
167
+ Style/ModuleFunction:
168
+ Description: Checks for usage of `extend self` in modules.
169
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
170
+ Enabled: false
171
+ Style/OneLineConditional:
172
+ Description: Favor the ternary operator(?:) over if/then/else/end constructs.
173
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
174
+ Enabled: false
175
+ Style/OptionHash:
176
+ Description: Don't use option hashes when you can use keyword arguments.
177
+ Enabled: false
178
+ Style/PercentLiteralDelimiters:
179
+ Description: Use `%`-literal delimiters consistently
180
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
181
+ Enabled: true
182
+ PreferredDelimiters:
183
+ "%": "()"
184
+ "%i": "()"
185
+ "%q": "()"
186
+ "%Q": "()"
187
+ "%r": "{}"
188
+ "%s": "()"
189
+ "%w": "()"
190
+ "%W": "()"
191
+ "%x": "()"
192
+ Style/PerlBackrefs:
193
+ Description: Avoid Perl-style regex back references.
194
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
195
+ Enabled: false
196
+ Style/PredicateName:
197
+ Description: Check the names of predicate methods.
198
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
199
+ Enabled: true
200
+ NamePrefix:
201
+ - is_
202
+ - has_
203
+ - have_
204
+ NamePrefixBlacklist:
205
+ - is_
206
+ Exclude:
207
+ - spec/**/*
208
+ Style/RaiseArgs:
209
+ Description: Checks the arguments passed to raise/fail.
210
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
211
+ Enabled: true
212
+ EnforcedStyle: exploded
213
+ SupportedStyles:
214
+ - compact
215
+ - exploded
216
+ Style/Send:
217
+ Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
218
+ may overlap with existing methods.
219
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
220
+ Enabled: false
221
+ Style/SignalException:
222
+ Description: Checks for proper usage of fail and raise.
223
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
224
+ Enabled: true
225
+ EnforcedStyle: semantic
226
+ SupportedStyles:
227
+ - only_raise
228
+ - only_fail
229
+ - semantic
230
+ Style/SingleLineBlockParams:
231
+ Description: Enforces the names of some block params.
232
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
233
+ Enabled: true
234
+ Methods:
235
+ - reduce:
236
+ - a
237
+ - e
238
+ - inject:
239
+ - a
240
+ - e
241
+ Style/SingleLineMethods:
242
+ Description: Avoid single-line methods.
243
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
244
+ Enabled: true
245
+ AllowIfMethodIsEmpty: true
246
+ Style/SpecialGlobalVars:
247
+ Description: Avoid Perl-style global variables.
248
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
249
+ Enabled: false
250
+ Style/StringLiterals:
251
+ Description: Checks if uses of quotes match the configured preference.
252
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
253
+ Enabled: true
254
+ EnforcedStyle: single_quotes
255
+ SupportedStyles:
256
+ - single_quotes
257
+ - double_quotes
258
+ Style/StringLiteralsInInterpolation:
259
+ Description: Checks if uses of quotes inside expressions in interpolated strings
260
+ match the configured preference.
261
+ Enabled: true
262
+ EnforcedStyle: single_quotes
263
+ SupportedStyles:
264
+ - single_quotes
265
+ - double_quotes
266
+ Style/TrailingCommaInArguments:
267
+ Description: 'Checks for trailing comma in argument lists.'
268
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
269
+ Enabled: true
270
+ EnforcedStyleForMultiline: no_comma
271
+ SupportedStyles:
272
+ - comma
273
+ - consistent_comma
274
+ - no_comma
275
+ Style/TrailingCommaInLiteral:
276
+ Description: 'Checks for trailing comma in array and hash literals.'
277
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
278
+ Enabled: true
279
+ EnforcedStyleForMultiline: no_comma
280
+ SupportedStyles:
281
+ - comma
282
+ - consistent_comma
283
+ - no_comma
284
+ Style/VariableInterpolation:
285
+ Description: Don't interpolate global, instance and class variables directly in
286
+ strings.
287
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
288
+ Enabled: false
289
+ Style/WhenThen:
290
+ Description: Use when x then ... for one-line cases.
291
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
292
+ Enabled: false
293
+ Style/ZeroLengthPredicate:
294
+ Description: 'Use #empty? when testing for objects of length 0.'
295
+ Enabled: true
data/.travis.yml CHANGED
@@ -1,25 +1,24 @@
1
1
  language: ruby
2
2
 
3
3
  env:
4
- - "RAILS_VERSION=3.2"
5
4
  - "RAILS_VERSION=4.0"
6
5
  - "RAILS_VERSION=4.1"
7
6
  - "RAILS_VERSION=4.2"
8
7
  - "RAILS_VERSION=master"
9
8
 
10
9
  rvm:
11
- - 2.0
12
10
  - 2.1
13
- - 2.2.2
11
+ - 2.2
12
+ - 2.3.1
14
13
 
15
14
  matrix:
16
15
  allow_failures:
17
16
  - env: "RAILS_VERSION=master"
18
17
  exclude:
19
- - rvm: 2.0
20
- env: RAILS_VERSION=master
21
18
  - rvm: 2.1
22
19
  env: RAILS_VERSION=master
20
+ - rvm: 2.2
21
+ env: RAILS_VERSION=master
23
22
 
24
23
  before_install:
25
24
  - gem update bundler
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  # Change Log
2
2
 
3
- ## [Unreleased](https://github.com/houdini/two_factor_authentication/tree/HEAD)
3
+ ## [Unreleased](https://github.com/Houdini/two_factor_authentication/tree/HEAD)
4
4
 
5
- [Full Changelog](https://github.com/houdini/two_factor_authentication/compare/v1.1.4...HEAD)
5
+ [Full Changelog](https://github.com/Houdini/two_factor_authentication/compare/v1.1.5...HEAD)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Fix class detection in reset\_otp\_state\_for\(user\) [\#69](https://github.com/Houdini/two_factor_authentication/pull/69) ([monfresh](https://github.com/monfresh))
10
+ - Add ability to resend code [\#52](https://github.com/Houdini/two_factor_authentication/pull/52) ([iDiogenes](https://github.com/iDiogenes))
11
+
12
+ ## [v1.1.5](https://github.com/Houdini/two_factor_authentication/tree/v1.1.5) (2016-02-01)
13
+ [Full Changelog](https://github.com/Houdini/two_factor_authentication/compare/v1.1.4...v1.1.5)
6
14
 
7
15
  **Closed issues:**
8
16
 
@@ -10,12 +18,16 @@
10
18
 
11
19
  **Merged pull requests:**
12
20
 
21
+ - added french translation [\#68](https://github.com/Houdini/two_factor_authentication/pull/68) ([qsypoq](https://github.com/qsypoq))
22
+ - Drop support for Ruby 1.9.3 & update .travis.yml [\#67](https://github.com/Houdini/two_factor_authentication/pull/67) ([monfresh](https://github.com/monfresh))
23
+ - Fix reset\_otp\_state specs [\#66](https://github.com/Houdini/two_factor_authentication/pull/66) ([monfresh](https://github.com/monfresh))
24
+ - Add a CHANGELOG.md [\#65](https://github.com/Houdini/two_factor_authentication/pull/65) ([monfresh](https://github.com/monfresh))
13
25
  - Update bundler on Travis before installing gems [\#63](https://github.com/Houdini/two_factor_authentication/pull/63) ([monfresh](https://github.com/monfresh))
14
26
  - Add support for OTP secret key encryption [\#62](https://github.com/Houdini/two_factor_authentication/pull/62) ([monfresh](https://github.com/monfresh))
15
27
  - Allow executing code after sign in and before sign out [\#61](https://github.com/Houdini/two_factor_authentication/pull/61) ([monfresh](https://github.com/monfresh))
16
28
 
17
- ## [v1.1.4](https://github.com/houdini/two_factor_authentication/tree/v1.1.4) (2016-01-01)
18
- [Full Changelog](https://github.com/houdini/two_factor_authentication/compare/v1.1.3...v1.1.4)
29
+ ## [v1.1.4](https://github.com/Houdini/two_factor_authentication/tree/v1.1.4) (2016-01-01)
30
+ [Full Changelog](https://github.com/Houdini/two_factor_authentication/compare/v1.1.3...v1.1.4)
19
31
 
20
32
  **Closed issues:**
21
33
 
@@ -31,8 +43,8 @@
31
43
  - Test against Ruby 2.2 and Rails 4.2 [\#53](https://github.com/Houdini/two_factor_authentication/pull/53) ([boffbowsh](https://github.com/boffbowsh))
32
44
  - Eliminates appended '?' to redirects that have no query string [\#46](https://github.com/Houdini/two_factor_authentication/pull/46) ([daveriess](https://github.com/daveriess))
33
45
 
34
- ## [v1.1.3](https://github.com/houdini/two_factor_authentication/tree/v1.1.3) (2014-12-14)
35
- [Full Changelog](https://github.com/houdini/two_factor_authentication/compare/list...v1.1.3)
46
+ ## [v1.1.3](https://github.com/Houdini/two_factor_authentication/tree/v1.1.3) (2014-12-14)
47
+ [Full Changelog](https://github.com/Houdini/two_factor_authentication/compare/v1.1.2...v1.1.3)
36
48
 
37
49
  **Closed issues:**
38
50
 
@@ -45,11 +57,8 @@
45
57
  - Preserve query parameters in \_return\_to for redirect. [\#42](https://github.com/Houdini/two_factor_authentication/pull/42) ([omb-awong](https://github.com/omb-awong))
46
58
  - Add file extension to ActiveRecord generator [\#41](https://github.com/Houdini/two_factor_authentication/pull/41) ([jackturnbull](https://github.com/jackturnbull))
47
59
 
48
- ## [list](https://github.com/houdini/two_factor_authentication/tree/list) (2014-07-14)
49
- [Full Changelog](https://github.com/houdini/two_factor_authentication/compare/v1.1.2...list)
50
-
51
- ## [v1.1.2](https://github.com/houdini/two_factor_authentication/tree/v1.1.2) (2014-07-14)
52
- [Full Changelog](https://github.com/houdini/two_factor_authentication/compare/v1.1.1...v1.1.2)
60
+ ## [v1.1.2](https://github.com/Houdini/two_factor_authentication/tree/v1.1.2) (2014-07-14)
61
+ [Full Changelog](https://github.com/Houdini/two_factor_authentication/compare/v1.1.1...v1.1.2)
53
62
 
54
63
  **Closed issues:**
55
64
 
@@ -60,8 +69,8 @@
60
69
  - Updated readme with rake task to update existing users with OTP secret k... [\#39](https://github.com/Houdini/two_factor_authentication/pull/39) ([Znow](https://github.com/Znow))
61
70
  - Updated readme with view overriding [\#38](https://github.com/Houdini/two_factor_authentication/pull/38) ([Znow](https://github.com/Znow))
62
71
 
63
- ## [v1.1.1](https://github.com/houdini/two_factor_authentication/tree/v1.1.1) (2014-05-31)
64
- [Full Changelog](https://github.com/houdini/two_factor_authentication/compare/v1.1...v1.1.1)
72
+ ## [v1.1.1](https://github.com/Houdini/two_factor_authentication/tree/v1.1.1) (2014-05-31)
73
+ [Full Changelog](https://github.com/Houdini/two_factor_authentication/compare/v1.1...v1.1.1)
65
74
 
66
75
  **Closed issues:**
67
76
 
@@ -74,7 +83,7 @@
74
83
  - Chore/extract reused hash key [\#34](https://github.com/Houdini/two_factor_authentication/pull/34) ([rud](https://github.com/rud))
75
84
  - Pad OTP codes with less than 6 digits [\#31](https://github.com/Houdini/two_factor_authentication/pull/31) ([brissmyr](https://github.com/brissmyr))
76
85
 
77
- ## [v1.1](https://github.com/houdini/two_factor_authentication/tree/v1.1) (2014-04-16)
86
+ ## [v1.1](https://github.com/Houdini/two_factor_authentication/tree/v1.1) (2014-04-16)
78
87
  **Closed issues:**
79
88
 
80
89
  - Update [\#15](https://github.com/Houdini/two_factor_authentication/issues/15)
@@ -106,4 +115,5 @@
106
115
  - Add generators to make it easier to install and fix deprecation warnings [\#2](https://github.com/Houdini/two_factor_authentication/pull/2) ([carvil](https://github.com/carvil))
107
116
 
108
117
 
118
+
109
119
  \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
data/README.md CHANGED
@@ -1,16 +1,20 @@
1
1
  # Two factor authentication for Devise
2
2
 
3
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Houdini/two_factor_authentication?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+
3
5
  [![Build Status](https://travis-ci.org/Houdini/two_factor_authentication.svg?branch=master)](https://travis-ci.org/Houdini/two_factor_authentication)
4
- [![Code Climate](https://codeclimate.com/github/Houdini/two_factor_authentication.png)](https://codeclimate.com/github/Houdini/two_factor_authentication)
6
+ [![Code Climate](https://codeclimate.com/github/Houdini/two_factor_authentication.svg)](https://codeclimate.com/github/Houdini/two_factor_authentication)
5
7
 
6
8
  ## Features
7
9
 
8
- * configurable OTP code digit length
9
- * configurable max login attempts
10
- * customizable logic to determine if a user needs two factor authentication
11
- * customizable logic for sending the OTP code to the user
12
- * configurable period where users won't be asked for 2FA again
13
- * option to encrypt the OTP secret key in the database, with iv and salt
10
+ * Support for 2 types of OTP codes
11
+ 1. Codes delivered directly to the user
12
+ 2. TOTP (Google Authenticator) codes based on a shared secret (HMAC)
13
+ * Configurable OTP code digit length
14
+ * Configurable max login attempts
15
+ * Customizable logic to determine if a user needs two factor authentication
16
+ * Configurable period where users won't be asked for 2FA again
17
+ * Option to encrypt the TOTP secret in the database, with iv and salt
14
18
 
15
19
  ## Configuration
16
20
 
@@ -24,11 +28,12 @@ Once that's done, run:
24
28
 
25
29
  bundle install
26
30
 
27
- Note that Ruby 2.0 or greater is required.
31
+ Note that Ruby 2.1 or greater is required.
28
32
 
29
33
  ### Installation
30
34
 
31
35
  #### Automatic initial setup
36
+
32
37
  To set up the model and database migration file automatically, run the
33
38
  following command:
34
39
 
@@ -42,8 +47,12 @@ migration in `db/migrate/`, which will add the following columns to your table:
42
47
  - `:encrypted_otp_secret_key`
43
48
  - `:encrypted_otp_secret_key_iv`
44
49
  - `:encrypted_otp_secret_key_salt`
50
+ - `:direct_otp`
51
+ - `:direct_otp_sent_at`
52
+ - `:totp_timestamp`
45
53
 
46
54
  #### Manual initial setup
55
+
47
56
  If you prefer to set up the model and migration manually, add the
48
57
  `:two_factor_authentication` option to your existing devise options, such as:
49
58
 
@@ -55,7 +64,7 @@ devise :database_authenticatable, :registerable, :recoverable, :rememberable,
55
64
  Then create your migration file using the Rails generator, such as:
56
65
 
57
66
  ```
58
- rails g migration AddTwoFactorFieldsToUsers second_factor_attempts_count:integer encrypted_otp_secret_key:string:index encrypted_otp_secret_key_iv:string encrypted_otp_secret_key_salt:string
67
+ rails g migration AddTwoFactorFieldsToUsers second_factor_attempts_count:integer encrypted_otp_secret_key:string:index encrypted_otp_secret_key_iv:string encrypted_otp_secret_key_salt:string direct_otp:string direct_otp_sent_at:datetime totp_timestamp:timestamp
59
68
  ```
60
69
 
61
70
  Open your migration file (it will be in the `db/migrate` directory and will be
@@ -68,6 +77,7 @@ add_index :users, :encrypted_otp_secret_key, unique: true
68
77
  Save the file.
69
78
 
70
79
  #### Complete the setup
80
+
71
81
  Run the migration with:
72
82
 
73
83
  bundle exec rake db:migrate
@@ -80,21 +90,25 @@ Set config values in `config/initializers/devise.rb`:
80
90
 
81
91
  ```ruby
82
92
  config.max_login_attempts = 3 # Maximum second factor attempts count.
83
- config.allowed_otp_drift_seconds = 30 # Allowed time drift between client and server.
84
- config.otp_length = 6 # OTP code length
85
- config.remember_otp_session_for_seconds = 30.days # Time before browser has to enter OTP code again. Default is 0.
93
+ config.allowed_otp_drift_seconds = 30 # Allowed TOTP time drift between client and server.
94
+ config.otp_length = 6 # TOTP code length
95
+ config.direct_otp_valid_for = 5.minutes # Time before direct OTP becomes invalid
96
+ config.direct_otp_length = 6 # Direct OTP code length
97
+ config.remember_otp_session_for_seconds = 30.days # Time before browser has to perform 2fA again. Default is 0.
86
98
  config.otp_secret_encryption_key = ENV['OTP_SECRET_ENCRYPTION_KEY']
99
+ config.second_factor_resource_id = 'id' # Field or method name used to set value for 2fA remember cookie
87
100
  ```
88
101
  The `otp_secret_encryption_key` must be a random key that is not stored in the
89
102
  DB, and is not checked in to your repo. It is recommended to store it in an
90
103
  environment variable, and you can generate it with `bundle exec rake secret`.
91
104
 
92
- Override the method to send one-time passwords in your model. This is
93
- automatically called when a user logs in:
105
+ Override the method in your model in order to send direct OTP codes. This is
106
+ automatically called when a user logs in unless they have TOTP enabled (see
107
+ below):
94
108
 
95
109
  ```ruby
96
- def send_two_factor_authentication_code
97
- # use Model#otp_code and send via SMS, etc.
110
+ def send_two_factor_authentication_code(code)
111
+ # Send code via SMS, etc.
98
112
  end
99
113
  ```
100
114
 
@@ -113,7 +127,14 @@ In the example above, two factor authentication will not be required for local
113
127
  users.
114
128
 
115
129
  This gem is compatible with [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en).
116
- You can generate provisioning uris by invoking the following method on your model:
130
+ To enable this a shared secret must be generated by invoking the following
131
+ method on your model:
132
+
133
+ ```ruby
134
+ user.generate_totp_secret
135
+ ```
136
+
137
+ This must then be shared via a provisioning uri:
117
138
 
118
139
  ```ruby
119
140
  user.provisioning_uri # This assumes a user model with an email attribute
@@ -121,9 +142,7 @@ user.provisioning_uri # This assumes a user model with an email attribute
121
142
 
122
143
  This provisioning uri can then be turned in to a QR code if desired so that
123
144
  users may add the app to Google Authenticator easily. Once this is done, they
124
- may retrieve a one-time password directly from the Google Authenticator app as
125
- well as through whatever method you define in
126
- `send_two_factor_authentication_code`.
145
+ may retrieve a one-time password directly from the Google Authenticator app.
127
146
 
128
147
  #### Overriding the view
129
148
 
@@ -142,27 +161,33 @@ Below is an example using ERB:
142
161
  <% end %>
143
162
 
144
163
  <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
145
-
146
164
  ```
147
165
 
148
- #### Updating existing users with OTP secret key
166
+ #### Upgrading from version 1.X to 2.X
167
+
168
+ The following database fields are new in version 2.
169
+
170
+ - `direct_otp`
171
+ - `direct_otp_sent_at`
172
+ - `totp_timestamp`
149
173
 
150
- If you have existing users that need to be provided with a OTP secret key, so
151
- they can use two factor authentication, create a rake task. It could look like this one below:
174
+ To add them, generate a migration such as:
175
+
176
+ $ rails g migration AddTwoFactorFieldsToUsers direct_otp:string direct_otp_sent_at:datetime totp_timestamp:timestamp
177
+
178
+ The `otp_secret_key` is not only required for users who use Google Authentictor,
179
+ so unless it has been shared with the user it should be set to `nil`. The
180
+ following pseudo-code is an example of how this might be done:
152
181
 
153
182
  ```ruby
154
- desc 'rake task to update users with otp secret key'
155
- task :update_users_with_otp_secret_key => :environment do
156
- User.find_each do |user|
157
- user.otp_secret_key = ROTP::Base32.random_base32
158
- user.save!
159
- puts "Rake[:update_users_with_otp_secret_key] => OTP secret key set to '#{key}' for User '#{user.email}'"
183
+ User.find_each do |user| do
184
+ if !uses_authentictor_app(user)
185
+ user.otp_secret_key = nil
160
186
  end
161
187
  end
162
188
  ```
163
- Then run the task with `bundle exec rake update_users_with_otp_secret_key`
164
189
 
165
- #### Adding the OTP encryption option to an existing app
190
+ #### Adding the TOTP encryption option to an existing app
166
191
 
167
192
  If you've already been using this gem, and want to start encrypting the OTP
168
193
  secret key in the database (recommended), you'll need to perform the following
@@ -236,39 +261,6 @@ after them):
236
261
  bundle exec rake db:rollback STEP=3
237
262
  ```
238
263
 
239
- #### Executing some code after the user signs in and before they sign out
240
-
241
- In some cases, you might want to perform some action right after the user signs
242
- in, but before the OTP is sent, and also right before the user signs out. One
243
- scenario where you would need this is if you are requiring users to confirm
244
- their phone number first before they can receive an OTP. If they enter a wrong
245
- number, then sign out or close the browser before they confirm, they won't be
246
- able to confirm their real number. To solve this problem, we need to be able to
247
- reset their unconfirmed number before they sign out or sign in, and before the
248
- OTP code is sent.
249
-
250
- To define this action, create a `#{user.class}OtpSender` class that takes the
251
- current user as its parameter, and defines a `#reset_otp_state` instance method.
252
- For example, if your user's class is `User`, you would create a `UserOtpSender`
253
- class, like this:
254
- ```ruby
255
- class UserOtpSender
256
- def initialize(user)
257
- @user = user
258
- end
259
-
260
- def reset_otp_state
261
- if @user.unconfirmed_mobile.present?
262
- @user.update(unconfirmed_mobile: nil)
263
- end
264
- end
265
- end
266
- ```
267
- If you have different types of users in your app (for example, User and Admin),
268
- and you need different logic for each type of user, create a second class for
269
- your admin user, such as `AdminOtpSender`, with its own logic for
270
- `#reset_otp_state`.
271
-
272
264
  ### Example App
273
265
 
274
266
  [TwoFactorAuthenticationExample](https://github.com/Houdini/TwoFactorAuthenticationExample)