devise_instant2fa 1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a1b1be53c25de64e34b74a41cdd2e37a6b8cdfd9
4
+ data.tar.gz: 9314e6632e80fa4e8428a1ced354df19e461d967
5
+ SHA512:
6
+ metadata.gz: bd69fe2574166de4a5925bfe95210c2968c71eb0d7affffbb80e65e2263ce47548f654069fdb708ac8a014c319b013b805fd899550d86af7c4b46e448e127613
7
+ data.tar.gz: 55950735513bcf851f970886c1bff733aafa074e2e80434003136d87706e79eeab3980c557b62a6146379ab64b4c5d052d24d36cfd3264b8b664c78faf6a164d
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+
6
+ # Temporary files of every sort
7
+ .DS_Store
8
+ .idea
9
+ .rvmrc
10
+ .stgit*
11
+ *.swap
12
+ *.swo
13
+ *.swp
14
+ *~
15
+ bin/*
16
+ nbproject
17
+ patches-*
18
+ capybara-*.html
19
+ dump.rdb
20
+ *.ids
21
+ .rbenv-version
22
+ .ruby-gemset
23
+ .ruby-version
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 ADDED
@@ -0,0 +1,29 @@
1
+ language: ruby
2
+
3
+ env:
4
+ - "RAILS_VERSION=4.0"
5
+ - "RAILS_VERSION=4.1"
6
+ - "RAILS_VERSION=4.2"
7
+ - "RAILS_VERSION=master"
8
+
9
+ rvm:
10
+ - 2.1
11
+ - 2.2
12
+ - 2.3.1
13
+
14
+ matrix:
15
+ allow_failures:
16
+ - env: "RAILS_VERSION=master"
17
+ exclude:
18
+ - rvm: 2.1
19
+ env: RAILS_VERSION=master
20
+ - rvm: 2.2
21
+ env: RAILS_VERSION=master
22
+
23
+ before_install:
24
+ - gem update bundler
25
+
26
+ before_script:
27
+ - bundle exec rake app:db:migrate
28
+
29
+ script: bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,31 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in devise_ip_filter.gemspec
4
+ gemspec
5
+
6
+ rails_version = ENV["RAILS_VERSION"] || "default"
7
+
8
+ rails = case rails_version
9
+ when "master"
10
+ {github: "rails/rails"}
11
+ when "default"
12
+ "~> 4.1"
13
+ else
14
+ "~> #{rails_version}"
15
+ end
16
+
17
+ gem "rails", rails
18
+
19
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.2.0')
20
+ gem "test-unit", "~> 3.0"
21
+ end
22
+
23
+ group :test, :development do
24
+ gem 'sqlite3'
25
+ end
26
+
27
+ group :test do
28
+ gem 'rack_session_access'
29
+ gem 'ammeter'
30
+ gem 'pry'
31
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2016 Clef, Inc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Instant 2FA for Devise
2
+
3
+ ## Configuration
4
+
5
+ ### Initial Setup
6
+
7
+ In a Rails environment, require the gem in your Gemfile:
8
+
9
+ gem 'devise_instant2fa'
10
+
11
+ Once that's done, run:
12
+
13
+ bundle install
14
+
15
+ Note that Ruby 2.1 or greater is required.
16
+
17
+ ### Installation
18
+
19
+ #### Configuration
20
+
21
+ In order to use Instant 2FA, you'll need to configure your `access_key` and `access_secret` in the `config/initializers/devise.rb` file:
22
+
23
+ ```ruby
24
+ config.instant2fa_access_key = 'YOUR_ACCESS_KEY'
25
+ config.instant2fa_access_secret = 'YOUR_ACCESS_SECRET'
26
+ ```
27
+
28
+ After you've updated your configuration settings, you'll need to add the `:instant2fa_authenticatable` strategy to your user (likely in your `user.rb` file):
29
+
30
+ ```ruby
31
+ devise :instant2fa_authenticatable, :database_authenticatable, :registerable, :recoverable, :rememberable,
32
+ :trackable, :validatable
33
+ ```
34
+
35
+ With those changes enabled, users who enable Instant 2FA will be prompted for verification on login.
36
+
37
+ ### Customisation and Usage
38
+
39
+ #### Adding the user settings page
40
+
41
+ Instant 2FA automatically provides a hosted user settings page. This library provies view helpers to embed that page in your user experience. To use the helpers, you'll need to include the `DeviseInstant2fa::Views::Helpers` module in your `ApplicationHelpers` (or in a more specific module):
42
+
43
+ ```ruby
44
+ module ApplicationHelper
45
+ include DeviseInstant2fa::Views::Helpers
46
+ end
47
+ ```
48
+
49
+ Once this is included, you'll have access to the `instant2fa_settings_view(user)` method, which you can use in any view:
50
+
51
+ ```html
52
+ <div class="two-factor-settings">
53
+ <%= instant2fa_settings_view(resource) %>
54
+ </div>
55
+ ````
56
+
57
+ #### Overriding the verification view
58
+
59
+ The default view that shows the form can be overridden by adding a file named `show.html.erb` (or `show.html.haml` if you prefer HAML) inside `app/views/devise/instant2fa/` and customizing it. The important element to display is the `instant2fa_verification_form` helper.
60
+
61
+ Below is an example using ERB:
62
+
63
+ ```html
64
+ <p><%= flash[:notice] %></p>
65
+
66
+ <%= instant2fa_verification_form(resource_name, @hosted_page_url)%>
67
+ ```
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ APP_RAKEFILE = File.expand_path("../spec/rails_app/Rakefile", __FILE__)
4
+ load 'rails/tasks/engine.rake'
5
+
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc "Run all specs in spec directory (excluding plugin specs)"
9
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
10
+
11
+ task :default => :spec
12
+
13
+ # To test against a specific version of Rails
14
+ # export RAILS_VERSION=3.2.0; bundle update; rake
@@ -0,0 +1,57 @@
1
+ class Devise::Instant2faController < DeviseController
2
+ prepend_before_action :find_resource_and_require_password_checked, :only => [
3
+ :show, :update
4
+ ]
5
+
6
+ def show
7
+ @hosted_page_url = session["#{resource_name}_hosted_page_url"]
8
+ end
9
+
10
+ def update
11
+ render :show and return if params[:instant2faToken].nil?
12
+
13
+ begin
14
+ Instant2fa.confirm_verification(@resource.id.to_s, params[:instant2faToken])
15
+ after_two_factor_success_for(@resource)
16
+ rescue Instant2fa::Errors::VerificationMismatch
17
+ after_two_factor_fail_for(@resource)
18
+ rescue Instant2fa::Errors::VerificationFailed
19
+ after_two_factor_fail_for(@resource)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def find_resource
26
+ @resource = send("current_#{resource_name}")
27
+
28
+ if @resource.nil?
29
+ @resource = resource_class.find_by_id(session["#{resource_name}_id"])
30
+ end
31
+ end
32
+
33
+ def find_resource_and_require_password_checked
34
+ find_resource
35
+
36
+ if @resource.nil? || session[:"#{resource_name}_password_checked"].to_s != "true"
37
+ redirect_to invalid_resource_path
38
+ end
39
+ end
40
+
41
+ def after_two_factor_success_for(resource)
42
+ remember_device if params[:remember_device].to_i == 1
43
+ if session.delete("#{resource_name}_remember_me") == true && resource.respond_to?(:remember_me=)
44
+ resource.remember_me = true
45
+ end
46
+ sign_in(resource_name, resource)
47
+
48
+ set_flash_message(:notice, :signed_in) if is_navigational_format?
49
+ respond_with resource, :location => after_sign_in_path_for(resource)
50
+ end
51
+
52
+ def after_two_factor_fail_for(resource)
53
+ set_flash_message :alert, :attempt_failed, now: true
54
+ sign_out(resource)
55
+ redirect_to :root
56
+ end
57
+ end
@@ -0,0 +1,2 @@
1
+ <p><%= flash[:notice] %></p>
2
+ <%= instant2fa_verification_form(resource_name, @hosted_page_url)%>
@@ -0,0 +1,7 @@
1
+ en:
2
+ devise:
3
+ instant2fa:
4
+ user:
5
+ signed_in: "Two factor authentication successful."
6
+ success: "Two factor authentication successful."
7
+ attempt_failed: "Two factor authentication failed."
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "devise_instant2fa/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "devise_instant2fa"
7
+ s.version = DeviseInstant2fa::VERSION.dup
8
+ s.authors = ["Jesse Pollak"]
9
+ s.email = ["jesse@instant2fa.com"]
10
+ s.homepage = "https://github.com/clef/instant2fa-devise"
11
+ s.summary = %q{Instant 2FA plugin for devise}
12
+
13
+ s.rubyforge_project = "devise_instant2fa"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency 'rails', '>= 3.1.1'
21
+ s.add_runtime_dependency 'devise'
22
+ s.add_runtime_dependency 'instant2fa', '~> 1'
23
+
24
+ s.add_development_dependency 'bundler'
25
+ s.add_development_dependency 'rake'
26
+ s.add_development_dependency 'rspec-rails', '>= 3.0.1'
27
+ s.add_development_dependency 'capybara', '2.4.1'
28
+ s.add_development_dependency 'pry'
29
+ s.add_development_dependency 'timecop'
30
+ end
@@ -0,0 +1,61 @@
1
+ module DeviseInstant2fa
2
+ module Controllers
3
+ module Helpers
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_action :handle_two_factor_authentication, :if => :is_signing_in?
8
+ end
9
+
10
+ def is_devise_sessions_controller?
11
+ self.class == Devise::SessionsController || self.class.ancestors.include?(Devise::SessionsController)
12
+ end
13
+
14
+ def is_signing_in?
15
+ if devise_controller? && signed_in?(resource_name) &&
16
+ is_devise_sessions_controller? &&
17
+ self.action_name == "create"
18
+ return true
19
+ end
20
+
21
+ return false
22
+ end
23
+
24
+ private
25
+
26
+ def handle_two_factor_authentication
27
+ Devise.mappings.keys.flatten.any? do |scope|
28
+ if signed_in?(scope) and warden.session(scope)[DeviseInstant2fa::NEED_AUTHENTICATION]
29
+ check_request_and_redirect_to_verify(scope)
30
+ end
31
+ end
32
+ end
33
+
34
+ def check_request_and_redirect_to_verify(scope)
35
+ id = warden.session(resource_name)[:id]
36
+ hosted_page_url = warden.session(resource_name)[DeviseInstant2fa::HOSTED_PAGE_URL]
37
+
38
+ remember_me = (params.fetch(resource_name, {})[:remember_me].to_s == "1")
39
+ return_to = session["#{resource_name}_return_to"]
40
+ warden.logout
41
+ warden.reset_session! # make sure the session reset
42
+
43
+ session["#{resource_name}_id"] = id
44
+ session["#{resource_name}_hosted_page_url"] = hosted_page_url
45
+ # this is safe to put in the session because the cookie is signed
46
+ session["#{resource_name}_password_checked"] = true
47
+ session["#{resource_name}_remember_me"] = remember_me
48
+ session["#{resource_name}_return_to"] = return_to if return_to
49
+
50
+ redirect_to two_factor_authentication_path_for(scope)
51
+ return
52
+ end
53
+
54
+ def two_factor_authentication_path_for(resource_or_scope = nil)
55
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
56
+ change_path = "#{scope}_two_factor_authentication_path"
57
+ send(change_path)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ require 'instant2fa'
2
+
3
+ Warden::Manager.after_authentication do |user, auth, options|
4
+ begin
5
+ hosted_page_url = Instant2fa.create_verification(user.id.to_s)
6
+ auth.session(options[:scope])[DeviseInstant2fa::NEED_AUTHENTICATION] = true
7
+ auth.session(options[:scope])[DeviseInstant2fa::HOSTED_PAGE_URL] = hosted_page_url
8
+ auth.session(options[:scope])[:id] = user.id
9
+ rescue Instant2fa::Errors::MFANotEnabled
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module DeviseInstant2fa
2
+ class Engine < ::Rails::Engine
3
+ ActiveSupport.on_load(:action_controller) do
4
+ include DeviseInstant2fa::Controllers::Helpers
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ protected
4
+
5
+ def devise_instant2fa(mapping, controllers)
6
+ resource :two_factor_authentication, :only => [:show, :update], :path => 'verify', :controller => controllers[:instant2fa] do
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module DeviseInstant2fa
2
+ VERSION = "1.0.0".freeze
3
+ end
@@ -0,0 +1,21 @@
1
+ module DeviseInstant2fa
2
+ module Views
3
+ module Helpers
4
+ def instant2fa_settings_view(resource)
5
+ instant2fa_javascript_tag resource.instant2fa_settings_url
6
+ end
7
+
8
+ def instant2fa_verification_form(resource_name, url)
9
+ form_tag([resource_name, :two_factor_authentication], :method => :put) do
10
+ instant2fa_javascript_tag url
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def instant2fa_javascript_tag(uri)
17
+ javascript_include_tag 'https://js.instant2fa.com/hosted.js', class: 'instant2fa-page', 'data-uri' => uri
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,61 @@
1
+ require 'devise_instant2fa/version'
2
+ require 'devise'
3
+ require 'active_support/concern'
4
+ require 'active_support/core_ext/class/attribute_accessors'
5
+ require 'instant2fa'
6
+
7
+ module Devise
8
+
9
+ @@instant2fa_access_key = nil
10
+ def self.instant2fa_access_key
11
+ @@instant2fa_access_key
12
+ end
13
+
14
+ def self.instant2fa_access_key=(instant2fa_access_key)
15
+ @@instant2fa_access_key = @@instant2fa_access_key
16
+ Instant2fa.configure do |config|
17
+ config.access_key = instant2fa_access_key
18
+ end
19
+ end
20
+
21
+ @@instant2fa_access_secret = nil
22
+ def self.instant2fa_access_secret
23
+ @@instant2fa_access_secret
24
+ end
25
+
26
+ def self.instant2fa_access_secret=(instant2fa_access_secret)
27
+ @@instant2fa_access_secret = @@instant2fa_access_secret
28
+ Instant2fa.configure do |config|
29
+ config.access_secret = instant2fa_access_secret
30
+ end
31
+ end
32
+ end
33
+
34
+ module DeviseInstant2fa
35
+ NEED_AUTHENTICATION = 'need_two_factor_authentication'
36
+ HOSTED_PAGE_URL = 'hosted_page_url'
37
+
38
+ module Controllers
39
+ autoload :Helpers, 'devise_instant2fa/controllers/helpers'
40
+ end
41
+
42
+ module Views
43
+ autoload :Helpers, 'devise_instant2fa/views/helpers'
44
+ end
45
+ end
46
+
47
+ module Devise
48
+ module Models
49
+ module Instant2faAuthenticatable
50
+ def instant2fa_settings_url
51
+ Instant2fa.create_settings(self.id)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ Devise.add_module :instant2fa_authenticatable, :controller => :instant2fa, :route => :instant2fa
58
+
59
+ require 'devise_instant2fa/hooks/instant2fa_authenticatable'
60
+ require 'devise_instant2fa/routes'
61
+ require 'devise_instant2fa/rails'
@@ -0,0 +1,26 @@
1
+ ENV["RAILS_ENV"] ||= "test"
2
+ require File.expand_path("../rails_app/config/environment.rb", __FILE__)
3
+
4
+ require 'rspec/rails'
5
+ require 'timecop'
6
+ require 'rack_session_access/capybara'
7
+
8
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
+ RSpec.configure do |config|
10
+ config.run_all_when_everything_filtered = true
11
+ config.filter_run :focus
12
+
13
+ config.use_transactional_examples = true
14
+
15
+ config.include Capybara::DSL
16
+
17
+ # Run specs in random order to surface order dependencies. If you find an
18
+ # order dependency and want to debug it, you can fix the order by providing
19
+ # the seed, which is printed after each run.
20
+ # --seed 1234
21
+ config.order = 'random'
22
+
23
+ config.after(:each) { Timecop.return }
24
+ end
25
+
26
+ Dir["#{Dir.pwd}/spec/support/**/*.rb"].each {|f| require f}
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devise_instant2fa
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jesse Pollak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: devise
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: instant2fa
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 3.0.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 3.0.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: capybara
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 2.4.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 2.4.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: timecop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description:
140
+ email:
141
+ - jesse@instant2fa.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - ".rubocop.yml"
148
+ - ".travis.yml"
149
+ - Gemfile
150
+ - LICENSE
151
+ - README.md
152
+ - Rakefile
153
+ - app/controllers/devise/instant2fa_controller.rb
154
+ - app/views/devise/instant2fa/show.html.erb
155
+ - config/locales/en.yml
156
+ - devise_instant2fa.gemspec
157
+ - lib/devise_instant2fa.rb
158
+ - lib/devise_instant2fa/controllers/helpers.rb
159
+ - lib/devise_instant2fa/hooks/instant2fa_authenticatable.rb
160
+ - lib/devise_instant2fa/rails.rb
161
+ - lib/devise_instant2fa/routes.rb
162
+ - lib/devise_instant2fa/version.rb
163
+ - lib/devise_instant2fa/views/helpers.rb
164
+ - spec/spec_helper.rb
165
+ homepage: https://github.com/clef/instant2fa-devise
166
+ licenses: []
167
+ metadata: {}
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ requirements: []
183
+ rubyforge_project: devise_instant2fa
184
+ rubygems_version: 2.5.1
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Instant 2FA plugin for devise
188
+ test_files:
189
+ - spec/spec_helper.rb