devise_google_authenticator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "rails"
6
+ gem "devise"
7
+ gem "rotp"
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "shoulda", ">= 0"
13
+ gem "bundler", "~> 1.0.0"
14
+ gem "jeweler", "~> 1.6.4"
15
+ gem "rcov", ">= 0"
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,109 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.1.1)
5
+ actionpack (= 3.1.1)
6
+ mail (~> 2.3.0)
7
+ actionpack (3.1.1)
8
+ activemodel (= 3.1.1)
9
+ activesupport (= 3.1.1)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ i18n (~> 0.6)
13
+ rack (~> 1.3.2)
14
+ rack-cache (~> 1.1)
15
+ rack-mount (~> 0.8.2)
16
+ rack-test (~> 0.6.1)
17
+ sprockets (~> 2.0.2)
18
+ activemodel (3.1.1)
19
+ activesupport (= 3.1.1)
20
+ builder (~> 3.0.0)
21
+ i18n (~> 0.6)
22
+ activerecord (3.1.1)
23
+ activemodel (= 3.1.1)
24
+ activesupport (= 3.1.1)
25
+ arel (~> 2.2.1)
26
+ tzinfo (~> 0.3.29)
27
+ activeresource (3.1.1)
28
+ activemodel (= 3.1.1)
29
+ activesupport (= 3.1.1)
30
+ activesupport (3.1.1)
31
+ multi_json (~> 1.0)
32
+ arel (2.2.1)
33
+ bcrypt-ruby (3.0.1)
34
+ builder (3.0.0)
35
+ devise (1.4.9)
36
+ bcrypt-ruby (~> 3.0)
37
+ orm_adapter (~> 0.0.3)
38
+ warden (~> 1.0.3)
39
+ erubis (2.7.0)
40
+ git (1.2.5)
41
+ hike (1.2.1)
42
+ i18n (0.6.0)
43
+ jeweler (1.6.4)
44
+ bundler (~> 1.0)
45
+ git (>= 1.2.5)
46
+ rake
47
+ json (1.6.1)
48
+ mail (2.3.0)
49
+ i18n (>= 0.4.0)
50
+ mime-types (~> 1.16)
51
+ treetop (~> 1.4.8)
52
+ mime-types (1.17.2)
53
+ multi_json (1.0.3)
54
+ orm_adapter (0.0.5)
55
+ polyglot (0.3.3)
56
+ rack (1.3.5)
57
+ rack-cache (1.1)
58
+ rack (>= 0.4)
59
+ rack-mount (0.8.3)
60
+ rack (>= 1.0.0)
61
+ rack-ssl (1.3.2)
62
+ rack
63
+ rack-test (0.6.1)
64
+ rack (>= 1.0)
65
+ rails (3.1.1)
66
+ actionmailer (= 3.1.1)
67
+ actionpack (= 3.1.1)
68
+ activerecord (= 3.1.1)
69
+ activeresource (= 3.1.1)
70
+ activesupport (= 3.1.1)
71
+ bundler (~> 1.0)
72
+ railties (= 3.1.1)
73
+ railties (3.1.1)
74
+ actionpack (= 3.1.1)
75
+ activesupport (= 3.1.1)
76
+ rack-ssl (~> 1.3.2)
77
+ rake (>= 0.8.7)
78
+ rdoc (~> 3.4)
79
+ thor (~> 0.14.6)
80
+ rake (0.9.2.2)
81
+ rcov (0.9.11)
82
+ rdoc (3.11)
83
+ json (~> 1.4)
84
+ rotp (1.3.2)
85
+ shoulda (2.11.3)
86
+ sprockets (2.0.3)
87
+ hike (~> 1.2)
88
+ rack (~> 1.0)
89
+ tilt (~> 1.1, != 1.3.0)
90
+ thor (0.14.6)
91
+ tilt (1.3.3)
92
+ treetop (1.4.10)
93
+ polyglot
94
+ polyglot (>= 0.3.1)
95
+ tzinfo (0.3.31)
96
+ warden (1.0.6)
97
+ rack (>= 1.0)
98
+
99
+ PLATFORMS
100
+ ruby
101
+
102
+ DEPENDENCIES
103
+ bundler (~> 1.0.0)
104
+ devise
105
+ jeweler (~> 1.6.4)
106
+ rails
107
+ rcov
108
+ rotp
109
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Christian Frichot
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = devise_google_authenticator
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to devise_google_authenticator
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Christian Frichot. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "devise_google_authenticator"
18
+ gem.homepage = "http://github.com/xntrik/devise_google_authenticator"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Devise Google Authenticator Extension}
21
+ gem.description = %Q{Devise Google Authenticator Extension, for adding Google's OTP to your Rails apps!}
22
+ gem.email = "xntrik@gmail.com"
23
+ gem.authors = ["Christian Frichot"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "devise_google_authenticator #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,13 @@
1
+ class Devise::CheckgaController < Devise::SessionsController
2
+ prepend_before_filter :require_no_authentication, :only => [ :show, :update ]
3
+ include Devise::Controllers::InternalHelpers
4
+
5
+ def show
6
+ render_with_scope :show
7
+ end
8
+
9
+ def update
10
+ sign_in(resource_name, resource)
11
+ respond_with resource, :location => redirect_location(resource_name, resource)
12
+ end
13
+ end
@@ -0,0 +1,35 @@
1
+ class Devise::DisplayqrController < ApplicationController
2
+ prepend_before_filter :authenticate_scope!, :only => [:show,:update]
3
+
4
+ include Devise::Controllers::InternalHelpers
5
+
6
+ def show
7
+ if not resource.nil? and not resource.gauth_secret.nil?
8
+ render_with_scope :show
9
+ else
10
+ sign_in scope, resource, :bypass => true
11
+ redirect_to stored_location_for(scope) || :root
12
+ end
13
+ end
14
+
15
+ def update
16
+ tmp = params[resource_name]
17
+ if resource.set_gauth_enabled(params[resource_name])
18
+ set_flash_message :notice, "Status Updated!"
19
+ sign_in scope, resource, :bypass => true
20
+ redirect_to stored_location_for(scope) || :root
21
+ else
22
+ render_with_scope :show
23
+ end
24
+ end
25
+
26
+ private
27
+ def scope
28
+ resource_name.to_sym
29
+ end
30
+
31
+ def authenticate_scope!
32
+ send(:"authenticate_#{resource_name}!")
33
+ self.resource = send("current_#{resource_name}")
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+ <h2>Submit QR Code</h2>
2
+
3
+ <%= form_for(resource, :as => resource_name, :url => [resource_name, :checkga], :html => { :method => :put }) do |f| %>
4
+
5
+ <p><%= f.submit "Continue.." %></p>
6
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <h2>Your QR Code</h2>
2
+
3
+ <%= google_authenticator_qrcode(resource) %>
4
+
5
+ <%= form_for(resource, :as => resource_name, :url => [resource_name, :displayqr], :html => { :method => :put }) do |f| %>
6
+ <%= devise_error_messages! %>
7
+ <h3>Would you like to enable Google Authenticator?</h3>
8
+ <p><%= f.label :gauth_enabled, "Google Authenticator Status" %><br />
9
+ <%= f.check_box :gauth_enabled %></p>
10
+
11
+ <p><%= f.submit "Continue.." %></p>
12
+ <% end %>
@@ -0,0 +1,82 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "devise_google_authenticator"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Christian Frichot"]
12
+ s.date = "2011-11-21"
13
+ s.description = "Devise Google Authenticator Extension, for adding Google's OTP to your Rails apps!"
14
+ s.email = "xntrik@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "app/controllers/devise/checkga_controller.rb",
28
+ "app/controllers/devise/displayqr_controller.rb",
29
+ "app/views/devise/checkga/show.html.erb",
30
+ "app/views/devise/displayqr/show.html.erb",
31
+ "devise_google_authenticator.gemspec",
32
+ "lib/devise_google_authenticatable/controllers/helpers.rb",
33
+ "lib/devise_google_authenticatable/hooks/google_authenticatable.rb",
34
+ "lib/devise_google_authenticatable/models/google_authenticatable.rb",
35
+ "lib/devise_google_authenticatable/orm/active_record.rb",
36
+ "lib/devise_google_authenticatable/patches.rb",
37
+ "lib/devise_google_authenticatable/patches/check_ga.rb",
38
+ "lib/devise_google_authenticatable/patches/display_qr.rb",
39
+ "lib/devise_google_authenticatable/rails.rb",
40
+ "lib/devise_google_authenticatable/routes.rb",
41
+ "lib/devise_google_authenticatable/schema.rb",
42
+ "lib/devise_google_authenticator.rb",
43
+ "test/helper.rb",
44
+ "test/test_devise_google_authenticator.rb"
45
+ ]
46
+ s.homepage = "http://github.com/xntrik/devise_google_authenticator"
47
+ s.licenses = ["MIT"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = "1.8.10"
50
+ s.summary = "Devise Google Authenticator Extension"
51
+
52
+ if s.respond_to? :specification_version then
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
56
+ s.add_runtime_dependency(%q<rails>, [">= 0"])
57
+ s.add_runtime_dependency(%q<devise>, [">= 0"])
58
+ s.add_runtime_dependency(%q<rotp>, [">= 0"])
59
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
60
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
61
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
62
+ s.add_development_dependency(%q<rcov>, [">= 0"])
63
+ else
64
+ s.add_dependency(%q<rails>, [">= 0"])
65
+ s.add_dependency(%q<devise>, [">= 0"])
66
+ s.add_dependency(%q<rotp>, [">= 0"])
67
+ s.add_dependency(%q<shoulda>, [">= 0"])
68
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
70
+ s.add_dependency(%q<rcov>, [">= 0"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<rails>, [">= 0"])
74
+ s.add_dependency(%q<devise>, [">= 0"])
75
+ s.add_dependency(%q<rotp>, [">= 0"])
76
+ s.add_dependency(%q<shoulda>, [">= 0"])
77
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
78
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
79
+ s.add_dependency(%q<rcov>, [">= 0"])
80
+ end
81
+ end
82
+
@@ -0,0 +1,17 @@
1
+ module DeviseGoogleAuthenticator
2
+ module Controllers # :nodoc:
3
+ module Helpers # :nodoc:
4
+ def google_authenticator_qrcode(user)
5
+ data = "otpauth://totp/#{username_from_email(user.email)}@#{Rails.application.class.parent_name}?secret=#{user.gauth_secret}"
6
+ data = Rack::Utils.escape(data)
7
+ url = "https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=#{data}"
8
+ return image_tag(url, :alt => 'Google Authenticator QRCode')
9
+ end
10
+
11
+ def username_from_email(email)
12
+ (/^(.*)@/).match(email)[1]
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ Warden::Manager.after_set_user do |record, warden, options|
2
+ if record.respond_to?(:login_phase_one)
3
+ if warden.session(options[:scope]).fetch(:gauth_phase_one,"nope") == "nope"
4
+ redirect_to :controller => 'checkga', :action => 'show'
5
+ end
6
+ #warden.session(options[:scope])[:gauth_phase_one]
7
+ #respond_with record, :location => {:controller => 'checkga', :action => 'show'}
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ require 'rotp'
2
+ #require 'devise_google_authenticatable/hooks/google_authenticatable'
3
+
4
+ module Devise # :nodoc:
5
+ module Models # :nodoc:
6
+
7
+ module GoogleAuthenticatable
8
+
9
+ def self.included(base) # :nodoc:
10
+ base.extend ClassMethods
11
+
12
+ base.class_eval do
13
+ before_validation :assign_auth_secret, :on => :create
14
+ include InstanceMethods
15
+ end
16
+ end
17
+
18
+ module InstanceMethods # :nodoc:
19
+ def get_qr
20
+ self.gauth_secret
21
+ end
22
+
23
+ def set_gauth_enabled(param)
24
+ self.update_without_password(param)
25
+ end
26
+
27
+ def login_phase_one
28
+ return "yep"
29
+ end
30
+
31
+ private
32
+
33
+ def assign_auth_secret
34
+ self.gauth_secret = ROTP::Base32.random_base32
35
+ end
36
+
37
+ end
38
+
39
+ module ClassMethods # :nodoc:
40
+ #Something here?
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ module DeviseGoogleAuthenticator
2
+ module Orm
3
+ # This module contains handle schema (migrations):
4
+ #
5
+ # create_table :accounts do |t|
6
+ # t.gauth_secret
7
+ # t.gauth_enabled
8
+ # end
9
+ #
10
+
11
+ module ActiveRecord
12
+ module Schema
13
+ include DeviseGoogleAuthenticator::Schema
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+
20
+ ActiveRecord::ConnectionAdapters::Table.send :include, DeviseGoogleAuthenticator::Orm::ActiveRecord::Schema
21
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, DeviseGoogleAuthenticator::Orm::ActiveRecord::Schema
@@ -0,0 +1,90 @@
1
+ module DeviseGoogleAuthenticator::Patches
2
+ # patch Sessions controller to check that the OTP is accurate
3
+ module CheckGA
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ # here the patch
7
+
8
+ alias_method :create_original, :create
9
+
10
+ #Below is trial 1 .. over-writing most of the create method
11
+ #Whilst this works, I wish it was about a gazillion times cleaner
12
+
13
+ define_method :create do
14
+ #Okay, firstly we grab the resource, if the user stuffs up anything, this dies immediately.
15
+ #This actually authenticates their password
16
+ resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
17
+
18
+ #Okay, check that the resource model includes the get_qr method
19
+ if resource.respond_to?(:get_qr) #Therefore we can quiz for a QR
20
+
21
+ # Okay, we have the method to get the qr secret, lets check if the user has gauth enabled
22
+ if resource.gauth_enabled.to_i != 0 #gauth_enabled is not set to zero, therefore it's ON!
23
+
24
+ # Orite, At this point the user model includes the extension stuff
25
+ # PLUS, gauth_enabled is ON, so lets try and authenticate .. but first
26
+
27
+ # Lets check if the "POST" includes the gauth_submit parameter
28
+ if params.fetch(resource_name).include?("gauth_submit") #Yep, the browser submitted the gauth_submit - OTP
29
+
30
+ #Okay, lets get what they submitted in the form, crunch it into an int
31
+ submitted_value = params.fetch(resource_name).fetch("gauth_submit").to_i
32
+
33
+ #By default, gauth is not successful
34
+ gauth_successful = false
35
+
36
+ if submitted_value == 0 #We have a field, but they've left it blank..
37
+ #Nothing, they left the field blank, and therefore will not sign in, gauth_successfull remains false
38
+ else
39
+ #Okay, they submitted something into the OTP field
40
+
41
+ #Lets account for the fact the timing may not always be accurate, so go backwards, current and forwards
42
+ #If the submitted OTP matches, then gauth_successful is true - YAY for you! .. Yay for you indeed.
43
+
44
+ #CF TODO: Do some checking here, how late can these codes be??
45
+ if submitted_value == ROTP::TOTP.new(resource.get_qr).at(Time.now.ago(30))
46
+ gauth_successful = true
47
+ elsif submitted_value == ROTP::TOTP.new(resource.get_qr).at(Time.now)
48
+ gauth_successful = true
49
+ elsif submitted_value == ROTP::TOTP.new(resource.get_qr).at(Time.now.in(30))
50
+ gauth_successful = true
51
+ end
52
+ end
53
+
54
+ if gauth_successful == true #That means the OTP actually worked, lets log 'em in
55
+ set_flash_message(:notice, :signed_in) if is_navigational_format?
56
+ sign_in(resource_name, resource)
57
+ respond_with resource, :location => redirect_location(resource_name, resource)
58
+ else #That means that, the OTP did NOT line up properly, lets kick 'em back to the start
59
+ signed_in = signed_in?(resource_name)
60
+ Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
61
+ resource = build_resource
62
+ clean_up_passwords(resource)
63
+ respond_with resource, :location => {:controller => 'sessions', :action => 'new'}
64
+ end
65
+
66
+ else #Okay, this is odd, the user is all set to go, but the browser did NOT include the OTP, tampering occurred
67
+ # OR - the developer did NOT modify the "sessions" view to include
68
+ # TODO: What should they put in the view again?
69
+
70
+ #At this point, we're going to log them back out and send them back to the start
71
+ signed_in = signed_in?(resource_name)
72
+ Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
73
+ resource = build_resource
74
+ clean_up_passwords(resource)
75
+ respond_with resource, :location => {:controller => 'sessions', :action => 'new'}
76
+ end
77
+ else #gauth_enabled must have been set to zero, therefore it's off .. lets just continue with the original sign in process
78
+ set_flash_message(:notice, :signed_in) if is_navigational_format?
79
+ sign_in(resource_name, resource)
80
+ respond_with resource, :location => redirect_location(resource_name, resource)
81
+ end
82
+ else #It looks like the model did NOT include the get_qr method .. lets just continue with the original sign in process
83
+ set_flash_message(:notice, :signed_in) if is_navigational_format?
84
+ sign_in(resource_name, resource)
85
+ respond_with resource, :location => redirect_location(resource_name, resource)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,31 @@
1
+ module DeviseGoogleAuthenticator::Patches
2
+ # patch Registrations controller to display the QR code
3
+ module DisplayQR
4
+ extend ActiveSupport::Concern
5
+ included do
6
+
7
+ #arrr be the patch
8
+ alias_method :create_original, :create
9
+
10
+ define_method :create do
11
+ build_resource
12
+
13
+ if resource.save
14
+ if resource.active_for_authentication?
15
+ set_flash_message :notice, :signed_up if is_navigational_format?
16
+ sign_in(resource_name, resource)
17
+
18
+ respond_with resource, :location => {:controller => 'displayqr', :action => 'show'}
19
+ else
20
+ set_flash_message :notice, :inactive_signed_up, :reason => inactive_reason(resource) if is_navigational_format?
21
+ expire_session_data_after_sign_in!
22
+ respond_with resource, :location => after_inactive_sign_up_path_for(resource)
23
+ end
24
+ else
25
+ clean_up_passwords(resource)
26
+ respond_with_navigational(resource) { render_with_scope :new }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module DeviseGoogleAuthenticator
2
+ module Patches
3
+ autoload :DisplayQR, 'devise_google_authenticatable/patches/display_qr'
4
+ autoload :CheckGA, 'devise_google_authenticatable/patches/check_ga'
5
+
6
+ class << self
7
+ def apply
8
+ Devise::RegistrationsController.send(:include, Patches::DisplayQR)
9
+ Devise::SessionsController.send(:include, Patches::CheckGA)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module DeviseGoogleAuthenticator
2
+ class Engine < ::Rails::Engine # :nodoc:
3
+ ActionDispatch::Callbacks.to_prepare do
4
+ DeviseGoogleAuthenticator::Patches.apply
5
+ end
6
+
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ module ActionDispatch::Routing # :nodoc:
2
+ class Mapper # :nodoc:
3
+
4
+ protected
5
+
6
+ # route for handle expired passwords
7
+ def devise_displayqr(mapping, controllers)
8
+ resource :displayqr, :only => [:show, :update], :path => mapping.path_names[:displayqr], :controller => controllers[:displayqr]
9
+ resource :checkga, :only => [:show, :update], :path => mapping.path_names[:checkga], :controller => controllers[:checkga]
10
+ end
11
+
12
+ end
13
+ end
14
+
@@ -0,0 +1,30 @@
1
+ module DeviseGoogleAuthenticator
2
+ # add schema helper for migrations
3
+ module Schema
4
+ # Add gauth_secret columns in the resource's database tables
5
+ #
6
+ # Examples
7
+ #
8
+ # # For a new resource migration:
9
+ # create_table :the_resources do |t|
10
+ # t.gauth_secret
11
+ # t.gauth_enabled
12
+ # ...
13
+ # end
14
+ #
15
+ # # or if the resource's table already exists, define a migration and put this in:
16
+ # change_table :the_resources do |t|
17
+ # t.string :gauth_secret
18
+ # t.boolean :gauth_enabled
19
+ # end
20
+ #
21
+ def gauth_secret
22
+ apply_devise_schema :gauth_secret, String
23
+ end
24
+
25
+ def gauth_enabled
26
+ apply_devise_schema :gauth_enabled, Integer, {:default => 0}
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_record/connection_adapters/abstract/schema_definitions'
2
+ require 'active_support/core_ext/integer'
3
+ require 'active_support/core_ext/string'
4
+ require 'active_support/ordered_hash'
5
+ require 'active_support/concern'
6
+ require 'devise'
7
+
8
+ # a security extension for devise
9
+ module DeviseGoogleAuthenticator
10
+ autoload :Schema, 'devise_google_authenticatable/schema'
11
+ autoload :Patches, 'devise_google_authenticatable/patches'
12
+
13
+ # module Controllers # :nodoc:
14
+ # autoload :Helpers, 'devise_google_authenticatable/controllers/helpers'
15
+ # end
16
+ end
17
+
18
+
19
+
20
+ require 'devise_google_authenticatable/routes'
21
+ require 'devise_google_authenticatable/rails'
22
+ require 'devise_google_authenticatable/orm/active_record'
23
+ require 'devise_google_authenticatable/controllers/helpers'
24
+ ActionView::Base.send :include, DeviseGoogleAuthenticator::Controllers::Helpers
25
+
26
+ Devise.add_module :google_authenticatable, :controller => :google_authenticatable, :model => 'devise_google_authenticatable/models/google_authenticatable', :route => :displayqr
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'devise_google_authenticator'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestDeviseGoogleAuthenticator < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devise_google_authenticator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Christian Frichot
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-21 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: &70249517217040 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70249517217040
25
+ - !ruby/object:Gem::Dependency
26
+ name: devise
27
+ requirement: &70249517216520 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70249517216520
36
+ - !ruby/object:Gem::Dependency
37
+ name: rotp
38
+ requirement: &70249517215940 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70249517215940
47
+ - !ruby/object:Gem::Dependency
48
+ name: shoulda
49
+ requirement: &70249517215320 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70249517215320
58
+ - !ruby/object:Gem::Dependency
59
+ name: bundler
60
+ requirement: &70249517214560 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.0.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70249517214560
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: &70249517213420 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.6.4
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70249517213420
80
+ - !ruby/object:Gem::Dependency
81
+ name: rcov
82
+ requirement: &70249517212620 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70249517212620
91
+ description: Devise Google Authenticator Extension, for adding Google's OTP to your
92
+ Rails apps!
93
+ email: xntrik@gmail.com
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files:
97
+ - LICENSE.txt
98
+ - README.rdoc
99
+ files:
100
+ - .document
101
+ - Gemfile
102
+ - Gemfile.lock
103
+ - LICENSE.txt
104
+ - README.rdoc
105
+ - Rakefile
106
+ - VERSION
107
+ - app/controllers/devise/checkga_controller.rb
108
+ - app/controllers/devise/displayqr_controller.rb
109
+ - app/views/devise/checkga/show.html.erb
110
+ - app/views/devise/displayqr/show.html.erb
111
+ - devise_google_authenticator.gemspec
112
+ - lib/devise_google_authenticatable/controllers/helpers.rb
113
+ - lib/devise_google_authenticatable/hooks/google_authenticatable.rb
114
+ - lib/devise_google_authenticatable/models/google_authenticatable.rb
115
+ - lib/devise_google_authenticatable/orm/active_record.rb
116
+ - lib/devise_google_authenticatable/patches.rb
117
+ - lib/devise_google_authenticatable/patches/check_ga.rb
118
+ - lib/devise_google_authenticatable/patches/display_qr.rb
119
+ - lib/devise_google_authenticatable/rails.rb
120
+ - lib/devise_google_authenticatable/routes.rb
121
+ - lib/devise_google_authenticatable/schema.rb
122
+ - lib/devise_google_authenticator.rb
123
+ - test/helper.rb
124
+ - test/test_devise_google_authenticator.rb
125
+ homepage: http://github.com/xntrik/devise_google_authenticator
126
+ licenses:
127
+ - MIT
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ segments:
139
+ - 0
140
+ hash: -1606279146511615943
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 1.8.10
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: Devise Google Authenticator Extension
153
+ test_files: []