yubikey_database_authenticatable 0.3.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.
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