two_factor_authentication 0.0.1
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.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE +19 -0
- data/README.md +81 -0
- data/Rakefile +1 -0
- data/app/controllers/devise/two_factor_authentication_controller.rb +43 -0
- data/app/views/devise/two_factor_authentication/max_login_attempts_reached.html.erb +3 -0
- data/app/views/devise/two_factor_authentication/show.html.erb +10 -0
- data/config/locales/en.yml +4 -0
- data/lib/generators/active_record/templates/migration.rb +8 -0
- data/lib/generators/active_record/two_factor_authentication_generator.rb +14 -0
- data/lib/generators/two_factor_authentication/two_factor_authentication_generator.rb +17 -0
- data/lib/two_factor_authentication.rb +27 -0
- data/lib/two_factor_authentication/controllers/helpers.rb +32 -0
- data/lib/two_factor_authentication/hooks/two_factor_authenticatable.rb +10 -0
- data/lib/two_factor_authentication/models/two_factor_authenticatable.rb +28 -0
- data/lib/two_factor_authentication/orm/active_record.rb +12 -0
- data/lib/two_factor_authentication/rails.rb +7 -0
- data/lib/two_factor_authentication/routes.rb +9 -0
- data/lib/two_factor_authentication/schema.rb +11 -0
- data/lib/two_factor_authentication/version.rb +3 -0
- data/two_factor_authentication.gemspec +32 -0
- metadata +133 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2012 Dmitrii Golub
|
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,81 @@
|
|
1
|
+
## Two factor authentication for Devise
|
2
|
+
|
3
|
+
## Features
|
4
|
+
|
5
|
+
* control sms code pattern
|
6
|
+
* configure max login attempts
|
7
|
+
* per user level control if he really need two factor authentication
|
8
|
+
* your own sms logic
|
9
|
+
|
10
|
+
## Configuration
|
11
|
+
|
12
|
+
### Initial Setup
|
13
|
+
|
14
|
+
In a Rails environment, require the gem in your Gemfile:
|
15
|
+
|
16
|
+
gem 'two_factor_authentication', git: "http://github.com/Houdini/two_factor_authentication.git"
|
17
|
+
|
18
|
+
Once that's done, run:
|
19
|
+
|
20
|
+
bundle install
|
21
|
+
|
22
|
+
|
23
|
+
### Automatic installation
|
24
|
+
|
25
|
+
In order to add two factor authorisation to a model, run the command:
|
26
|
+
|
27
|
+
bundle exec rails g two_factor_authentication MODEL
|
28
|
+
|
29
|
+
Where MODEL is your model name (e.g. User or Admin). This generator will add `:two_factor_authenticatable` to your model
|
30
|
+
and create a migration in `db/migrate/`, which will add `::second_factor_pass_code` and `:second_factor_attempts_count` to your table.
|
31
|
+
Finally, run the migration with:
|
32
|
+
|
33
|
+
bundle exec rake db:migrate
|
34
|
+
|
35
|
+
|
36
|
+
### Manual installation
|
37
|
+
|
38
|
+
To manually enable two factor authentication for the User model, you should add two_factor_authentication to your devise line, like:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
devise :database_authenticatable, :registerable,
|
42
|
+
:recoverable, :rememberable, :trackable, :validatable, :two_factor_authenticatable
|
43
|
+
```
|
44
|
+
|
45
|
+
Two default parameters
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
config.login_code_random_pattern = /\w+/
|
49
|
+
config.max_login_attempts = 3
|
50
|
+
```
|
51
|
+
|
52
|
+
Possible random patterns
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
/\d{5}/
|
56
|
+
/\w{4,8}/
|
57
|
+
```
|
58
|
+
|
59
|
+
see more https://github.com/benburkert/randexp
|
60
|
+
|
61
|
+
### Customisation
|
62
|
+
|
63
|
+
By default second factor authentication enabled for each user, you can change it with this method in your User model:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
def need_two_factor_authentication?(request)
|
67
|
+
request.ip != '127.0.0.1'
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
this will disable two factor authentication for local users
|
72
|
+
|
73
|
+
Your send sms logic should be in this method in your User model:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
def send_two_factor_authentication_code(code)
|
77
|
+
puts code
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
This example just puts the code in the logs.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Devise::TwoFactorAuthenticationController < DeviseController
|
2
|
+
prepend_before_filter :authenticate_scope!
|
3
|
+
before_filter :prepare_and_validate, :handle_two_factor_authentication
|
4
|
+
|
5
|
+
def show
|
6
|
+
end
|
7
|
+
|
8
|
+
def update
|
9
|
+
render :show and return if params[:code].nil?
|
10
|
+
md5 = Digest::MD5.hexdigest(params[:code])
|
11
|
+
if md5.eql?(resource.second_factor_pass_code)
|
12
|
+
warden.session(resource_name)[:need_two_factor_authentication] = false
|
13
|
+
sign_in resource_name, resource, :bypass => true
|
14
|
+
redirect_to stored_location_for(resource_name) || :root
|
15
|
+
resource.update_attribute(:second_factor_attempts_count, 0)
|
16
|
+
else
|
17
|
+
resource.second_factor_attempts_count += 1
|
18
|
+
resource.save
|
19
|
+
set_flash_message :notice, :attempt_failed
|
20
|
+
if resource.max_login_attempts?
|
21
|
+
sign_out(resource)
|
22
|
+
render :template => 'devise/two_factor_authentication/max_login_attempts_reached' and return
|
23
|
+
else
|
24
|
+
render :show
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def authenticate_scope!
|
32
|
+
self.resource = send("current_#{resource_name}")
|
33
|
+
end
|
34
|
+
|
35
|
+
def prepare_and_validate
|
36
|
+
redirect_to :root and return if resource.nil?
|
37
|
+
@limit = resource.class.max_login_attempts
|
38
|
+
if resource.max_login_attempts?
|
39
|
+
sign_out(resource)
|
40
|
+
render :template => 'devise/two_factor_authentication/max_login_attempts_reached' and return
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<h2>Enter your personal code</h2>
|
2
|
+
|
3
|
+
<p><%= flash[:notice] %></p>
|
4
|
+
|
5
|
+
<%= form_tag([resource_name, :two_factor_authentication], :method => :put) do %>
|
6
|
+
<%= text_field_tag :code %>
|
7
|
+
<%= submit_tag "Submit" %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class TwoFactorAuthenticationAddTo<%= table_name.camelize %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
change_table :<%= table_name %> do |t|
|
4
|
+
t.string :second_factor_pass_code , :limit => 32
|
5
|
+
t.integer :second_factor_attempts_count, :default => 0
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Generators
|
5
|
+
class TwoFactorAuthenticationGenerator < ActiveRecord::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
def copy_two_factor_authentication_migration
|
9
|
+
migration_template "migration.rb", "db/migrate/two_factor_authentication_add_to_#{table_name}"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module TwoFactorAuthenticatable
|
2
|
+
module Generators
|
3
|
+
class TwoFactorAuthenticationGenerator < Rails::Generators::NamedBase
|
4
|
+
namespace "two_factor_authentication"
|
5
|
+
|
6
|
+
desc "Adds :two_factor_authenticable directive in the given model. It also generates an active record migration."
|
7
|
+
|
8
|
+
def inject_two_factor_authentication_content
|
9
|
+
path = File.join("app", "models", "#{file_path}.rb")
|
10
|
+
inject_into_file(path, "two_factor_authenticatable, :", :after => "devise :") if File.exists?(path)
|
11
|
+
end
|
12
|
+
|
13
|
+
hook_for :orm
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'two_factor_authentication/version'
|
2
|
+
require 'randexp'
|
3
|
+
require 'devise'
|
4
|
+
require 'digest'
|
5
|
+
require 'active_support/concern'
|
6
|
+
|
7
|
+
module Devise
|
8
|
+
mattr_accessor :login_code_random_pattern
|
9
|
+
@@login_code_random_pattern = /\w+/
|
10
|
+
|
11
|
+
mattr_accessor :max_login_attempts
|
12
|
+
@@max_login_attempts = 3
|
13
|
+
end
|
14
|
+
|
15
|
+
module TwoFactorAuthentication
|
16
|
+
autoload :Schema, 'two_factor_authentication/schema'
|
17
|
+
module Controllers
|
18
|
+
autoload :Helpers, 'two_factor_authentication/controllers/helpers'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Devise.add_module :two_factor_authenticatable, :model => 'two_factor_authentication/models/two_factor_authenticatable', :controller => :two_factor_authentication, :route => :two_factor_authentication
|
23
|
+
|
24
|
+
require 'two_factor_authentication/orm/active_record'
|
25
|
+
require 'two_factor_authentication/routes'
|
26
|
+
require 'two_factor_authentication/models/two_factor_authenticatable'
|
27
|
+
require 'two_factor_authentication/rails'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module TwoFactorAuthentication
|
2
|
+
module Controllers
|
3
|
+
module Helpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_filter :handle_two_factor_authentication
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def handle_two_factor_authentication
|
13
|
+
if not request.format.nil? and request.format.html? and not devise_controller?
|
14
|
+
Devise.mappings.keys.flatten.any? do |scope|
|
15
|
+
if signed_in?(scope) and warden.session(scope)[:need_two_factor_authentication]
|
16
|
+
session["#{scope}_return_tor"] = request.path if request.get?
|
17
|
+
redirect_to two_factor_authentication_path_for(scope)
|
18
|
+
return
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def two_factor_authentication_path_for(resource_or_scope = nil)
|
25
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
26
|
+
change_path = "#{scope}_two_factor_authentication_path"
|
27
|
+
send(change_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Warden::Manager.after_authentication do |user, auth, options|
|
2
|
+
if user.respond_to?(:need_two_factor_authentication?)
|
3
|
+
if auth.session(options[:scope])[:need_two_factor_authentication] = user.need_two_factor_authentication?(auth.request)
|
4
|
+
code = user.generate_two_factor_code
|
5
|
+
user.second_factor_pass_code = Digest::MD5.hexdigest(code)
|
6
|
+
user.save
|
7
|
+
user.send_two_factor_authentication_code(code)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'two_factor_authentication/hooks/two_factor_authenticatable'
|
2
|
+
module Devise
|
3
|
+
module Models
|
4
|
+
module TwoFactorAuthenticatable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
::Devise::Models.config(self, :login_code_random_pattern, :max_login_attempts)
|
9
|
+
end
|
10
|
+
|
11
|
+
def need_two_factor_authentication?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate_two_factor_code
|
16
|
+
self.class.login_code_random_pattern.gen
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_two_factor_authentication_code(code)
|
20
|
+
p "Code is #{code}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def max_login_attempts?
|
24
|
+
second_factor_attempts_count >= self.class.max_login_attempts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module TwoFactorAuthentication
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
module Schema
|
5
|
+
include TwoFactorAuthentication::Schema
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveRecord::ConnectionAdapters::Table.send :include, TwoFactorAuthentication::Orm::ActiveRecord::Schema
|
12
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, TwoFactorAuthentication::Orm::ActiveRecord::Schema
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
class Mapper
|
3
|
+
protected
|
4
|
+
|
5
|
+
def devise_two_factor_authentication(mapping, controllers)
|
6
|
+
resource :two_factor_authentication, :only => [:show, :update], :path => mapping.path_names[:two_factor_authentication], :controller => controllers[:two_factor_authentication]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module TwoFactorAuthentication
|
2
|
+
module Schema
|
3
|
+
def second_factor_pass_code
|
4
|
+
apply_devise_schema :second_factor_pass_code, String, :limit => 32
|
5
|
+
end
|
6
|
+
|
7
|
+
def second_factor_attempts_count
|
8
|
+
apply_devise_schema :second_factor_attempts_count, Integer, :default => 0
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "two_factor_authentication/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "two_factor_authentication"
|
7
|
+
s.version = TwoFactorAuthentication::VERSION
|
8
|
+
s.authors = ["Dmitrii Golub"]
|
9
|
+
s.email = ["dmitrii.golub@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/Houdini/two_factor_authentication"
|
11
|
+
s.summary = %q{Two factor authentication plugin for devise}
|
12
|
+
s.description = <<-EOF
|
13
|
+
### Features ###
|
14
|
+
* control sms code pattern
|
15
|
+
* configure max login attempts
|
16
|
+
* per user level control if he really need two factor authentication
|
17
|
+
* your own sms logic
|
18
|
+
EOF
|
19
|
+
|
20
|
+
s.rubyforge_project = "two_factor_authentication"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
|
27
|
+
s.add_runtime_dependency 'rails', '>= 3.1.1'
|
28
|
+
s.add_runtime_dependency 'devise'
|
29
|
+
s.add_runtime_dependency 'randexp'
|
30
|
+
|
31
|
+
s.add_development_dependency 'bundler'
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: two_factor_authentication
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dmitrii Golub
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.1.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.1.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: devise
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: randexp
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: ! " ### Features ###\n * control sms code pattern\n * configure
|
79
|
+
max login attempts\n * per user level control if he really need two factor authentication\n
|
80
|
+
\ * your own sms logic\n"
|
81
|
+
email:
|
82
|
+
- dmitrii.golub@gmail.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- Gemfile
|
89
|
+
- LICENSE
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- app/controllers/devise/two_factor_authentication_controller.rb
|
93
|
+
- app/views/devise/two_factor_authentication/max_login_attempts_reached.html.erb
|
94
|
+
- app/views/devise/two_factor_authentication/show.html.erb
|
95
|
+
- config/locales/en.yml
|
96
|
+
- lib/generators/active_record/templates/migration.rb
|
97
|
+
- lib/generators/active_record/two_factor_authentication_generator.rb
|
98
|
+
- lib/generators/two_factor_authentication/two_factor_authentication_generator.rb
|
99
|
+
- lib/two_factor_authentication.rb
|
100
|
+
- lib/two_factor_authentication/controllers/helpers.rb
|
101
|
+
- lib/two_factor_authentication/hooks/two_factor_authenticatable.rb
|
102
|
+
- lib/two_factor_authentication/models/two_factor_authenticatable.rb
|
103
|
+
- lib/two_factor_authentication/orm/active_record.rb
|
104
|
+
- lib/two_factor_authentication/rails.rb
|
105
|
+
- lib/two_factor_authentication/routes.rb
|
106
|
+
- lib/two_factor_authentication/schema.rb
|
107
|
+
- lib/two_factor_authentication/version.rb
|
108
|
+
- two_factor_authentication.gemspec
|
109
|
+
homepage: https://github.com/Houdini/two_factor_authentication
|
110
|
+
licenses: []
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project: two_factor_authentication
|
129
|
+
rubygems_version: 1.8.24
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: Two factor authentication plugin for devise
|
133
|
+
test_files: []
|