google-authenticator-rails 2.0.0 → 3.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 +5 -5
- data/Appraisals +9 -28
- data/Gemfile +1 -1
- data/Gemfile.lock +158 -113
- data/README.md +4 -4
- data/google-authenticator.gemspec +38 -0
- data/lib/google-authenticator-rails/action_controller/rails_adapter.rb +1 -1
- data/lib/google-authenticator-rails/active_record/helpers.rb +17 -9
- data/lib/google-authenticator-rails/version.rb +1 -1
- data/lib/google-authenticator-rails.rb +7 -7
- data/lib/tasks/google_authenticator.rake +5 -5
- data/spec/google_authenticator_spec.rb +80 -71
- data/spec/session/persistance_spec.rb +9 -3
- metadata +28 -23
- data/Dockerfile +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 440ad5551c31c754fd9870dfd810d9ea97969627f5a97e058c336cc8148b5e59
|
|
4
|
+
data.tar.gz: 1324392b3336a8ebe39c5c57c117412472d33b9985be59b6a11e72d62414955c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 98c1cfa7de93eb922afc7c6d58db9fccb732be27e092846902db62993b75f4d55768c57f3352b56ffd28e3c2350faa17c8b458b61e02bf143b54458ceb856124
|
|
7
|
+
data.tar.gz: 724c84f98fbe300eb2488dcb2c24649592df811e65d1af5fc8c17aeec14c069102e5a3564592083cc131f2de193e95d82d8d44f4a904874c0e5faf59203573f0
|
data/Appraisals
CHANGED
|
@@ -4,37 +4,18 @@ major = version_info.first.to_i
|
|
|
4
4
|
minor = version_info[1].to_i
|
|
5
5
|
hotfix = version_info.last.to_i
|
|
6
6
|
|
|
7
|
-
appraise "
|
|
8
|
-
gem "activerecord", "~>
|
|
7
|
+
appraise "rails-5.2" do
|
|
8
|
+
gem "activerecord", "~> 5.2.0"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
appraise "
|
|
12
|
-
gem "activerecord", "~>
|
|
11
|
+
appraise "rails-6.0" do
|
|
12
|
+
gem "activerecord", "~> 6.0.0"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
appraise "
|
|
16
|
-
gem "activerecord", "~>
|
|
15
|
+
appraise "rails-6.1" do
|
|
16
|
+
gem "activerecord", "~> 6.1.0"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
appraise "
|
|
20
|
-
gem "activerecord", "~>
|
|
21
|
-
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
appraise "rails4.1" do
|
|
25
|
-
gem "activerecord", "~> 4.1.0"
|
|
26
|
-
gem "protected_attributes"
|
|
27
|
-
gem "json", "~> 1.8.3"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
appraise "rails4.2" do
|
|
31
|
-
gem "activerecord", "~> 4.2.0"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
appraise "rails5.0" do
|
|
35
|
-
gem "activerecord", "~> 5.0.0"
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
appraise "rails5.1" do
|
|
39
|
-
gem "activerecord", "~> 5.1.0"
|
|
40
|
-
end
|
|
19
|
+
appraise "rails-7.0" do
|
|
20
|
+
gem "activerecord", "~> 7.0.0"
|
|
21
|
+
end
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,156 +1,201 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
google-authenticator-rails (
|
|
4
|
+
google-authenticator-rails (3.0.0)
|
|
5
5
|
actionpack
|
|
6
6
|
activerecord
|
|
7
|
-
google-qr
|
|
8
7
|
rails
|
|
9
|
-
rotp (
|
|
8
|
+
rotp (>= 5.0, < 7.0)
|
|
9
|
+
rqrcode
|
|
10
10
|
|
|
11
11
|
GEM
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
|
-
actioncable (
|
|
15
|
-
actionpack (=
|
|
14
|
+
actioncable (7.0.3)
|
|
15
|
+
actionpack (= 7.0.3)
|
|
16
|
+
activesupport (= 7.0.3)
|
|
16
17
|
nio4r (~> 2.0)
|
|
17
18
|
websocket-driver (>= 0.6.1)
|
|
18
|
-
|
|
19
|
-
actionpack (=
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
actionmailbox (7.0.3)
|
|
20
|
+
actionpack (= 7.0.3)
|
|
21
|
+
activejob (= 7.0.3)
|
|
22
|
+
activerecord (= 7.0.3)
|
|
23
|
+
activestorage (= 7.0.3)
|
|
24
|
+
activesupport (= 7.0.3)
|
|
25
|
+
mail (>= 2.7.1)
|
|
26
|
+
net-imap
|
|
27
|
+
net-pop
|
|
28
|
+
net-smtp
|
|
29
|
+
actionmailer (7.0.3)
|
|
30
|
+
actionpack (= 7.0.3)
|
|
31
|
+
actionview (= 7.0.3)
|
|
32
|
+
activejob (= 7.0.3)
|
|
33
|
+
activesupport (= 7.0.3)
|
|
22
34
|
mail (~> 2.5, >= 2.5.4)
|
|
35
|
+
net-imap
|
|
36
|
+
net-pop
|
|
37
|
+
net-smtp
|
|
23
38
|
rails-dom-testing (~> 2.0)
|
|
24
|
-
actionpack (
|
|
25
|
-
actionview (=
|
|
26
|
-
activesupport (=
|
|
27
|
-
rack (~> 2.0)
|
|
39
|
+
actionpack (7.0.3)
|
|
40
|
+
actionview (= 7.0.3)
|
|
41
|
+
activesupport (= 7.0.3)
|
|
42
|
+
rack (~> 2.0, >= 2.2.0)
|
|
28
43
|
rack-test (>= 0.6.3)
|
|
29
44
|
rails-dom-testing (~> 2.0)
|
|
30
|
-
rails-html-sanitizer (~> 1.0, >= 1.0
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
46
|
+
actiontext (7.0.3)
|
|
47
|
+
actionpack (= 7.0.3)
|
|
48
|
+
activerecord (= 7.0.3)
|
|
49
|
+
activestorage (= 7.0.3)
|
|
50
|
+
activesupport (= 7.0.3)
|
|
51
|
+
globalid (>= 0.6.0)
|
|
52
|
+
nokogiri (>= 1.8.5)
|
|
53
|
+
actionview (7.0.3)
|
|
54
|
+
activesupport (= 7.0.3)
|
|
33
55
|
builder (~> 3.1)
|
|
34
56
|
erubi (~> 1.4)
|
|
35
57
|
rails-dom-testing (~> 2.0)
|
|
36
|
-
rails-html-sanitizer (~> 1.
|
|
37
|
-
activejob (
|
|
38
|
-
activesupport (=
|
|
58
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
59
|
+
activejob (7.0.3)
|
|
60
|
+
activesupport (= 7.0.3)
|
|
39
61
|
globalid (>= 0.3.6)
|
|
40
|
-
activemodel (
|
|
41
|
-
activesupport (=
|
|
42
|
-
activerecord (
|
|
43
|
-
activemodel (=
|
|
44
|
-
activesupport (=
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
activerecord (=
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
activemodel (7.0.3)
|
|
63
|
+
activesupport (= 7.0.3)
|
|
64
|
+
activerecord (7.0.3)
|
|
65
|
+
activemodel (= 7.0.3)
|
|
66
|
+
activesupport (= 7.0.3)
|
|
67
|
+
activestorage (7.0.3)
|
|
68
|
+
actionpack (= 7.0.3)
|
|
69
|
+
activejob (= 7.0.3)
|
|
70
|
+
activerecord (= 7.0.3)
|
|
71
|
+
activesupport (= 7.0.3)
|
|
72
|
+
marcel (~> 1.0)
|
|
73
|
+
mini_mime (>= 1.1.0)
|
|
74
|
+
activesupport (7.0.3)
|
|
51
75
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
52
|
-
i18n (>=
|
|
53
|
-
minitest (
|
|
54
|
-
tzinfo (~>
|
|
55
|
-
appraisal (
|
|
76
|
+
i18n (>= 1.6, < 2)
|
|
77
|
+
minitest (>= 5.1)
|
|
78
|
+
tzinfo (~> 2.0)
|
|
79
|
+
appraisal (2.4.1)
|
|
56
80
|
bundler
|
|
57
81
|
rake
|
|
58
|
-
|
|
59
|
-
builder (3.2.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
thor (>= 0.14.0)
|
|
83
|
+
builder (3.2.4)
|
|
84
|
+
chunky_png (1.4.0)
|
|
85
|
+
concurrent-ruby (1.1.10)
|
|
86
|
+
crass (1.0.6)
|
|
87
|
+
diff-lcs (1.5.0)
|
|
88
|
+
digest (3.1.0)
|
|
89
|
+
docile (1.4.0)
|
|
90
|
+
erubi (1.10.0)
|
|
91
|
+
globalid (1.0.0)
|
|
92
|
+
activesupport (>= 5.0)
|
|
93
|
+
i18n (1.10.0)
|
|
69
94
|
concurrent-ruby (~> 1.0)
|
|
70
|
-
|
|
71
|
-
loofah (2.2.2)
|
|
95
|
+
loofah (2.18.0)
|
|
72
96
|
crass (~> 1.0.2)
|
|
73
97
|
nokogiri (>= 1.5.9)
|
|
74
|
-
mail (2.7.
|
|
98
|
+
mail (2.7.1)
|
|
75
99
|
mini_mime (>= 0.1.1)
|
|
76
|
-
marcel (0.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
marcel (1.0.2)
|
|
101
|
+
method_source (1.0.0)
|
|
102
|
+
mini_mime (1.1.2)
|
|
103
|
+
mini_portile2 (2.8.0)
|
|
104
|
+
minitest (5.15.0)
|
|
105
|
+
net-imap (0.2.3)
|
|
106
|
+
digest
|
|
107
|
+
net-protocol
|
|
108
|
+
strscan
|
|
109
|
+
net-pop (0.1.1)
|
|
110
|
+
digest
|
|
111
|
+
net-protocol
|
|
112
|
+
timeout
|
|
113
|
+
net-protocol (0.1.3)
|
|
114
|
+
timeout
|
|
115
|
+
net-smtp (0.3.1)
|
|
116
|
+
digest
|
|
117
|
+
net-protocol
|
|
118
|
+
timeout
|
|
119
|
+
nio4r (2.5.8)
|
|
120
|
+
nokogiri (1.13.6)
|
|
121
|
+
mini_portile2 (~> 2.8.0)
|
|
122
|
+
racc (~> 1.4)
|
|
123
|
+
racc (1.6.0)
|
|
124
|
+
rack (2.2.3.1)
|
|
125
|
+
rack-test (1.1.0)
|
|
88
126
|
rack (>= 1.0, < 3)
|
|
89
|
-
rails (
|
|
90
|
-
actioncable (=
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
127
|
+
rails (7.0.3)
|
|
128
|
+
actioncable (= 7.0.3)
|
|
129
|
+
actionmailbox (= 7.0.3)
|
|
130
|
+
actionmailer (= 7.0.3)
|
|
131
|
+
actionpack (= 7.0.3)
|
|
132
|
+
actiontext (= 7.0.3)
|
|
133
|
+
actionview (= 7.0.3)
|
|
134
|
+
activejob (= 7.0.3)
|
|
135
|
+
activemodel (= 7.0.3)
|
|
136
|
+
activerecord (= 7.0.3)
|
|
137
|
+
activestorage (= 7.0.3)
|
|
138
|
+
activesupport (= 7.0.3)
|
|
139
|
+
bundler (>= 1.15.0)
|
|
140
|
+
railties (= 7.0.3)
|
|
102
141
|
rails-dom-testing (2.0.3)
|
|
103
142
|
activesupport (>= 4.2.0)
|
|
104
143
|
nokogiri (>= 1.6)
|
|
105
|
-
rails-html-sanitizer (1.
|
|
106
|
-
loofah (~> 2.
|
|
107
|
-
railties (
|
|
108
|
-
actionpack (=
|
|
109
|
-
activesupport (=
|
|
144
|
+
rails-html-sanitizer (1.4.3)
|
|
145
|
+
loofah (~> 2.3)
|
|
146
|
+
railties (7.0.3)
|
|
147
|
+
actionpack (= 7.0.3)
|
|
148
|
+
activesupport (= 7.0.3)
|
|
110
149
|
method_source
|
|
111
|
-
rake (>=
|
|
112
|
-
thor (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
rspec
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
150
|
+
rake (>= 12.2)
|
|
151
|
+
thor (~> 1.0)
|
|
152
|
+
zeitwerk (~> 2.5)
|
|
153
|
+
rake (13.0.6)
|
|
154
|
+
rotp (6.2.0)
|
|
155
|
+
rqrcode (2.1.1)
|
|
156
|
+
chunky_png (~> 1.0)
|
|
157
|
+
rqrcode_core (~> 1.0)
|
|
158
|
+
rqrcode_core (1.2.0)
|
|
159
|
+
rspec (3.4.0)
|
|
160
|
+
rspec-core (~> 3.4.0)
|
|
161
|
+
rspec-expectations (~> 3.4.0)
|
|
162
|
+
rspec-mocks (~> 3.4.0)
|
|
163
|
+
rspec-core (3.4.4)
|
|
164
|
+
rspec-support (~> 3.4.0)
|
|
165
|
+
rspec-expectations (3.4.0)
|
|
166
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
167
|
+
rspec-support (~> 3.4.0)
|
|
168
|
+
rspec-mocks (3.4.1)
|
|
169
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
170
|
+
rspec-support (~> 3.4.0)
|
|
171
|
+
rspec-support (3.4.1)
|
|
172
|
+
simplecov (0.21.2)
|
|
173
|
+
docile (~> 1.1)
|
|
174
|
+
simplecov-html (~> 0.11)
|
|
175
|
+
simplecov_json_formatter (~> 0.1)
|
|
176
|
+
simplecov-html (0.12.3)
|
|
177
|
+
simplecov_json_formatter (0.1.4)
|
|
178
|
+
sqlite3 (1.4.2)
|
|
179
|
+
strscan (3.0.3)
|
|
180
|
+
thor (1.2.1)
|
|
181
|
+
timeout (0.3.0)
|
|
182
|
+
tzinfo (2.0.4)
|
|
129
183
|
concurrent-ruby (~> 1.0)
|
|
130
|
-
|
|
131
|
-
sprockets-rails (3.2.1)
|
|
132
|
-
actionpack (>= 4.0)
|
|
133
|
-
activesupport (>= 4.0)
|
|
134
|
-
sprockets (>= 3.0.0)
|
|
135
|
-
sqlite3 (1.3.13)
|
|
136
|
-
thor (0.20.0)
|
|
137
|
-
thread_safe (0.3.6)
|
|
138
|
-
tzinfo (1.2.5)
|
|
139
|
-
thread_safe (~> 0.1)
|
|
140
|
-
websocket-driver (0.7.0)
|
|
184
|
+
websocket-driver (0.7.5)
|
|
141
185
|
websocket-extensions (>= 0.1.0)
|
|
142
|
-
websocket-extensions (0.1.
|
|
186
|
+
websocket-extensions (0.1.5)
|
|
187
|
+
zeitwerk (2.5.4)
|
|
143
188
|
|
|
144
189
|
PLATFORMS
|
|
145
190
|
ruby
|
|
146
191
|
|
|
147
192
|
DEPENDENCIES
|
|
148
|
-
appraisal (~>
|
|
193
|
+
appraisal (~> 2.4.1)
|
|
149
194
|
google-authenticator-rails!
|
|
150
|
-
rake (~>
|
|
151
|
-
rspec (~>
|
|
195
|
+
rake (~> 13.0)
|
|
196
|
+
rspec (~> 3.4.0)
|
|
152
197
|
simplecov
|
|
153
|
-
sqlite3
|
|
198
|
+
sqlite3 (~> 1.4.0)
|
|
154
199
|
|
|
155
200
|
BUNDLED WITH
|
|
156
|
-
|
|
201
|
+
2.3.15
|
data/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# GoogleAuthenticatorRails
|
|
2
2
|
|
|
3
3
|
[](http://badge.fury.io/rb/google-authenticator-rails)
|
|
4
|
-
[](http://travis-ci.org/jaredonline/google-authenticator)
|
|
5
4
|
[](https://codeclimate.com/github/jaredonline/google-authenticator)
|
|
6
5
|
[](https://codeclimate.com/github/jaredonline/google-authenticator/test_coverage)
|
|
6
|
+
[](https://circleci.com/gh/jaredonline/google-authenticator/tree/master)
|
|
7
7
|
|
|
8
8
|
Rails (ActiveRecord) integration with the Google Authenticator apps for [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2) and the [iPhone](https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8). Uses the Authlogic style for cookie management.
|
|
9
9
|
|
|
@@ -52,7 +52,7 @@ Example:
|
|
|
52
52
|
|
|
53
53
|
```ruby
|
|
54
54
|
class User
|
|
55
|
-
acts_as_google_authenticated :
|
|
55
|
+
acts_as_google_authenticated :column_name => :user_name
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
@user = User.new(:user_name => "ted")
|
|
@@ -200,7 +200,7 @@ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
|
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
# app/controllers/mfa_session_controller.rb
|
|
203
|
-
|
|
203
|
+
class MfaSessionController < ApplicationController
|
|
204
204
|
def create
|
|
205
205
|
UserMfaSession.create(user)
|
|
206
206
|
end
|
|
@@ -367,7 +367,7 @@ to change all encrypted google secret fields to use the new key.
|
|
|
367
367
|
If the app is not running under Rails version 4.1 or above, encryption will be disabled, and a warning issued if ```:encrypt_secrets```
|
|
368
368
|
is enabled on a model.
|
|
369
369
|
|
|
370
|
-
If encryption is enabled for a model, the Google secret column of its table must be able to hold at least
|
|
370
|
+
If encryption is enabled for a model, the Google secret column of its table must be able to hold at least 162 characters, rather than just 32.
|
|
371
371
|
|
|
372
372
|
## Contributing
|
|
373
373
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/google-authenticator-rails/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
version_info = RUBY_VERSION.split(".")
|
|
5
|
+
|
|
6
|
+
major = version_info.first.to_i
|
|
7
|
+
minor = version_info[1].to_i
|
|
8
|
+
hotfix = version_info.last.to_i
|
|
9
|
+
|
|
10
|
+
Gem::Specification.new do |gem|
|
|
11
|
+
gem.authors = ["Jared McFarland"]
|
|
12
|
+
gem.email = ["jared.online@gmail.com"]
|
|
13
|
+
gem.description = %q{Add the ability to use the Google Authenticator with ActiveRecord.}
|
|
14
|
+
gem.summary = %q{Add the ability to use the Google Authenticator with ActiveRecord.}
|
|
15
|
+
gem.homepage = "http://github.com/jaredonline/google-authenticator"
|
|
16
|
+
|
|
17
|
+
gem.files = Dir['lib/**/*.{rb,rake}'] + Dir['bin/*']
|
|
18
|
+
gem.files += Dir['[A-Z]*'] + Dir['spec/**/*.rb']
|
|
19
|
+
gem.files.reject! { |fn| fn.include? "CVS" }
|
|
20
|
+
|
|
21
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
22
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
23
|
+
gem.name = "google-authenticator-rails"
|
|
24
|
+
gem.require_paths = ["lib"]
|
|
25
|
+
gem.version = GoogleAuthenticatorRails::VERSION
|
|
26
|
+
|
|
27
|
+
gem.add_dependency "rotp", ">= 5.0", "< 7.0"
|
|
28
|
+
gem.add_dependency "rails"
|
|
29
|
+
gem.add_dependency "activerecord"
|
|
30
|
+
gem.add_dependency "rqrcode"
|
|
31
|
+
gem.add_dependency "actionpack"
|
|
32
|
+
|
|
33
|
+
gem.add_development_dependency "rake", "~> 13.0"
|
|
34
|
+
gem.add_development_dependency "rspec", "~> 3.4.0"
|
|
35
|
+
gem.add_development_dependency "appraisal", "~> 2.4.1"
|
|
36
|
+
gem.add_development_dependency "simplecov"
|
|
37
|
+
gem.add_development_dependency "sqlite3", "~> 1.4.0"
|
|
38
|
+
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module GoogleAuthenticatorRails # :nodoc:
|
|
2
2
|
mattr_accessor :secret_encryptor
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
module ActiveRecord # :nodoc:
|
|
5
5
|
module Helpers
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# Returns and memoizes the plain text google secret for this instance, irrespective of the
|
|
8
8
|
# name of the google secret storage column and whether secret encryption is enabled for this model.
|
|
9
9
|
#
|
|
@@ -16,7 +16,7 @@ module GoogleAuthenticatorRails # :nodoc:
|
|
|
16
16
|
@google_secret_value = secret_in_db.present? && self.class.google_secrets_encrypted ? google_secret_encryptor.decrypt_and_verify(secret_in_db) : secret_in_db
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def set_google_secret
|
|
21
21
|
change_google_secret_to!(GoogleAuthenticatorRails::generate_secret)
|
|
22
22
|
end
|
|
@@ -32,7 +32,12 @@ module GoogleAuthenticatorRails # :nodoc:
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def google_qr_uri(size = nil)
|
|
35
|
-
|
|
35
|
+
data = ROTP::TOTP.new(google_secret_value, :issuer => google_issuer).provisioning_uri(google_label)
|
|
36
|
+
"https://chart.googleapis.com/chart?cht=qr&chl=#{CGI.escape(data)}&chs=#{size || self.class.google_qr_size}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def google_qr_to_base64(size = 200)
|
|
40
|
+
"data:image/png;base64,#{Base64.strict_encode64(RQRCode::QRCode.new(ROTP::TOTP.new(google_secret_value, :issuer => google_issuer).provisioning_uri(google_label).to_s).as_png(size: size).to_s)}"
|
|
36
41
|
end
|
|
37
42
|
|
|
38
43
|
def google_label
|
|
@@ -50,7 +55,7 @@ module GoogleAuthenticatorRails # :nodoc:
|
|
|
50
55
|
def google_token_value
|
|
51
56
|
self.__send__(self.class.google_lookup_token)
|
|
52
57
|
end
|
|
53
|
-
|
|
58
|
+
|
|
54
59
|
def encrypt_google_secret!
|
|
55
60
|
change_google_secret_to!(google_secret_column_value)
|
|
56
61
|
end
|
|
@@ -59,7 +64,7 @@ module GoogleAuthenticatorRails # :nodoc:
|
|
|
59
64
|
def default_google_label_method
|
|
60
65
|
self.__send__(self.class.google_label_column)
|
|
61
66
|
end
|
|
62
|
-
|
|
67
|
+
|
|
63
68
|
def google_secret_column_value
|
|
64
69
|
self.__send__(self.class.google_secret_column)
|
|
65
70
|
end
|
|
@@ -75,13 +80,16 @@ module GoogleAuthenticatorRails # :nodoc:
|
|
|
75
80
|
issuer = self.class.google_issuer
|
|
76
81
|
issuer.is_a?(Proc) ? issuer.call(self) : issuer
|
|
77
82
|
end
|
|
78
|
-
|
|
83
|
+
|
|
79
84
|
def google_secret_encryptor
|
|
80
85
|
GoogleAuthenticatorRails.secret_encryptor ||= GoogleAuthenticatorRails::ActiveRecord::Helpers.get_google_secret_encryptor
|
|
81
86
|
end
|
|
82
|
-
|
|
87
|
+
|
|
83
88
|
def self.get_google_secret_encryptor
|
|
84
|
-
|
|
89
|
+
encryption_key = Rails.application.key_generator.generate_key('Google-secret encryption key', 32)
|
|
90
|
+
encryptor = ActiveSupport::MessageEncryptor.new(encryption_key)
|
|
91
|
+
encryptor.rotate(encryption_key, cipher: 'aes-256-cbc') # Legacy support for Rails 5.2
|
|
92
|
+
encryptor
|
|
85
93
|
end
|
|
86
94
|
end
|
|
87
95
|
end
|
|
@@ -4,7 +4,7 @@ require 'active_support'
|
|
|
4
4
|
require 'active_record'
|
|
5
5
|
require 'openssl'
|
|
6
6
|
require 'rotp'
|
|
7
|
-
require '
|
|
7
|
+
require 'rqrcode'
|
|
8
8
|
|
|
9
9
|
# Stuff the gem is
|
|
10
10
|
#
|
|
@@ -26,13 +26,13 @@ module GoogleAuthenticatorRails
|
|
|
26
26
|
def self.encryption_supported?
|
|
27
27
|
defined?(Rails) && (Rails::VERSION::MAJOR > 4 || Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR > 0)
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
class Railtie < Rails::Railtie
|
|
31
31
|
rake_tasks do
|
|
32
32
|
load 'tasks/google_authenticator.rake'
|
|
33
33
|
end
|
|
34
|
-
end if encryption_supported? && !Rails.env.test? # Without this last condition tasks under test are run twice
|
|
35
|
-
|
|
34
|
+
end if encryption_supported? && !Rails.env.test? # Without this last condition tasks under test are run twice
|
|
35
|
+
|
|
36
36
|
# Drift is set to 6 because ROTP drift is not inclusive. This allows a drift of 5 seconds.
|
|
37
37
|
DRIFT = 6
|
|
38
38
|
|
|
@@ -44,7 +44,7 @@ module GoogleAuthenticatorRails
|
|
|
44
44
|
|
|
45
45
|
# Additional configuration passed to a Session::Persistence cookie.
|
|
46
46
|
@@cookie_options = { :httponly => true }
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
def self.generate_password(secret, iteration)
|
|
49
49
|
ROTP::HOTP.new(secret).at(iteration)
|
|
50
50
|
end
|
|
@@ -54,11 +54,11 @@ module GoogleAuthenticatorRails
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def self.valid?(code, secret, drift = DRIFT)
|
|
57
|
-
ROTP::TOTP.new(secret).
|
|
57
|
+
!!ROTP::TOTP.new(secret).verify(code, drift_ahead: drift, drift_behind: drift)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def self.generate_secret
|
|
61
|
-
ROTP::Base32.
|
|
61
|
+
ROTP::Base32.random
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def self.time_until_expiration
|
|
@@ -7,9 +7,9 @@ namespace :google_authenticator do
|
|
|
7
7
|
# Adapted from https://stackoverflow.com/a/8248849/7478194
|
|
8
8
|
Dir[Rails.root.join('app/models/*.rb').to_s].map { |filename| File.basename(filename, '.rb').camelize }
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
ActiveRecord::Base.transaction do
|
|
12
|
-
match_op =
|
|
12
|
+
match_op = already_encrypted ? " in (138,162)" : "in (16,32)"
|
|
13
13
|
model_names.each do |model_name|
|
|
14
14
|
klass = model_name.constantize
|
|
15
15
|
next unless klass.ancestors.include?(ActiveRecord::Base) && klass.try(:google_secrets_encrypted)
|
|
@@ -23,7 +23,7 @@ namespace :google_authenticator do
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
desc 'Encrypt all secret columns (add the :encrypt_secrets options *before* running)'
|
|
28
28
|
task :encrypt_secrets, [:optional_model_list] => :environment do |_t, args|
|
|
29
29
|
do_encrypt(args, false, 'Encrypt') { |record| record.encrypt_google_secret! }
|
|
@@ -46,10 +46,10 @@ namespace :google_authenticator do
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
desc 'Decrypt all secret columns (remove the :encrypt_secrets options *after* running)'
|
|
51
51
|
task :decrypt_secrets, [:optional_model_list] => :environment do |_t, args|
|
|
52
52
|
do_encrypt(args, true, 'Decrypt') { |record| record.send(:change_google_secret_to!, record.google_secret_value, false) }
|
|
53
|
-
end
|
|
53
|
+
end
|
|
54
54
|
|
|
55
55
|
end
|
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe GoogleAuthenticatorRails do
|
|
4
|
+
def get_secret
|
|
5
|
+
'LMFMFDV3UGN7LBO4FEMVQVJOK7F7FLLE'
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
describe '#generate_password' do
|
|
5
|
-
subject { GoogleAuthenticatorRails::generate_password(
|
|
9
|
+
subject { GoogleAuthenticatorRails::generate_password(get_secret, counter) }
|
|
6
10
|
|
|
7
11
|
context 'counter = 1' do
|
|
8
12
|
let(:counter) { 1 }
|
|
9
|
-
it { should == "
|
|
13
|
+
it { should == "664045" }
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
context 'counter = 2' do
|
|
13
17
|
let(:counter) { 2 }
|
|
14
|
-
it { should == "
|
|
18
|
+
it { should == "548382" }
|
|
15
19
|
end
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
context 'time-based passwords' do
|
|
19
|
-
let(:secret) {
|
|
23
|
+
let(:secret) { get_secret }
|
|
20
24
|
let(:original_time) { Time.parse("2012-08-07 11:11:00 AM +0700") }
|
|
21
25
|
let!(:time) { original_time }
|
|
22
|
-
let(:code) { "
|
|
26
|
+
let(:code) { "954578" }
|
|
23
27
|
|
|
24
28
|
before do
|
|
25
|
-
Time.
|
|
26
|
-
ROTP::Base32.
|
|
29
|
+
allow(Time).to receive(:now).and_return(time)
|
|
30
|
+
allow(ROTP::Base32).to receive(:random).and_return(secret)
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
specify { GoogleAuthenticatorRails::time_based_password(secret).should == code }
|
|
@@ -43,44 +47,44 @@ describe GoogleAuthenticatorRails do
|
|
|
43
47
|
@user = user
|
|
44
48
|
user.google_secret = secret
|
|
45
49
|
end
|
|
46
|
-
|
|
50
|
+
|
|
47
51
|
context "custom drift" do
|
|
48
52
|
# 30 seconds drift
|
|
49
53
|
let(:user) { UserFactory.create DriftUser }
|
|
50
54
|
subject { user.google_authentic?(code) }
|
|
51
|
-
|
|
55
|
+
|
|
52
56
|
context '6 seconds of drift' do
|
|
53
57
|
let(:time) { original_time + 36.seconds }
|
|
54
58
|
it { should be true }
|
|
55
59
|
end
|
|
56
|
-
|
|
60
|
+
|
|
57
61
|
context '30 seconds of drift' do
|
|
58
62
|
let(:time) { original_time + 61.seconds }
|
|
59
63
|
it { should be false }
|
|
60
64
|
end
|
|
61
65
|
end
|
|
62
|
-
|
|
66
|
+
|
|
63
67
|
context 'code validation' do
|
|
64
68
|
subject { user.google_authentic?(code) }
|
|
65
|
-
|
|
69
|
+
|
|
66
70
|
it { should be true }
|
|
67
|
-
|
|
71
|
+
|
|
68
72
|
context 'within 5 seconds of drift' do
|
|
69
73
|
let(:time) { original_time + 34.seconds }
|
|
70
74
|
it { should be true }
|
|
71
75
|
end
|
|
72
|
-
|
|
76
|
+
|
|
73
77
|
context '6 seconds of drift' do
|
|
74
78
|
let(:time) { original_time + 36.seconds }
|
|
75
79
|
it { should be false }
|
|
76
80
|
end
|
|
77
81
|
end
|
|
78
|
-
|
|
82
|
+
|
|
79
83
|
it 'creates a secret' do
|
|
80
84
|
user.set_google_secret
|
|
81
85
|
user.google_secret.should == secret
|
|
82
86
|
end
|
|
83
|
-
|
|
87
|
+
|
|
84
88
|
shared_examples 'handles nil secrets' do
|
|
85
89
|
it 'clears a secret' do
|
|
86
90
|
@user.clear_google_secret!
|
|
@@ -95,102 +99,102 @@ describe GoogleAuthenticatorRails do
|
|
|
95
99
|
@user = UserFactory.create EncryptedUser
|
|
96
100
|
@user.set_google_secret
|
|
97
101
|
end
|
|
98
|
-
|
|
102
|
+
|
|
99
103
|
it 'encrypts_the_secret' do
|
|
100
|
-
@user.google_secret.length.should == (GoogleAuthenticatorRails.encryption_supported? ?
|
|
104
|
+
@user.google_secret.length.should == (GoogleAuthenticatorRails.encryption_supported? ? 162 : 32)
|
|
101
105
|
end
|
|
102
|
-
|
|
106
|
+
|
|
103
107
|
it 'decrypts_the_secret' do
|
|
104
108
|
@user.google_secret_value.should == secret
|
|
105
|
-
end
|
|
106
|
-
|
|
109
|
+
end
|
|
110
|
+
|
|
107
111
|
it 'validates code' do
|
|
108
|
-
@user.google_authentic?(code).should
|
|
112
|
+
@user.google_authentic?(code).should be_truthy
|
|
109
113
|
end
|
|
110
114
|
|
|
111
115
|
it_behaves_like 'handles nil secrets'
|
|
112
116
|
end
|
|
113
|
-
|
|
117
|
+
|
|
114
118
|
context 'custom secret column' do
|
|
115
119
|
before do
|
|
116
120
|
@user = UserFactory.create CustomUser
|
|
117
121
|
@user.set_google_secret
|
|
118
122
|
end
|
|
119
|
-
|
|
123
|
+
|
|
120
124
|
it 'validates code' do
|
|
121
|
-
@user.google_authentic?(code).should
|
|
125
|
+
@user.google_authentic?(code).should be_truthy
|
|
122
126
|
end
|
|
123
|
-
|
|
127
|
+
|
|
124
128
|
it 'generates a url for a qr code' do
|
|
125
|
-
@user.google_qr_uri.should == "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
129
|
+
@user.google_qr_uri.should == "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=200x200"
|
|
126
130
|
end
|
|
127
131
|
end
|
|
128
|
-
|
|
132
|
+
|
|
129
133
|
context 'encrypted column with custom secret column' do
|
|
130
134
|
before do
|
|
131
135
|
@user = UserFactory.create EncryptedCustomUser
|
|
132
136
|
@user.set_google_secret
|
|
133
137
|
end
|
|
134
|
-
|
|
138
|
+
|
|
135
139
|
it 'encrypts the secret' do
|
|
136
|
-
@user.mfa_secret.length.should == (GoogleAuthenticatorRails.encryption_supported? ?
|
|
140
|
+
@user.mfa_secret.length.should == (GoogleAuthenticatorRails.encryption_supported? ? 162 : 32)
|
|
137
141
|
end
|
|
138
|
-
|
|
142
|
+
|
|
139
143
|
it 'decrypts the secret' do
|
|
140
144
|
@user.google_secret_value.should == secret
|
|
141
|
-
end
|
|
142
|
-
|
|
145
|
+
end
|
|
146
|
+
|
|
143
147
|
it 'validates code' do
|
|
144
|
-
@user.google_authentic?(code).should
|
|
148
|
+
@user.google_authentic?(code).should be_truthy
|
|
145
149
|
end
|
|
146
150
|
end
|
|
147
|
-
|
|
151
|
+
|
|
148
152
|
if GoogleAuthenticatorRails.encryption_supported?
|
|
149
153
|
context 'encryption Rake tasks' do
|
|
150
154
|
before(:all) { Rails.application.load_tasks }
|
|
151
|
-
|
|
155
|
+
|
|
152
156
|
def set_and_run_task(type)
|
|
153
157
|
User.delete_all
|
|
154
|
-
EncryptedCustomUser.delete_all
|
|
158
|
+
EncryptedCustomUser.delete_all
|
|
155
159
|
@user = UserFactory.create User
|
|
156
160
|
@user.set_google_secret
|
|
157
161
|
@encrypted_user = UserFactory.create EncryptedCustomUser
|
|
158
162
|
@encrypted_user.set_google_secret
|
|
159
163
|
@non_encrypted_user = UserFactory.create EncryptedCustomUser
|
|
160
|
-
@non_encrypted_user.update_attribute(:mfa_secret,
|
|
164
|
+
@non_encrypted_user.update_attribute(:mfa_secret, get_secret)
|
|
161
165
|
Rake.application.invoke_task("google_authenticator:#{type}_secrets[User,EncryptedCustomUser]")
|
|
162
|
-
end
|
|
163
|
-
|
|
166
|
+
end
|
|
167
|
+
|
|
164
168
|
def encryption_ok?(user, secret_should_be_encrypted)
|
|
165
169
|
secret_value = user.reload.send(:google_secret_column_value)
|
|
166
|
-
(secret_value.blank? || secret_value.length.should == (secret_should_be_encrypted ?
|
|
170
|
+
(secret_value.blank? || secret_value.length.should == (secret_should_be_encrypted ? 162 : 32)) &&
|
|
167
171
|
(user.class.google_secrets_encrypted ^ secret_should_be_encrypted || user.google_secret_value == secret)
|
|
168
172
|
end
|
|
169
|
-
|
|
173
|
+
|
|
170
174
|
shared_examples 'task tests' do |type|
|
|
171
175
|
it 'handles non-encrypted secrets' do
|
|
172
176
|
encryption_ok?(@non_encrypted_user, type == 'encrypt')
|
|
173
177
|
end
|
|
174
|
-
|
|
178
|
+
|
|
175
179
|
it 'handles encrypted secrets' do
|
|
176
180
|
encryption_ok?(@encrypted_user, type != 'decrypt')
|
|
177
181
|
end
|
|
178
|
-
|
|
182
|
+
|
|
179
183
|
it "doesn't #{type} non-encrypted models" do
|
|
180
184
|
encryption_ok?(@user, false)
|
|
181
185
|
end
|
|
182
186
|
end
|
|
183
|
-
|
|
187
|
+
|
|
184
188
|
context 'encrypt_secrets task' do
|
|
185
189
|
before(:all) { set_and_run_task('encrypt') }
|
|
186
190
|
it_behaves_like 'task tests', 'encrypt'
|
|
187
191
|
end
|
|
188
|
-
|
|
192
|
+
|
|
189
193
|
context 'decrypt_secrets task' do
|
|
190
194
|
before(:all) { set_and_run_task('decrypt') }
|
|
191
195
|
it_behaves_like 'task tests', 'decrypt'
|
|
192
196
|
end
|
|
193
|
-
|
|
197
|
+
|
|
194
198
|
context 'reencrypt_secrets task' do
|
|
195
199
|
before(:all) do
|
|
196
200
|
def reset_encryption(secret_key_base)
|
|
@@ -198,79 +202,84 @@ describe GoogleAuthenticatorRails do
|
|
|
198
202
|
Rails.application.instance_eval { @caching_key_generator = nil }
|
|
199
203
|
GoogleAuthenticatorRails.secret_encryptor = nil
|
|
200
204
|
end
|
|
201
|
-
|
|
205
|
+
|
|
202
206
|
current_secret_key_base = Rails.application.secrets[:secret_key_base]
|
|
203
207
|
reset_encryption(Rails.application.secrets.old_secret_key_base)
|
|
204
208
|
set_and_run_task('reencrypt')
|
|
205
209
|
reset_encryption(current_secret_key_base)
|
|
206
210
|
end
|
|
207
|
-
|
|
211
|
+
|
|
208
212
|
it_behaves_like 'task tests', 'reencrypt'
|
|
209
213
|
end
|
|
210
214
|
end
|
|
211
215
|
end
|
|
212
|
-
|
|
216
|
+
|
|
213
217
|
context 'google label' do
|
|
214
218
|
let(:user) { UserFactory.create NilMethodUser }
|
|
215
219
|
subject { lambda { user.google_label } }
|
|
216
220
|
it { should raise_error(NoMethodError) }
|
|
217
221
|
end
|
|
218
|
-
|
|
222
|
+
|
|
219
223
|
context "drift value" do
|
|
220
224
|
it { DriftUser.google_drift.should == 31 }
|
|
221
|
-
|
|
225
|
+
|
|
222
226
|
context "default value" do
|
|
223
227
|
it { User.google_drift.should == 6 }
|
|
224
228
|
end
|
|
225
229
|
end
|
|
226
|
-
|
|
230
|
+
|
|
227
231
|
context 'qr codes' do
|
|
228
232
|
let(:user) { UserFactory.create User }
|
|
229
233
|
before { user.set_google_secret }
|
|
230
234
|
subject { user.google_qr_uri }
|
|
231
|
-
|
|
232
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
233
|
-
|
|
235
|
+
|
|
236
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=200x200" }
|
|
237
|
+
|
|
234
238
|
context 'custom column name' do
|
|
235
239
|
let(:user) { UserFactory.create ColumnNameUser }
|
|
236
240
|
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest_user%3Fsecret%3D#{secret}&chs=200x200" }
|
|
237
241
|
end
|
|
238
|
-
|
|
242
|
+
|
|
239
243
|
context 'custom proc' do
|
|
240
244
|
let(:user) { UserFactory.create ProcLabelUser }
|
|
241
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest_user%
|
|
245
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest_user%2540futureadvisor-admin%3Fsecret%3D#{secret}&chs=200x200" }
|
|
242
246
|
end
|
|
243
|
-
|
|
247
|
+
|
|
244
248
|
context 'custom issuer' do
|
|
245
249
|
let(:user) { UserFactory.create ProcIssuerUser }
|
|
246
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2FFA%2520Admin%3Atest%
|
|
250
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2FFA%2520Admin%3Atest%2540example.com%3Fsecret%3D#{secret}%26issuer%3DFA%2520Admin&chs=200x200" }
|
|
247
251
|
end
|
|
248
|
-
|
|
252
|
+
|
|
249
253
|
context 'method defined by symbol' do
|
|
250
254
|
let(:user) { UserFactory.create SymbolUser }
|
|
251
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
255
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=200x200" }
|
|
252
256
|
end
|
|
253
|
-
|
|
257
|
+
|
|
254
258
|
context 'method defined by string' do
|
|
255
259
|
let(:user) { UserFactory.create StringUser }
|
|
256
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
260
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=200x200" }
|
|
257
261
|
end
|
|
258
|
-
|
|
262
|
+
|
|
259
263
|
context 'custom qr size' do
|
|
260
264
|
let(:user) { UserFactory.create QrCodeUser }
|
|
261
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
265
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=300x300" }
|
|
262
266
|
end
|
|
263
|
-
|
|
267
|
+
|
|
264
268
|
context 'qr size passed to method' do
|
|
265
269
|
subject { user.google_qr_uri('400x400') }
|
|
266
|
-
let(:user) { UserFactory.create StringUser }
|
|
267
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
270
|
+
let(:user) { UserFactory.create StringUser }
|
|
271
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=400x400" }
|
|
268
272
|
end
|
|
269
|
-
|
|
273
|
+
|
|
270
274
|
context 'qr size passed to method and size set on model' do
|
|
271
275
|
let(:user) { UserFactory.create QrCodeUser }
|
|
272
276
|
subject { user.google_qr_uri('400x400') }
|
|
273
|
-
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%
|
|
277
|
+
it { should eq "https://chart.googleapis.com/chart?cht=qr&chl=otpauth%3A%2F%2Ftotp%2Ftest%2540example.com%3Fsecret%3D#{secret}&chs=400x400" }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
context 'generates base64 image' do
|
|
281
|
+
let(:user) { UserFactory.create QrCodeUser }
|
|
282
|
+
it { user.google_qr_to_base64.include?('data:image/png;base64').should be_truthy }
|
|
274
283
|
end
|
|
275
284
|
end
|
|
276
285
|
end
|
|
@@ -20,7 +20,9 @@ describe GoogleAuthenticatorRails::Session::Base do
|
|
|
20
20
|
after { clear_cookie unless user.nil? }
|
|
21
21
|
|
|
22
22
|
it { should be_a UserMfaSession }
|
|
23
|
-
|
|
23
|
+
it "can fetch the record" do
|
|
24
|
+
expect(subject.record).to eq(user)
|
|
25
|
+
end
|
|
24
26
|
|
|
25
27
|
context 'custom lookup token' do
|
|
26
28
|
let(:user) { SaltUser.create(:password => "password", :email => "email@example.com") }
|
|
@@ -28,7 +30,9 @@ describe GoogleAuthenticatorRails::Session::Base do
|
|
|
28
30
|
subject { SaltUserMfaSession.find }
|
|
29
31
|
|
|
30
32
|
it { should be_a SaltUserMfaSession }
|
|
31
|
-
|
|
33
|
+
it "can fetch the record" do
|
|
34
|
+
expect(subject.record).to eq(user)
|
|
35
|
+
end
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
context 'after destroy' do
|
|
@@ -46,7 +50,9 @@ describe GoogleAuthenticatorRails::Session::Base do
|
|
|
46
50
|
subject { UserMfaSession.create(user) }
|
|
47
51
|
|
|
48
52
|
it { should be_a UserMfaSession }
|
|
49
|
-
|
|
53
|
+
it "can fetch the record" do
|
|
54
|
+
expect(subject.record).to eq(user)
|
|
55
|
+
end
|
|
50
56
|
|
|
51
57
|
context 'nil user' do
|
|
52
58
|
let(:user) { nil }
|
metadata
CHANGED
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: google-authenticator-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jared McFarland
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-06-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rotp
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
- - "<"
|
|
18
21
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
22
|
+
version: '7.0'
|
|
20
23
|
type: :runtime
|
|
21
24
|
prerelease: false
|
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
26
|
requirements:
|
|
24
|
-
- -
|
|
27
|
+
- - ">="
|
|
25
28
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
29
|
+
version: '5.0'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.0'
|
|
27
33
|
- !ruby/object:Gem::Dependency
|
|
28
34
|
name: rails
|
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -53,7 +59,7 @@ dependencies:
|
|
|
53
59
|
- !ruby/object:Gem::Version
|
|
54
60
|
version: '0'
|
|
55
61
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
62
|
+
name: rqrcode
|
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
|
58
64
|
requirements:
|
|
59
65
|
- - ">="
|
|
@@ -86,42 +92,42 @@ dependencies:
|
|
|
86
92
|
requirements:
|
|
87
93
|
- - "~>"
|
|
88
94
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
95
|
+
version: '13.0'
|
|
90
96
|
type: :development
|
|
91
97
|
prerelease: false
|
|
92
98
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
99
|
requirements:
|
|
94
100
|
- - "~>"
|
|
95
101
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
102
|
+
version: '13.0'
|
|
97
103
|
- !ruby/object:Gem::Dependency
|
|
98
104
|
name: rspec
|
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
|
100
106
|
requirements:
|
|
101
107
|
- - "~>"
|
|
102
108
|
- !ruby/object:Gem::Version
|
|
103
|
-
version:
|
|
109
|
+
version: 3.4.0
|
|
104
110
|
type: :development
|
|
105
111
|
prerelease: false
|
|
106
112
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
113
|
requirements:
|
|
108
114
|
- - "~>"
|
|
109
115
|
- !ruby/object:Gem::Version
|
|
110
|
-
version:
|
|
116
|
+
version: 3.4.0
|
|
111
117
|
- !ruby/object:Gem::Dependency
|
|
112
118
|
name: appraisal
|
|
113
119
|
requirement: !ruby/object:Gem::Requirement
|
|
114
120
|
requirements:
|
|
115
121
|
- - "~>"
|
|
116
122
|
- !ruby/object:Gem::Version
|
|
117
|
-
version:
|
|
123
|
+
version: 2.4.1
|
|
118
124
|
type: :development
|
|
119
125
|
prerelease: false
|
|
120
126
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
127
|
requirements:
|
|
122
128
|
- - "~>"
|
|
123
129
|
- !ruby/object:Gem::Version
|
|
124
|
-
version:
|
|
130
|
+
version: 2.4.1
|
|
125
131
|
- !ruby/object:Gem::Dependency
|
|
126
132
|
name: simplecov
|
|
127
133
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -140,16 +146,16 @@ dependencies:
|
|
|
140
146
|
name: sqlite3
|
|
141
147
|
requirement: !ruby/object:Gem::Requirement
|
|
142
148
|
requirements:
|
|
143
|
-
- - "
|
|
149
|
+
- - "~>"
|
|
144
150
|
- !ruby/object:Gem::Version
|
|
145
|
-
version:
|
|
151
|
+
version: 1.4.0
|
|
146
152
|
type: :development
|
|
147
153
|
prerelease: false
|
|
148
154
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
155
|
requirements:
|
|
150
|
-
- - "
|
|
156
|
+
- - "~>"
|
|
151
157
|
- !ruby/object:Gem::Version
|
|
152
|
-
version:
|
|
158
|
+
version: 1.4.0
|
|
153
159
|
description: Add the ability to use the Google Authenticator with ActiveRecord.
|
|
154
160
|
email:
|
|
155
161
|
- jared.online@gmail.com
|
|
@@ -160,12 +166,12 @@ files:
|
|
|
160
166
|
- Appraisals
|
|
161
167
|
- CODE_OF_CONDUCT.md
|
|
162
168
|
- CONTRIBUTING.md
|
|
163
|
-
- Dockerfile
|
|
164
169
|
- Gemfile
|
|
165
170
|
- Gemfile.lock
|
|
166
171
|
- LICENSE
|
|
167
172
|
- README.md
|
|
168
173
|
- Rakefile
|
|
174
|
+
- google-authenticator.gemspec
|
|
169
175
|
- lib/google-authenticator-rails.rb
|
|
170
176
|
- lib/google-authenticator-rails/action_controller.rb
|
|
171
177
|
- lib/google-authenticator-rails/action_controller/rails_adapter.rb
|
|
@@ -187,7 +193,7 @@ files:
|
|
|
187
193
|
homepage: http://github.com/jaredonline/google-authenticator
|
|
188
194
|
licenses: []
|
|
189
195
|
metadata: {}
|
|
190
|
-
post_install_message:
|
|
196
|
+
post_install_message:
|
|
191
197
|
rdoc_options: []
|
|
192
198
|
require_paths:
|
|
193
199
|
- lib
|
|
@@ -202,9 +208,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
202
208
|
- !ruby/object:Gem::Version
|
|
203
209
|
version: '0'
|
|
204
210
|
requirements: []
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
signing_key:
|
|
211
|
+
rubygems_version: 3.3.15
|
|
212
|
+
signing_key:
|
|
208
213
|
specification_version: 4
|
|
209
214
|
summary: Add the ability to use the Google Authenticator with ActiveRecord.
|
|
210
215
|
test_files:
|
data/Dockerfile
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
FROM ruby:2.3.1
|
|
2
|
-
|
|
3
|
-
RUN mkdir -p /var/app
|
|
4
|
-
|
|
5
|
-
COPY Gemfile /var/app/Gemfile
|
|
6
|
-
COPY Gemfile.lock /var/app/Gemfile.lock
|
|
7
|
-
COPY google-authenticator.gemspec /var/app/google-authenticator.gemspec
|
|
8
|
-
COPY lib/google-authenticator-rails/version.rb /var/app/lib/google-authenticator-rails/version.rb
|
|
9
|
-
COPY Rakefile /var/app/Rakefile
|
|
10
|
-
COPY gemfiles/*.gemfile /var/app/
|
|
11
|
-
WORKDIR /var/app
|
|
12
|
-
|
|
13
|
-
RUN gem install bundler --version=1.15.4 --no-ri --no-rdoc
|
|
14
|
-
|
|
15
|
-
RUN bundle install
|
|
16
|
-
RUN bundle exec rake appraisal:install
|
|
17
|
-
|