devise-authy 1.10.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2944ca880949d1d99ba1116f87399c9be0043cc210d29c4d5c500b08b74a3ba
4
- data.tar.gz: 400fe93a97c18c62904d7f3b2795193bdfe724b4022c677bf20a507f12881cab
3
+ metadata.gz: e9332df09a8a1b3e1a71ff775f2cccc75c573123eccb8a6830454cdc3ef3834d
4
+ data.tar.gz: a0e4f00b59ece3eefe9fee9c04c51227216e13f241ac24afe94c4ec361416443
5
5
  SHA512:
6
- metadata.gz: 394a6c85daf4d32bd9a7f8be985cdb81dbc6aad4578b317bfbf2cd0514226bbef466fe0f3831b85034d7de6d99d7be2f4c461243705bb1936491e9454d595360
7
- data.tar.gz: a5defe4716260f048cf8080bd40fa47d4fb13da62ed42a75461b62c46c0b4b7eba25d6d8896064666e8252364d6da159b4375111019174591dc1f2b046f370ed
6
+ metadata.gz: 3d00cb1eb54d0169277b2e514431bb121f8c5e2dc6a565e07786a4866a29904b301a3730cdbff201f48d1ba5afb4c8b10249b75e9c8ab45da8a0022b9b1f64f9
7
+ data.tar.gz: 54596845d7b20034aa433497281d74135886f59828e9ae8026ae9fc43f0cfe2b4874cd90c4d69f8295ff76bc02ac7eaadb077fd53d1281354f7a3aa113dac65e
data/.gitignore CHANGED
@@ -31,14 +31,15 @@ build/
31
31
  Gemfile.lock
32
32
  .ruby-version
33
33
  .ruby-gemset
34
+ gemfiles/*.lock
34
35
 
35
36
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
37
  .rvmrc
37
38
 
38
- spec/rails-app/tmp
39
- spec/rails-app/db
40
- spec/rails-app/log
41
- *.sqlite3DS_Store
39
+ **/*.sqlite
40
+ **/*.log
42
41
 
43
42
  initializers/authy.rb
44
43
  .byebug_history
44
+
45
+ .rspec_status
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --require ./spec/spec_helper
@@ -1,12 +1,17 @@
1
1
  language: ruby
2
- before_install: cd spec/rails-app && bundle install
3
2
  script: bundle exec rspec
4
3
  rvm:
4
+ - 2.7
5
+ - 2.6
5
6
  - 2.5
6
7
  - 2.4
7
- - 2.3
8
- - 2.2
9
8
  - ruby-head
9
+ gemfile:
10
+ - gemfiles/rails_5_2.gemfile
11
+ - gemfiles/rails_6.gemfile
10
12
  matrix:
11
13
  allow_failures:
12
14
  - rvm: ruby-head
15
+ exclude:
16
+ - rvm: 2.4
17
+ gemfile: gemfiles/rails_6.gemfile
@@ -0,0 +1,21 @@
1
+ appraise "rails-5-2" do
2
+ gem "rails", "~> 5.2.0"
3
+ gem "sqlite3", "~> 1.3.13"
4
+
5
+ group :development, :test do
6
+ gem 'factory_girl_rails', :require => false
7
+ gem 'rspec-rails', "~>4.0.0.beta3", :require => false
8
+ gem 'database_cleaner', :require => false
9
+ end
10
+ end
11
+
12
+ appraise "rails-6" do
13
+ gem "rails", "~> 6.0.0"
14
+ gem "sqlite3", "~> 1.4"
15
+
16
+ group :development, :test do
17
+ gem 'factory_girl_rails', :require => false
18
+ gem 'rspec-rails', "~>4.0.0.beta3", :require => false
19
+ gem 'database_cleaner', :require => false
20
+ end
21
+ end if RUBY_VERSION.to_f >= 2.5
@@ -9,49 +9,127 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
9
9
 
10
10
  ...
11
11
 
12
+ ## [2.2.0] - 2020-06-04
13
+
14
+ ### Fixed
15
+
16
+ - Don't delete user in Authy if another user has the same authy_id (#144)
17
+
18
+ ## [2.1.0] - 2020-05-05
19
+
20
+ ### Added
21
+
22
+ - Support for generic authenticator tokens (#141)
23
+
24
+ ### Fixed
25
+
26
+ - Can remember device when enabling 2FA for the first time (#139)
27
+
28
+ ## [2.0.0] - 2020-04-28
29
+
30
+ Releasing this as version 2 because there is a significant change in dependencies. Minimum version of Rails is now 5 and of Devise is now 4. Otherwise the gem should work as before.
31
+
32
+ ### Added
33
+
34
+ - HTTP Only flag to remember_device cookie (#116 thanks @agronv)
35
+ - Remembers device when user logs in with One Touch (#128 thanks @cplopez4)
36
+ - Autocomplete attributes for HTML form (#130)
37
+
38
+ ### Changed
39
+
40
+ - Mocked API calls in test suite (#123)
41
+ - Full test suite refactor (#124)
42
+ - Increased required version for Devise and Rails (#125)
43
+ - Stopped calling `signed_in?` before it is needed (#126)
44
+
45
+ ### Fixes
46
+
47
+ - Remembers user correctly when logging in with One Touch (#129)
48
+
49
+ ## [1.11.1] - 2019-02-02
50
+
51
+ ### Fixed
52
+
53
+ - Using the version before loading it broke everything. :facepalm:
54
+
55
+ ## [1.11.0] - 2019-02-01
56
+
57
+ ### Fixed
58
+
59
+ - Corrects for label in verify_authy view (#103 thanks @mstruebing)
60
+ - Corrects heading in verify_authy view (#104 thanks @mstruebing)
61
+
62
+ ### Changed
63
+
64
+ - Allows you to define paths for request_sms and request_phone_call (#108 thanks @dedene)
65
+
66
+ ### Added
67
+
68
+ - Now sets a distinct user agent through the Authy gem (#110)
69
+
12
70
  ## [1.10.0] - 2018-09-26
13
71
 
14
72
  ### Changed
73
+
15
74
  - Moves OneTouch approval request copy to locale file.
16
75
 
17
76
  ### Removed
77
+
18
78
  - Demo app now lives in its own repo
19
79
 
20
80
  ## [1.9.0] - 2018-09-04
21
81
 
22
82
  ### Fixed
83
+
23
84
  - Generated migration now includes version number for Rails 5
24
85
 
25
86
  ### Changed
87
+
26
88
  - Removes Jeweler in favour of administering the gemspec by hand
27
89
  - Removes demo app files from gem package
28
90
 
29
91
  ## [1.8.3] - 2018-07-05
92
+
30
93
  ### Fixed
94
+
31
95
  - Fixes Ruby interpolation in HAML for onetouch (thanks @muan)
32
96
  - Records Authy authentication after install verification (thanks @nukturnal)
33
97
  - Forgets remember device cookie when disabling Authy (thanks @senekis)
34
98
 
35
99
  ### Changed
100
+
36
101
  - Updated testing Rubies in CI
37
102
 
38
103
  ## Older releases
39
104
 
40
- __*The following releases happened before the changelog was started. Some history will be added for clarity.*__
105
+ **_The following releases happened before the changelog was started. Some history will be added for clarity._**
41
106
 
42
107
  ## [1.8.2] - 2017-12-22
108
+
43
109
  ## [1.8.1] - 2016-12-06
110
+
44
111
  ## [1.8.0] - 2016-10-25
112
+
45
113
  ## [1.7.0] - 2015-12-22
114
+
46
115
  ## [1.6.0] - 2015-01-07
116
+
47
117
  ## [1.5.3] - 2014-06-11
118
+
48
119
  ## [1.5.2] - 2014-06-11
120
+
49
121
  ## [1.5.1] - 2014-04-24
122
+
50
123
  ## [1.5.0] - 2014-01-07
124
+
51
125
  ## [1.4.0] - 2013-12-17
126
+
52
127
  ## [1.3.0] - 2013-11-16
128
+
53
129
  ## [1.2.2] - 2013-09-04
130
+
54
131
  ## [1.2.1] - 2013-04-22
132
+
55
133
  ## [1.2.0] - 2013-04-22 [YANKED]
56
- ## [1.0.0] - 2013-04-10
57
134
 
135
+ ## [1.0.0] - 2013-04-10
data/Gemfile CHANGED
@@ -2,28 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- group :test do
6
- gem 'rails', '~> 4.2.7'
7
- gem 'sqlite3'
8
-
9
- # Use SCSS for stylesheets
10
- gem 'sass-rails', '~> 5.0'
11
-
12
- # Use Uglifier as compressor for JavaScript assets
13
- gem 'uglifier', '>= 1.3.0'
14
-
15
- # Use CoffeeScript for .coffee assets and views
16
- gem 'coffee-rails', '~> 4.1.0'
17
-
18
- # Use jquery as the JavaScript library
19
- gem 'jquery-rails'
20
-
21
- gem 'launchy'
22
- gem 'rspec-rails'
23
- gem 'database_cleaner'
24
- gem 'capybara'
25
- gem 'test-unit'
26
- end
27
-
28
5
  # bundle exec rake doc:rails generates the API under doc/api.
29
6
  gem 'sdoc', '~> 0.4.0', group: :doc
data/README.md CHANGED
@@ -1,10 +1,28 @@
1
1
  # Authy Devise [![Build Status](https://travis-ci.org/twilio/authy-devise.svg?branch=master)](https://travis-ci.org/twilio/authy-devise)
2
2
 
3
- This is a [Devise](https://github.com/plataformatec/devise) extension to add Two-Factor Authentication with Authy to your rails application.
3
+ This is a [Devise](https://github.com/plataformatec/devise) extension to add [Two-Factor Authentication with Authy](https://www.twilio.com/docs/authy) to your Rails application.
4
+
5
+ * [Pre-requisites](#pre-requisites)
6
+ * [Demo](#demo)
7
+ * [Getting started](#getting-started)
8
+ * [Configuring Models](#configuring-models)
9
+ * [With the generator](#with-the-generator)
10
+ * [Manually](#manually)
11
+ * [Final steps](#final-steps)
12
+ * [Custom Views](#custom-views)
13
+ * [Request a phone call](#request-a-phone-call)
14
+ * [Custom Redirect Paths (eg. using modules)](#custom-redirect-paths-eg-using-modules)
15
+ * [I18n](#i18n)
16
+ * [Session variables](#session-variables)
17
+ * [OneTouch support](#onetouch-support)
18
+ * [Generic authenticator token support](#generic-authenticator-token-support)
19
+ * [Rails 5 CSRF protection](#rails-5-csrf-protection)
20
+ * [Running Tests](#running-tests)
21
+ * [Copyright](#copyright)
4
22
 
5
23
  ## Pre-requisites
6
24
 
7
- To use the Authy API you will need a Twilio Account, [sign up for a free account here](https://www.twilio.com/try-twilio).
25
+ To use the Authy API you will need a Twilio Account, [sign up for a free Twilio account here](https://www.twilio.com/try-twilio).
8
26
 
9
27
  Create an [Authy Application in the Twilio console](https://www.twilio.com/console/authy/applications) and take note of the API key.
10
28
 
@@ -38,17 +56,55 @@ Add `Devise Authy` to your App:
38
56
 
39
57
  ### Configuring Models
40
58
 
41
- Configure your Devise user model:
59
+ You can add devise_authy to your user model in two ways.
42
60
 
43
- rails g devise_authy [MODEL_NAME]
61
+ #### With the generator
44
62
 
45
- or add the following line to your `User` model
63
+ This is the easiest way and is recommended. Run the following command:
64
+
65
+ ```bash
66
+ rails g devise_authy [MODEL_NAME]
67
+ ```
68
+
69
+ #### Manually
70
+
71
+ Add `:authy_authenticatable` to the `devise` options in your Devise user model:
46
72
 
47
73
  ```ruby
48
74
  devise :authy_authenticatable, :database_authenticatable
49
75
  ```
50
76
 
51
- Update the default routes to point to something like:
77
+ Also add a new migration. For example, if you are adding to the `User` model, use this migration:
78
+
79
+ ```ruby
80
+ class DeviseAuthyAddToUsers < ActiveRecord::Migration[6.0]
81
+ def self.up
82
+ change_table :users do |t|
83
+ t.string :authy_id
84
+ t.datetime :last_sign_in_with_authy
85
+ t.boolean :authy_enabled, :default => false
86
+ end
87
+
88
+ add_index :users, :authy_id
89
+ end
90
+
91
+ def self.down
92
+ change_table :users do |t|
93
+ t.remove :authy_id, :last_sign_in_with_authy, :authy_enabled
94
+ end
95
+ end
96
+ end
97
+ ```
98
+
99
+ #### Final steps
100
+
101
+ For either method above, run the migrations:
102
+
103
+ ```bash
104
+ rake db:migrate
105
+ ```
106
+
107
+ **[Optional]** Update the default routes to point to something like:
52
108
 
53
109
  ```ruby
54
110
  devise_for :users, :path_names => {
@@ -59,10 +115,6 @@ devise_for :users, :path_names => {
59
115
  }
60
116
  ```
61
117
 
62
- Then run the migrations:
63
-
64
- rake db:migrate
65
-
66
118
  Now whenever a user wants to enable two-factor authentication they can go to:
67
119
 
68
120
  http://your-app/users/enable-two-factor
@@ -71,7 +123,6 @@ And when the user logs in they will be redirected to:
71
123
 
72
124
  http://your-app/users/verify-token
73
125
 
74
-
75
126
  ## Custom Views
76
127
 
77
128
  If you want to customise your views, you can modify the files that are located at:
@@ -118,7 +169,6 @@ And tell the router to use this controller
118
169
  devise_for :users, controllers: {devise_authy: 'my_custom_module/devise_authy'}
119
170
  ```
120
171
 
121
-
122
172
  ## I18n
123
173
 
124
174
  The install generator also copies a `Devise Authy` i18n file which you can find at:
@@ -145,10 +195,36 @@ To enable [Authy push authentication](https://www.twilio.com/authy/features/push
145
195
  config.authy_enable_onetouch = true
146
196
  ```
147
197
 
198
+ ## Generic authenticator token support
199
+
200
+ Authy supports other authenticator apps by providing a QR code that your users can scan.
201
+
202
+ > **To use this feature, you need to enable it in your [Twilio Console](https://www.twilio.com/console/authy/applications)**
203
+
204
+ Once you have enabled generic authenticator tokens, you can enable this in devise-authy by modifying the Devise config file `config/initializers/devise.rb` and adding the configuration:
205
+
206
+ ```
207
+ config.authy_enable_qr_code = true
208
+ ```
209
+
210
+ This will display a QR code on the verification screen (you still need to take a user's phone number and country code). If you have implemented your own views, the QR code URL is available on the verification page as `@authy_qr_code`.
211
+
212
+ ## Rails 5 CSRF protection
213
+
214
+ In Rails 5 `protect_from_forgery` is no longer prepended to the `before_action` chain. If you call `authenticate_user` before `protect_from_forgery` your request will result in a "Can't verify CSRF token authenticity" error.
215
+
216
+ To remedy this, add `prepend: true` to your `protect_from_forgery` call, like in this example from the [Authy Devise demo app](https://github.com/twilio/authy-devise-demo):
217
+
218
+ ```ruby
219
+ class ApplicationController < ActionController::Base
220
+ protect_from_forgery with: :exception, prepend: true
221
+ end
222
+ ```
148
223
 
149
224
  ## Running Tests
150
225
 
151
226
  To prepare the tests run the following commands:
227
+
152
228
  ```bash
153
229
  $ cd spec/rails-app
154
230
  $ bundle install
@@ -156,17 +232,11 @@ $ RAILS_ENV=test bundle exec rake db:migrate
156
232
  ```
157
233
 
158
234
  Now on the project root run the following commands:
235
+
159
236
  ```bash
160
237
  $ bundle exec rspec spec/
161
238
  ```
162
239
 
163
- ## Backporting to Rails 3
164
-
165
- While we are not currently supporting Rails 3, there's an active fork that maintains the backwards compatibility.
166
-
167
- https://github.com/gcosta/authy-devise
168
-
169
240
  ## Copyright
170
241
 
171
- Copyright (c) 2012-2020 Authy Inc. See LICENSE.txt for
172
- further details.
242
+ Copyright (c) 2012-2020 Authy Inc. See LICENSE.txt for further details.
@@ -5,17 +5,25 @@ class Devise::DeviseAuthyController < DeviseController
5
5
  prepend_before_action :find_resource_and_require_password_checked, :only => [
6
6
  :GET_verify_authy, :POST_verify_authy, :GET_authy_onetouch_status
7
7
  ]
8
+
9
+ prepend_before_action :check_resource_has_authy_id, :only => [
10
+ :GET_verify_authy_installation, :POST_verify_authy_installation
11
+ ]
12
+
13
+ prepend_before_action :check_resource_not_authy_enabled, :only => [
14
+ :GET_verify_authy_installation, :POST_verify_authy_installation
15
+ ]
16
+
8
17
  prepend_before_action :authenticate_scope!, :only => [
9
- :GET_enable_authy, :POST_enable_authy,
10
- :GET_verify_authy_installation, :POST_verify_authy_installation,
11
- :POST_disable_authy
18
+ :GET_enable_authy, :POST_enable_authy, :GET_verify_authy_installation,
19
+ :POST_verify_authy_installation, :POST_disable_authy
12
20
  ]
21
+
13
22
  include Devise::Controllers::Helpers
14
23
 
15
24
  def GET_verify_authy
16
- @authy_id = @resource.authy_id
17
25
  if resource_class.authy_enable_onetouch
18
- approval_request = send_one_touch_request['approval_request']
26
+ approval_request = send_one_touch_request(@resource.authy_id)['approval_request']
19
27
  @onetouch_uuid = approval_request['uuid'] if approval_request.present?
20
28
  end
21
29
  render :verify_authy
@@ -30,10 +38,8 @@ class Devise::DeviseAuthyController < DeviseController
30
38
  })
31
39
 
32
40
  if token.ok?
33
- remember_device if params[:remember_device].to_i == 1
34
- if session.delete("#{resource_name}_remember_me") == true && @resource.respond_to?(:remember_me=)
35
- @resource.remember_me = true
36
- end
41
+ remember_device(@resource.id) if params[:remember_device].to_i == 1
42
+ remember_user
37
43
  record_authy_authentication
38
44
  respond_with resource, :location => after_sign_in_path_for(@resource)
39
45
  else
@@ -61,13 +67,11 @@ class Devise::DeviseAuthyController < DeviseController
61
67
  if @authy_user.ok?
62
68
  resource.authy_id = @authy_user.id
63
69
  if resource.save
64
- set_flash_message(:notice, :enabled)
70
+ redirect_to [resource_name, :verify_authy_installation] and return
65
71
  else
66
72
  set_flash_message(:error, :not_enabled)
67
73
  redirect_to after_authy_enabled_path_for(resource) and return
68
74
  end
69
-
70
- redirect_to [resource_name, :verify_authy_installation]
71
75
  else
72
76
  set_flash_message(:error, :not_enabled)
73
77
  render :enable_authy
@@ -76,22 +80,39 @@ class Devise::DeviseAuthyController < DeviseController
76
80
 
77
81
  # Disable 2FA
78
82
  def POST_disable_authy
79
- response = Authy::API.delete_user(:id => resource.authy_id)
80
-
81
- if response.ok?
82
- resource.update_attribute(:authy_enabled, false)
83
- resource.update_attribute(:authy_id, nil)
83
+ authy_id = resource.authy_id
84
+ resource.assign_attributes(:authy_enabled => false, :authy_id => nil)
85
+ resource.save(:validate => false)
86
+
87
+ other_resource = resource.class.find_by(:authy_id => authy_id)
88
+ if other_resource
89
+ # If another resource has the same authy_id, do not delete the user from
90
+ # the API.
84
91
  forget_device
85
-
86
92
  set_flash_message(:notice, :disabled)
87
93
  else
88
- set_flash_message(:error, :not_disabled)
94
+ response = Authy::API.delete_user(:id => authy_id)
95
+ if response.ok?
96
+ forget_device
97
+ set_flash_message(:notice, :disabled)
98
+ else
99
+ # If deleting the user from the API fails, set everything back to what
100
+ # it was before.
101
+ # I'm not sure this is a good idea, but it was existing behaviour.
102
+ # Could be changed in a major version bump.
103
+ resource.assign_attributes(:authy_enabled => true, :authy_id => authy_id)
104
+ resource.save(:validate => false)
105
+ set_flash_message(:error, :not_disabled)
106
+ end
89
107
  end
90
-
91
108
  redirect_to after_authy_disabled_path_for(resource)
92
109
  end
93
110
 
94
111
  def GET_verify_authy_installation
112
+ if resource_class.authy_enable_qr_code
113
+ response = Authy::API.request_qr_code(id: resource.authy_id)
114
+ @authy_qr_code = response.qr_code
115
+ end
95
116
  render :verify_authy_installation
96
117
  end
97
118
 
@@ -105,6 +126,7 @@ class Devise::DeviseAuthyController < DeviseController
105
126
  self.resource.authy_enabled = token.ok?
106
127
 
107
128
  if token.ok? && self.resource.save
129
+ remember_device(@resource.id) if params[:remember_device].to_i == 1
108
130
  record_authy_authentication
109
131
  set_flash_message(:notice, :enabled)
110
132
  redirect_to after_authy_verified_path_for(resource)
@@ -114,17 +136,20 @@ class Devise::DeviseAuthyController < DeviseController
114
136
  end
115
137
 
116
138
  def GET_authy_onetouch_status
117
- status = Authy::API.get_request("onetouch/json/approval_requests/#{params[:onetouch_uuid]}")['approval_request']['status']
139
+ response = Authy::OneTouch.approval_request_status(:uuid => params[:onetouch_uuid])
140
+ status = response.dig('approval_request', 'status')
118
141
  case status
119
142
  when 'pending'
120
143
  head 202
121
144
  when 'approved'
145
+ remember_device(@resource.id) if params[:remember_device].to_i == 1
146
+ remember_user
122
147
  record_authy_authentication
123
148
  render json: { redirect: after_sign_in_path_for(@resource) }
124
149
  when 'denied'
125
150
  head :unauthorized
126
151
  else
127
- head :error
152
+ head :internal_server_error
128
153
  end
129
154
  end
130
155
 
@@ -172,6 +197,16 @@ class Devise::DeviseAuthyController < DeviseController
172
197
  end
173
198
  end
174
199
 
200
+ def check_resource_has_authy_id
201
+ redirect_to [resource_name, :enable_authy] if !resource.authy_id
202
+ end
203
+
204
+ def check_resource_not_authy_enabled
205
+ if resource.authy_id && resource.authy_enabled
206
+ redirect_to after_authy_verified_path_for(resource)
207
+ end
208
+ end
209
+
175
210
  protected
176
211
 
177
212
  def after_authy_enabled_path_for(resource)
@@ -202,4 +237,10 @@ class Devise::DeviseAuthyController < DeviseController
202
237
  def after_account_is_locked
203
238
  sign_out_and_redirect @resource
204
239
  end
240
+
241
+ def remember_user
242
+ if session.delete("#{resource_name}_remember_me") == true && @resource.respond_to?(:remember_me=)
243
+ @resource.remember_me = true
244
+ end
245
+ end
205
246
  end