two_factor_authentication 1.1.5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.codeclimate.yml +21 -0
- data/.rubocop.yml +295 -0
- data/.travis.yml +4 -5
- data/CHANGELOG.md +24 -14
- data/README.md +57 -65
- data/app/controllers/devise/two_factor_authentication_controller.rb +28 -12
- data/app/views/devise/two_factor_authentication/show.html.erb +10 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +8 -0
- data/config/locales/fr.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/lib/generators/active_record/templates/migration.rb +3 -0
- data/lib/two_factor_authentication.rb +9 -0
- data/lib/two_factor_authentication/controllers/helpers.rb +1 -1
- data/lib/two_factor_authentication/hooks/two_factor_authenticatable.rb +4 -23
- data/lib/two_factor_authentication/models/two_factor_authenticatable.rb +68 -19
- data/lib/two_factor_authentication/routes.rb +3 -1
- data/lib/two_factor_authentication/schema.rb +12 -0
- data/lib/two_factor_authentication/version.rb +1 -1
- data/spec/controllers/two_factor_authentication_controller_spec.rb +2 -2
- data/spec/features/two_factor_authenticatable_spec.rb +36 -73
- data/spec/lib/two_factor_authentication/models/two_factor_authenticatable_spec.rb +137 -80
- data/spec/rails_app/app/controllers/home_controller.rb +1 -1
- data/spec/rails_app/app/models/admin.rb +6 -0
- data/spec/rails_app/app/models/encrypted_user.rb +2 -1
- data/spec/rails_app/app/models/guest_user.rb +8 -1
- data/spec/rails_app/app/models/user.rb +2 -2
- data/spec/rails_app/config/initializers/devise.rb +2 -2
- data/spec/rails_app/config/routes.rb +1 -0
- data/spec/rails_app/db/migrate/20140403184646_devise_create_users.rb +1 -1
- data/spec/rails_app/db/migrate/20160209032439_devise_create_admins.rb +42 -0
- data/spec/rails_app/db/schema.rb +19 -1
- data/spec/support/authenticated_model_helper.rb +22 -15
- data/spec/support/controller_helper.rb +1 -1
- data/spec/support/totp_helper.rb +11 -0
- data/two_factor_authentication.gemspec +1 -1
- metadata +74 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 780c92dea8df1f3f6d1e761562e1469cc12a96a8
|
4
|
+
data.tar.gz: 82e383a9f79a3628e9950a17da920eeed8464622
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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/
|
3
|
+
## [Unreleased](https://github.com/Houdini/two_factor_authentication/tree/HEAD)
|
4
4
|
|
5
|
-
[Full Changelog](https://github.com/
|
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/
|
18
|
-
[Full Changelog](https://github.com/
|
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/
|
35
|
-
[Full Changelog](https://github.com/
|
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
|
-
## [
|
49
|
-
[Full Changelog](https://github.com/
|
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/
|
64
|
-
[Full Changelog](https://github.com/
|
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/
|
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
|
+
[](https://gitter.im/Houdini/two_factor_authentication?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
4
|
+
|
3
5
|
[](https://travis-ci.org/Houdini/two_factor_authentication)
|
4
|
-
[](https://codeclimate.com/github/Houdini/two_factor_authentication)
|
5
7
|
|
6
8
|
## Features
|
7
9
|
|
8
|
-
*
|
9
|
-
|
10
|
-
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
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.
|
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 #
|
85
|
-
config.
|
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
|
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
|
-
#
|
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
|
-
|
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
|
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
|
-
####
|
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
|
-
|
151
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
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
|
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)
|