google-authenticator-rails 0.0.4 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73fb9d2e9191704db8c7059225616e08336f4328
4
+ data.tar.gz: babaa2016345e654a937bed679374e3226e5fbe7
5
+ SHA512:
6
+ metadata.gz: eea521e18f89fe7f69e98ade4199a6b10386dd7f322fd91fb3ac24440d5f94bda5958eac67fb0997b0aee3ad3fa56f22fd01dd854a4629feb52940fffae6ca3e
7
+ data.tar.gz: b91ca64415d05ccf921508df87047f4b889ac84bd26870fe90d1e2fb6e574951d3cb04445a60c59cd8e9c9b86d3255bb60dbf98416068dfc94e741c0dae80019
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ google-auth-rails
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.5
data/.travis.yml CHANGED
@@ -1,11 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
3
  - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
6
  # - jruby-18mode # JRuby in 1.8 mode
7
7
  # - jruby-19mode # JRuby in 1.9 mode
8
- - rbx-18mode
9
- - rbx-19mode
10
- # uncomment this line if your project needs to run something other than `rake`:
11
- script: bundle exec rspec spec
8
+ # - rbx-18mode
9
+ # - rbx-19mode
data/Appraisals ADDED
@@ -0,0 +1,27 @@
1
+ version_info = RUBY_VERSION.split(".")
2
+
3
+ major = version_info.first.to_i
4
+ minor = version_info[1].to_i
5
+ hotfix = version_info.last.to_i
6
+
7
+ appraise "rails3.0" do
8
+ gem "activerecord", "~> 3.0.0"
9
+ end
10
+
11
+ appraise "rails3.1" do
12
+ gem "activerecord", "~> 3.1.0"
13
+ end
14
+
15
+ appraise "rails3.2." do
16
+ gem "activerecord", "~> 3.2.0"
17
+ end
18
+
19
+ appraise "rails4.0" do
20
+ gem "activerecord", "~> 4.0.0"
21
+ gem "protected_attributes"
22
+ end
23
+
24
+ appraise "rails4.1" do
25
+ gem "activerecord", "~> 4.1.0"
26
+ gem "protected_attributes"
27
+ end
data/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/google-authenticator-rails.png)](http://badge.fury.io/rb/google-authenticator-rails)
4
4
  [![Build Status](https://secure.travis-ci.org/jaredonline/google-authenticator.png)](http://travis-ci.org/jaredonline/google-authenticator)
5
+ [![Code Climate](https://codeclimate.com/github/jaredonline/google-authenticator.png)](https://codeclimate.com/github/jaredonline/google-authenticator)
5
6
 
6
- Rails (ActiveRecord) integration with the Google Authenticator apps for Android and the iPhone. Uses the Authlogic style for cookie management.
7
+ 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.
7
8
 
8
9
  ## Installation
9
10
 
@@ -25,30 +26,29 @@ Example:
25
26
 
26
27
  ```ruby
27
28
  class User
28
- acts_as_google_authenticated
29
+ acts_as_google_authenticated
29
30
  end
30
31
 
31
32
  @user = User.new
32
33
  @user.set_google_secret # => true
33
34
  @user.google_qr_uri # => http://path.to.google/qr?with=params
34
- @user.google_authentic?(123456) # => true
35
+ @user.google_authentic?(123456) # => true
35
36
  ```
36
37
 
37
- Google Labels
38
- When setting up an account with the GoogleAuthenticator you need to provide
39
- a label for that account (to distinguish it from other accounts).
38
+ ## Google Labels
39
+
40
+ When setting up an account with `GoogleAuthenticatorRails` you need to provide a label for that account (to distinguish it from other accounts).
40
41
 
41
- GoogleAuthenticatorRails allows you to customize how the record will create
42
- that label. There are three options:
43
- - The default just uses the column "email" on the model
44
- - You can specify a custom column with the :column_name option
42
+ `GoogleAuthenticatorRails` allows you to customize how the record will create that label. There are three options:
43
+ - The default just uses the column `email` on the model
44
+ - You can specify a custom column with the `:column_name` option
45
45
  - You can specify a custom method via a symbol or a proc
46
46
 
47
- Examples:
47
+ Example:
48
48
 
49
49
  ```ruby
50
50
  class User
51
- acts_as_google_authenticated :column => :user_name
51
+ acts_as_google_authenticated :column => :user_name
52
52
  end
53
53
 
54
54
  @user = User.new(:user_name => "ted")
@@ -77,6 +77,14 @@ end
77
77
  @user.google_label # => "TED@EXAMPLE.COM"
78
78
  ```
79
79
 
80
+ Here's what the labels look like in Google Authenticator for iPhone:
81
+
82
+ ![iPhone Label Screenshot](http://jaredonline.github.io/google-authenticator/images/gar-label.png)
83
+
84
+ ## Google Secret
85
+ The "google secret" is where `GoogleAuthenticatorRails` stores the
86
+ secret token used to generate the MFA code.
87
+
80
88
  You can also specify a column for storing the google secret. The default is `google_secret`.
81
89
 
82
90
  Example
@@ -91,19 +99,153 @@ end
91
99
  @user.mfa_secret # => "56ahi483"
92
100
  ```
93
101
 
102
+ ## Drift
103
+
104
+ You can specify a custom drift value. Drift is the number of seconds that the client
105
+ and server are allowed to drift apart. Default value is 5 seconds.
106
+
107
+ ```ruby
108
+ class User
109
+ act_as_google_authenticated :drift => 31
110
+ end
111
+ ```
112
+
113
+ ## Lookup Token
114
+
115
+ You can also specify which column the appropriate `MfaSession` subclass should use to look up the record:
116
+
117
+ Example
118
+
119
+ ```ruby
120
+ class User
121
+ acts_as_google_authenticated :lookup_token => :salt
122
+ end
123
+ ```
124
+
125
+ The above will cause the `UserMfaSession` class to call `User.where(:salt => cookie_salt)` or `User.scoped(:conditions => { :salt => cookie_salt })` to find the appropriate record.
126
+
127
+ ### A note about record lookup
128
+
129
+ `GoogleAuthenticatorRails` makes one very large assumption when attempting to lookup a record. If your `MfaSession` subclass is named `UserMfaSession` it assumes you're trying to lookup a `User` record. Currently, there is no way to configure this, so if you're trying to lookup a `VeryLongModelNameForUser` you'll need to name your `MfaSession` subclass `VeryLongModelNameForUserMfaSession`.
130
+
131
+ For example:
132
+
133
+ ```ruby
134
+ # app/models/user.rb
135
+ class User < ActiveRecord::Base
136
+ acts_as_google_authentic
137
+ end
138
+
139
+ # app/models/user_mfa_session.rb
140
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
141
+ end
142
+ ```
143
+
144
+ ### A note about cookie creation and `Session::Persistence::TokenNotFound`
145
+
146
+ `GoogleAuthenticatorRails` looks up the record based on the cookie created when you call `MfaSession#create`. The `#create` method looks into the record class (in our example, `User`) and looks at the configured `:lookup_token` option. It uses that option to save two pieces of information into the cookie, the `id` of the record and the token, which defaults to `persistence_token`. `persistence_token` is what Authlogic uses, which this gem was originally designed to work with.
147
+
148
+ This can cause a lot of headaches if the model isn't configured correctly, and will cause a `GoogleAuthenticatorRails::Session::Persistence::TokenNotFound` error.
149
+
150
+ This error appears for one of three reasons:
151
+
152
+ 1. `user` is `nil`
153
+ 2. `user` doesn't respond to `:persistence_token`
154
+ 3. `user.persistence_token` is blank
155
+
156
+ For example:
157
+
158
+ ```ruby
159
+ # app/models/user.rb
160
+ class User < ActiveRecord::Base
161
+ acts_as_google_authentic
162
+ end
163
+
164
+ # Model has attributes:
165
+ # id: integer
166
+ # name: string
167
+ # salt: string
168
+
169
+ # app/models/user_mfa_session.rb
170
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
171
+ end
172
+
173
+ # app/controllers/mfa_session_controller.rb
174
+ class MfaSessionController < ApplicationController
175
+ def create
176
+ UserMfaSession.create(user) # => Error: GoogleAuthenticatorRails::Session::Persistence::TokenNotFound
177
+ end
178
+ end
179
+ ```
180
+
181
+ The above example will fail because the `User` class doesn't have a `persistence_token` method. The fix for this is to configure `actions_as_google_authentic` to use the right column:
182
+
183
+ ```ruby
184
+ # app/models/user.rb
185
+ class User < ActiveRecord::Base
186
+ acts_as_google_authentic :lookup_token => :salt
187
+ end
188
+
189
+ # Model has attributes:
190
+ # id: integer
191
+ # name: string
192
+ # salt: string
193
+
194
+ # app/models/user_mfa_session.rb
195
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
196
+ end
197
+
198
+ # app/controllers/mfa_session_controller.rb
199
+ def class MfaSessionController < ApplicationController
200
+ def create
201
+ UserMfaSession.create(user)
202
+ end
203
+ end
204
+ ```
205
+
206
+ This call to `#create` will succeed (as long as `user.salt` is not `nil`).
207
+
208
+
209
+ ## Issuer
210
+
211
+ You can also specify a name for the 'issuer' (the name of the website) where the user is using this token:
212
+
213
+ Example
214
+
215
+ ```ruby
216
+ class User
217
+ acts_as_google_authenticated :issuer => 'example.com'
218
+ end
219
+ ```
220
+
221
+ This way your user will have the name of your site at the authenticator card besides the current token.
222
+
223
+ Here's what the issuers look like in Google Authenticator for iPhone:
224
+
225
+ ![iPhone Label Screenshot](http://jaredonline.github.io/google-authenticator/images/gar-issuer.png)
226
+
94
227
  ## Sample Rails Setup
95
228
 
96
- This is a very rough outline of how GoogleAuthenticatorRails is meant to manage the sessions and cookies for a Rails app.
229
+ This is a very rough outline of how `GoogleAuthenticatorRails` is meant to manage the sessions and cookies for a Rails app.
97
230
 
98
231
  ```ruby
99
- Gemfile
232
+ # Gemfile
100
233
 
101
234
  gem 'rails'
102
235
  gem 'google-authenticator-rails'
103
236
  ```
104
237
 
238
+ First add a field to your user model to hold the Google token.
239
+ ```ruby
240
+ class AddGoogleSecretToUser < ActiveRecord::Migration
241
+ def change
242
+ add_column :users, :google_secret, :string
243
+ end
244
+ end
245
+ ```
246
+
105
247
  ```ruby
106
- app/models/users.rb
248
+ # app/models/users.rb
107
249
 
108
250
  class User < ActiveRecord::Base
109
251
  acts_as_google_authenticated
@@ -113,18 +255,18 @@ end
113
255
  If you want to authenticate based on a model called `User`, then you should name your session object `UserMfaSession`.
114
256
 
115
257
  ```ruby
116
- app/models/user_mfa_session.rb
258
+ # app/models/user_mfa_session.rb
117
259
 
118
- class UserMfaSession < GoogleAuthenticator::Session::Base
260
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
119
261
  # no real code needed here
120
262
  end
121
263
  ```
122
264
 
123
265
  ```ruby
124
- app/controllers/user_mfa_session_controller.rb
266
+ # app/controllers/user_mfa_session_controller.rb
125
267
 
126
268
  class UserMfaSessionController < ApplicationController
127
-
269
+
128
270
  def new
129
271
  # load your view
130
272
  end
@@ -144,27 +286,46 @@ end
144
286
  ```
145
287
 
146
288
  ```ruby
147
- app/controllers/application_controller.rb
289
+ # app/controllers/application_controller.rb
148
290
 
149
291
  class ApplicationController < ActionController::Base
150
292
  before_filter :check_mfa
151
293
 
152
294
  private
153
295
  def check_mfa
154
- if !(user_mfa_session = UserMfaSession.find) && user_mfa_session.record == current_user
296
+ if !(user_mfa_session = UserMfaSession.find) && (user_mfa_session ? user_mfa_session.record == current_user : !user_mfa_session)
155
297
  redirect_to new_user_mfa_session_path
156
298
  end
157
299
  end
158
300
  end
159
301
  ```
160
302
 
161
- By default, the cookie related to the MfaSession expires in 24 hours, but this can be changed:
303
+ ## Cookie options
304
+
305
+ You can configure the MfaSession cookie by creating an initializer:
306
+
162
307
  ```ruby
163
- config/initializers/google_authenticator_rails.rb
308
+ # config/initializers/google_authenticator_rails.rb
164
309
 
310
+ # The cookie normally expires in 24 hours, you can change this to 1 month
165
311
  GoogleAuthenticatorRails.time_until_expiration = 1.month
312
+
313
+ # You can override the suffix of the cookie's key, by default this is mfa_credentials
314
+ GoogleAuthenticatorRails.cookie_key_suffix = 'mfa_credentials'
315
+
316
+ # Rails offers a few more cookie options, by default only :httponly is turned on, you can change it to HTTPS only:
317
+ GoogleAuthenticatorRails.cookie_options = { :httponly => true, :secure => true, :domain => :all }
166
318
  ```
167
319
 
320
+ Additional cookie option symbols can be found in the [Ruby on Rails guide](http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html).
321
+
322
+ ## Destroying the Cookie
323
+
324
+ If you want to manually destroy the MFA cookie (for example, when a user logs out), just call
325
+
326
+ ```ruby
327
+ UserMfaSession::destroy
328
+ ```
168
329
 
169
330
  ## Contributing
170
331
 
@@ -177,3 +338,4 @@ GoogleAuthenticatorRails.time_until_expiration = 1.month
177
338
  ## License
178
339
 
179
340
  MIT.
341
+
data/Rakefile CHANGED
@@ -1,2 +1,28 @@
1
1
  #!/usr/bin/env rake
2
+ require "bundler/setup"
2
3
  require "bundler/gem_tasks"
4
+ require "appraisal"
5
+
6
+ begin
7
+ # RSpec 2
8
+ require "rspec/core/rake_task"
9
+
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.pattern = "spec/**/*_spec.rb"
12
+ t.rspec_opts = "--color --format documentation --backtrace"
13
+ end
14
+ rescue LoadError
15
+ # RSpec 1
16
+ require "spec/rake/spectask"
17
+
18
+ Spec::Rake::SpecTask.new(:spec) do |t|
19
+ t.pattern = "spec/**/*_spec.rb"
20
+ t.spec_opts = ["--color", "--format nested", "--backtrace"]
21
+ end
22
+ end
23
+
24
+ desc "Default: Test the gem under all supported Rails versions."
25
+ task :default => ["appraisal:install"] do
26
+ exec("rake appraisal spec")
27
+ end
28
+
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 2.3.8"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (2.3.18)
14
+ activesupport (= 2.3.18)
15
+ rack (~> 1.1.0)
16
+ activerecord (2.3.18)
17
+ activesupport (= 2.3.18)
18
+ activesupport (2.3.18)
19
+ appraisal (0.5.2)
20
+ bundler
21
+ rake
22
+ diff-lcs (1.1.3)
23
+ google-qr (0.2.2)
24
+ rack (1.1.6)
25
+ rake (10.1.1)
26
+ rotp (1.6.1)
27
+ rspec (2.8.0)
28
+ rspec-core (~> 2.8.0)
29
+ rspec-expectations (~> 2.8.0)
30
+ rspec-mocks (~> 2.8.0)
31
+ rspec-core (2.8.0)
32
+ rspec-expectations (2.8.0)
33
+ diff-lcs (~> 1.1.2)
34
+ rspec-mocks (2.8.0)
35
+ sqlite3 (1.3.8)
36
+
37
+ PLATFORMS
38
+ ruby
39
+
40
+ DEPENDENCIES
41
+ activerecord (~> 2.3.8)
42
+ appraisal (~> 0.5.1)
43
+ google-authenticator-rails!
44
+ rspec (~> 2.8.0)
45
+ sqlite3
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.0.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ abstract (1.0.0)
14
+ actionpack (3.0.20)
15
+ activemodel (= 3.0.20)
16
+ activesupport (= 3.0.20)
17
+ builder (~> 2.1.2)
18
+ erubis (~> 2.6.6)
19
+ i18n (~> 0.5.0)
20
+ rack (~> 1.2.5)
21
+ rack-mount (~> 0.6.14)
22
+ rack-test (~> 0.5.7)
23
+ tzinfo (~> 0.3.23)
24
+ activemodel (3.0.20)
25
+ activesupport (= 3.0.20)
26
+ builder (~> 2.1.2)
27
+ i18n (~> 0.5.0)
28
+ activerecord (3.0.20)
29
+ activemodel (= 3.0.20)
30
+ activesupport (= 3.0.20)
31
+ arel (~> 2.0.10)
32
+ tzinfo (~> 0.3.23)
33
+ activesupport (3.0.20)
34
+ appraisal (0.5.2)
35
+ bundler
36
+ rake
37
+ arel (2.0.10)
38
+ builder (2.1.2)
39
+ diff-lcs (1.1.3)
40
+ erubis (2.6.6)
41
+ abstract (>= 1.0.0)
42
+ google-qr (0.2.2)
43
+ i18n (0.5.3)
44
+ rack (1.2.8)
45
+ rack-mount (0.6.14)
46
+ rack (>= 1.0.0)
47
+ rack-test (0.5.7)
48
+ rack (>= 1.0)
49
+ rake (10.1.1)
50
+ rotp (1.6.1)
51
+ rspec (2.8.0)
52
+ rspec-core (~> 2.8.0)
53
+ rspec-expectations (~> 2.8.0)
54
+ rspec-mocks (~> 2.8.0)
55
+ rspec-core (2.8.0)
56
+ rspec-expectations (2.8.0)
57
+ diff-lcs (~> 1.1.2)
58
+ rspec-mocks (2.8.0)
59
+ sqlite3 (1.3.8)
60
+ tzinfo (0.3.38)
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ activerecord (~> 3.0.0)
67
+ appraisal (~> 0.5.1)
68
+ google-authenticator-rails!
69
+ rspec (~> 2.8.0)
70
+ sqlite3
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.1.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (3.1.12)
14
+ activemodel (= 3.1.12)
15
+ activesupport (= 3.1.12)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ i18n (~> 0.6)
19
+ rack (~> 1.3.6)
20
+ rack-cache (~> 1.2)
21
+ rack-mount (~> 0.8.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.0.4)
24
+ activemodel (3.1.12)
25
+ activesupport (= 3.1.12)
26
+ builder (~> 3.0.0)
27
+ i18n (~> 0.6)
28
+ activerecord (3.1.12)
29
+ activemodel (= 3.1.12)
30
+ activesupport (= 3.1.12)
31
+ arel (~> 2.2.3)
32
+ tzinfo (~> 0.3.29)
33
+ activesupport (3.1.12)
34
+ multi_json (~> 1.0)
35
+ appraisal (0.5.2)
36
+ bundler
37
+ rake
38
+ arel (2.2.3)
39
+ builder (3.0.4)
40
+ diff-lcs (1.1.3)
41
+ erubis (2.7.0)
42
+ google-qr (0.2.2)
43
+ hike (1.2.3)
44
+ i18n (0.6.9)
45
+ multi_json (1.8.4)
46
+ rack (1.3.10)
47
+ rack-cache (1.2)
48
+ rack (>= 0.4)
49
+ rack-mount (0.8.3)
50
+ rack (>= 1.0.0)
51
+ rack-test (0.6.2)
52
+ rack (>= 1.0)
53
+ rake (10.1.1)
54
+ rotp (1.6.1)
55
+ rspec (2.8.0)
56
+ rspec-core (~> 2.8.0)
57
+ rspec-expectations (~> 2.8.0)
58
+ rspec-mocks (~> 2.8.0)
59
+ rspec-core (2.8.0)
60
+ rspec-expectations (2.8.0)
61
+ diff-lcs (~> 1.1.2)
62
+ rspec-mocks (2.8.0)
63
+ sprockets (2.0.5)
64
+ hike (~> 1.2)
65
+ rack (~> 1.0)
66
+ tilt (~> 1.1, != 1.3.0)
67
+ sqlite3 (1.3.8)
68
+ tilt (1.4.1)
69
+ tzinfo (0.3.38)
70
+
71
+ PLATFORMS
72
+ ruby
73
+
74
+ DEPENDENCIES
75
+ activerecord (~> 3.1.0)
76
+ appraisal (~> 0.5.1)
77
+ google-authenticator-rails!
78
+ rspec (~> 2.8.0)
79
+ sqlite3
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.2.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (3.2.13)
14
+ activemodel (= 3.2.13)
15
+ activesupport (= 3.2.13)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ journey (~> 1.0.4)
19
+ rack (~> 1.4.5)
20
+ rack-cache (~> 1.2)
21
+ rack-test (~> 0.6.1)
22
+ sprockets (~> 2.2.1)
23
+ activemodel (3.2.13)
24
+ activesupport (= 3.2.13)
25
+ builder (~> 3.0.0)
26
+ activerecord (3.2.13)
27
+ activemodel (= 3.2.13)
28
+ activesupport (= 3.2.13)
29
+ arel (~> 3.0.2)
30
+ tzinfo (~> 0.3.29)
31
+ activesupport (3.2.13)
32
+ i18n (= 0.6.1)
33
+ multi_json (~> 1.0)
34
+ appraisal (0.5.2)
35
+ bundler
36
+ rake
37
+ arel (3.0.2)
38
+ builder (3.0.4)
39
+ diff-lcs (1.1.3)
40
+ erubis (2.7.0)
41
+ google-qr (0.2.2)
42
+ hike (1.2.3)
43
+ i18n (0.6.1)
44
+ journey (1.0.4)
45
+ multi_json (1.8.4)
46
+ rack (1.4.5)
47
+ rack-cache (1.2)
48
+ rack (>= 0.4)
49
+ rack-test (0.6.2)
50
+ rack (>= 1.0)
51
+ rake (10.1.1)
52
+ rotp (1.6.1)
53
+ rspec (2.8.0)
54
+ rspec-core (~> 2.8.0)
55
+ rspec-expectations (~> 2.8.0)
56
+ rspec-mocks (~> 2.8.0)
57
+ rspec-core (2.8.0)
58
+ rspec-expectations (2.8.0)
59
+ diff-lcs (~> 1.1.2)
60
+ rspec-mocks (2.8.0)
61
+ sprockets (2.2.3)
62
+ hike (~> 1.2)
63
+ multi_json (~> 1.0)
64
+ rack (~> 1.0)
65
+ tilt (~> 1.1, != 1.3.0)
66
+ sqlite3 (1.3.8)
67
+ tilt (1.4.1)
68
+ tzinfo (0.3.38)
69
+
70
+ PLATFORMS
71
+ ruby
72
+
73
+ DEPENDENCIES
74
+ activerecord (~> 3.2.0)
75
+ appraisal (~> 0.5.1)
76
+ google-authenticator-rails!
77
+ rspec (~> 2.8.0)
78
+ sqlite3