yubikey_database_authenticatable 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Stephen Kapp
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.md ADDED
@@ -0,0 +1,48 @@
1
+ # Devise - Yubikey Database Authentication
2
+
3
+ This extension to Devise adds a modified Database Authentication strategy to allow the authentication of a user with Two Factor Authentication provided by the Yubikey OTP token
4
+
5
+ This extension requires the used to already have a valid account and password and verifies that the user exists along with the password provided by verifying that the user presented a valid Yubikey OTP.
6
+
7
+ ## Installation
8
+
9
+ This plugin requires Rails 3.0.x+ and Devise 1.3.4+. Additionally the Yubikey Ruby library found here is required.
10
+
11
+ <https://github.com/titanous/yubikey>
12
+
13
+ The gem for the Yubikey library will need to be added to your Gemfile. Currently this can only be installed as a plugin.
14
+
15
+ `rails plugin install git://github.com/mort666/yubikey_database_authenticatable.git`
16
+
17
+ Is compatible with Rails 3.1.
18
+
19
+ ## Setup
20
+
21
+ Once the plugin is installed, all you need to do is setup the user model which includes a small addition to the model itself and to the schema.
22
+
23
+ The following needs to be added to the User module.
24
+
25
+ add_column :users, :useyubikey, :boolean
26
+ add_column :users, :registeredyubikey, :string
27
+
28
+ then finally add to the model:
29
+
30
+ class User < ActiveRecord::Base
31
+
32
+ devise :yubikey_database_authenticatable, :trackable, :timeoutable
33
+
34
+ # Setup accessible (or protected) attributes for your model
35
+ attr_accessible :useyubikey, :registeredyubikey, :yubiotp
36
+
37
+ attr_accessor :yubiotp
38
+
39
+ def registeredyubikey=(yubiotp)
40
+ write_attribute(:registeredyubikey, yubiotp[0..11])
41
+ end
42
+
43
+ ...
44
+ end
45
+
46
+ ## Copyright
47
+
48
+ Copyright (c) 2011 Stephen Kapp, Released under MIT License
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "yubiket_database_authenticatable"
9
+ gem.summary = %Q{YubiKey OTP Authentication Plugin for Devise}
10
+ gem.description = %Q{Extended version of the Devise Database Authentication module to implement YubiKey OTP two factor authentication for registered users}
11
+ gem.email = "mort666@virus.org"
12
+ gem.homepage = "https://github.com/mort666/yubikey_database_authenticatable"
13
+ gem.authors = ["Stephen Kapp"]
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ desc 'Default: run unit tests.'
22
+ task :default => :test
23
+
24
+ desc 'Test the yubikey_database_authenticatable plugin.'
25
+ Rake::TestTask.new(:test) do |t|
26
+ t.libs << 'lib'
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = true
30
+ end
31
+
32
+ desc 'Generate documentation for the yubikey_database_authenticatable plugin.'
33
+ Rake::RDocTask.new(:rdoc) do |rdoc|
34
+ rdoc.rdoc_dir = 'rdoc'
35
+ rdoc.title = 'YubikeyDatabaseAuthenticatable'
36
+ rdoc.options << '--line-numbers' << '--inline-source'
37
+ rdoc.rdoc_files.include('README')
38
+ rdoc.rdoc_files.include('lib/**/*.rb')
39
+ end
@@ -0,0 +1,100 @@
1
+ require 'yubikey'
2
+ require 'bcrypt'
3
+
4
+ module Devise
5
+ module Models
6
+ module YubikeyDatabaseAuthenticatable
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ attr_reader :yubiotp, :password, :current_password
11
+ attr_accessor :password_confirmation
12
+ end
13
+
14
+ def validate_yubikey(yubiotp)
15
+ begin
16
+ otp = Yubikey::OTP::Verify.new(yubiotp)
17
+
18
+ if otp.valid?
19
+ return true
20
+ else
21
+ return false
22
+ end
23
+ rescue Yubikey::OTP::InvalidOTPError
24
+ return false
25
+ end
26
+ end
27
+
28
+ # Generates password encryption based on the given value.
29
+ def password=(new_password)
30
+ @password = new_password
31
+ self.encrypted_password = password_digest(@password) if @password.present?
32
+ end
33
+
34
+ # Verifies whether an password (ie from sign in) is the user password.
35
+ def valid_password?(password)
36
+ return false if encrypted_password.blank?
37
+ bcrypt = ::BCrypt::Password.new(self.encrypted_password)
38
+ password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
39
+ Devise.secure_compare(password, self.encrypted_password)
40
+ end
41
+
42
+ # Set password and password confirmation to nil
43
+ def clean_up_passwords
44
+ self.password = self.password_confirmation = ""
45
+ end
46
+
47
+ # Update record attributes when :current_password matches, otherwise returns
48
+ # error on :current_password. It also automatically rejects :password and
49
+ # :password_confirmation if they are blank.
50
+ def update_with_password(params={})
51
+ current_password = params.delete(:current_password)
52
+
53
+ if params[:password].blank?
54
+ params.delete(:password)
55
+ params.delete(:password_confirmation) if params[:password_confirmation].blank?
56
+ end
57
+
58
+ result = if valid_password?(current_password)
59
+ update_attributes(params)
60
+ else
61
+ self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
62
+ self.attributes = params
63
+ false
64
+ end
65
+
66
+ clean_up_passwords
67
+ result
68
+ end
69
+
70
+ def after_database_authentication
71
+ end
72
+
73
+ # A reliable way to expose the salt regardless of the implementation.
74
+ def authenticatable_salt
75
+ self.encrypted_password[0,29] if self.encrypted_password
76
+ end
77
+
78
+ protected
79
+
80
+ # Downcase case-insensitive keys
81
+ def downcase_keys
82
+ (self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
83
+ end
84
+
85
+ # Digests the password using bcrypt.
86
+ def password_digest(password)
87
+ ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
88
+ end
89
+
90
+ module ClassMethods
91
+ def find_for_yubikey_database_authentication(conditions)
92
+ find_for_authentication(conditions)
93
+ end
94
+
95
+ Devise::Models.config(self, :pepper, :stretches)
96
+ end
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,4 @@
1
+ ActionController::Routing::Mapper.class_eval do
2
+ protected
3
+ alias_method :devise_yubikey_database_authenticatable, :devise_session
4
+ end
@@ -0,0 +1,32 @@
1
+ require 'devise/strategies/authenticatable'
2
+
3
+ module Devise
4
+ module Strategies
5
+ class YubikeyDatabaseAuthenticatable < Authenticatable
6
+ def authenticate!
7
+ resource = valid_password? && mapping.to.find_for_yubikey_database_authentication(authentication_hash)
8
+
9
+ if validate(resource) {resource.valid_password?(password)}
10
+ if resource.useyubikey == true
11
+ if params[:user][:yubiotp].blank?
12
+ fail('Yubikey OTP Required for this user.')
13
+ else
14
+ if resource.validate_yubikey(params[:user][:yubiotp]) && (resource.registeredyubikey == params[:user][:yubiotp][0..11])
15
+ resource.after_database_authentication
16
+ success!(resource)
17
+ else
18
+ fail('Invalid Yubikey OTP.')
19
+ end
20
+ end
21
+ else
22
+ success!(resource)
23
+ end
24
+ else
25
+ fail(:invalid)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ Warden::Strategies.add(:yubikey_database_authenticatable, Devise::Strategies::YubikeyDatabaseAuthenticatable)
@@ -0,0 +1,3 @@
1
+ module YubikeyDatabaseAuthenticatable
2
+ VERSION = "0.3.0".freeze
3
+ end
@@ -0,0 +1,11 @@
1
+ # YubikeyDatabaseAuthenticatable
2
+
3
+ require 'devise'
4
+
5
+ $: << File.expand_path("..", __FILE__)
6
+
7
+ require 'devise_yubikey_database_authenticatable/model'
8
+ require 'devise_yubikey_database_authenticatable/strategy'
9
+ require 'devise_yubikey_database_authenticatable/routes'
10
+
11
+ Devise.add_module(:yubikey_database_authenticatable, :strategy => true, :model => "devise_yubikey_database_authenticatable/model", :route => :session, :controller => :sessions)
data/rails/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ # Include hook code here
2
+
3
+ require 'devise'
4
+
5
+ $: << File.expand_path("..", __FILE__)
6
+
7
+ require 'lib/yubikey_database_authenticatable'
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_support'
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class YubikeyDatabaseAuthenticatableTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "devise_yubikey_database_authenticatable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'yubikey_database_authenticatable'
7
+ s.version = YubikeyDatabaseAuthenticatable::VERSION.dup
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = 'YubiKey OTP Authentication Plugin for Devise'
10
+ s.email = 'mort666@virus.org'
11
+ s.homepage = 'https://github.com/mort666/yubikey_database_authenticatable'
12
+ s.description = s.summary
13
+ s.authors = ['Stephen Kapp']
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency('devise', '~> 1.5.0')
21
+ s.add_dependency('yubikey', '~> 1.2.1')
22
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yubikey_database_authenticatable
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
+ platform: ruby
12
+ authors:
13
+ - Stephen Kapp
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-12-04 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: devise
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 1
32
+ - 5
33
+ - 0
34
+ version: 1.5.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: yubikey
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 29
46
+ segments:
47
+ - 1
48
+ - 2
49
+ - 1
50
+ version: 1.2.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: YubiKey OTP Authentication Plugin for Devise
54
+ email: mort666@virus.org
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files: []
60
+
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - lib/devise_yubikey_database_authenticatable/model.rb
66
+ - lib/devise_yubikey_database_authenticatable/routes.rb
67
+ - lib/devise_yubikey_database_authenticatable/strategy.rb
68
+ - lib/devise_yubikey_database_authenticatable/version.rb
69
+ - lib/yubikey_database_authenticatable.rb
70
+ - rails/init.rb
71
+ - test/test_helper.rb
72
+ - test/yubikey_database_authenticatable_test.rb
73
+ - yubikey_database_authenticatable.gemspec
74
+ has_rdoc: true
75
+ homepage: https://github.com/mort666/yubikey_database_authenticatable
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.6.2
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: YubiKey OTP Authentication Plugin for Devise
108
+ test_files:
109
+ - test/test_helper.rb
110
+ - test/yubikey_database_authenticatable_test.rb