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.
- 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
|
+
[![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.
|
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
|
-
*
|
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)
|