active_model_otp 0.0.1 → 0.0.2

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/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ matrix:
5
+ include:
6
+ - rvm: jruby
7
+ env: JRUBY_OPTS="--1.9 --server -Xcext.enabled=true"
8
+ - rvm: jruby-head
9
+ env: JRUBY_OPTS="--1.9 --server -Xcext.enabled=true"
10
+ notifications:
11
+ email: false
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.org/heapsource/active_model_otp.png)](https://travis-ci.org/heapsource/active_model_otp)
2
+
1
3
  # ActiveModel::Otp
2
4
 
3
5
  **ActiveModel::Otp** makes adding **Two Factor Authentication**(TFA) to a model simple, let's see what's required to get AMo::Otp working in our Application, using Rails 4.0 (AMo::Otp is also compatible with Rails 3.x versions) we're going to use an User model and some authentication to it. Inspired in AM::SecurePassword
@@ -38,8 +40,9 @@ end
38
40
 
39
41
  ##Usage
40
42
 
41
- The has_one_time_password sentence provides to the model some useful methods in order to implement our TFA system.
42
- The otp_secret_key is saved automatically when a object is created, otp_secret_key is generated according to [RFC 4226](http://tools.ietf.org/html/rfc4226) and the [HOTP RFC](http://tools.ietf.org/html/draft-mraihi-totp-timebased-00). This is compatible with Google Authenticator apps available for Android and iPhone, and now in use on GMail.
43
+ The has_one_time_password sentence provides to the model some useful methods in order to implement our TFA system. AMo:Otp generates one time passwords according to [RFC 4226](http://tools.ietf.org/html/rfc4226) and the [HOTP RFC](http://tools.ietf.org/html/draft-mraihi-totp-timebased-00). This is compatible with Google Authenticator apps available for Android and iPhone, and now in use on GMail.
44
+
45
+ The otp_secret_key is saved automatically when a object is created,
43
46
 
44
47
  ```ruby
45
48
  user = User.create(email: "hello@heapsource.com")
@@ -112,6 +115,8 @@ user.otp_secret_key = "2z6hxkdwi3uvrnpn"
112
115
  puts "Current code #{user.otp_code}"
113
116
  ```
114
117
 
118
+ **Note:** otp_secret_key must be generated using RFC 3548 base32 key strings (for compatilibity with google authenticator)
119
+
115
120
  ### Useful Examples
116
121
 
117
122
  #### Generating QR Code with Google Charts API
@@ -6,7 +6,7 @@ require 'active_model/otp/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "active_model_otp"
8
8
  spec.version = ActiveModel::Otp::VERSION
9
- spec.authors = ["Guillermo Iguaran", "Roberto Miranda", "Firebase.co"]
9
+ spec.authors = ["Guillermo Iguaran", "Roberto Miranda", "Heapsource"]
10
10
  spec.email = ["guilleiguaran@gmail.com", "rjmaltamar@gmail.com", "hello@firebase.co"]
11
11
  spec.description = %q{Adds methods to set and authenticate against one time passwords. Inspired in AM::SecurePassword"}
12
12
  spec.summary = "Adds methods to set and authenticate against one time passwords."
@@ -5,13 +5,16 @@ module ActiveModel
5
5
  module ClassMethods
6
6
  def has_one_time_password(options = {})
7
7
 
8
+ cattr_accessor :otp_column_name
9
+ self.otp_column_name = (options[:column_name] || "otp_secret_key").to_s
10
+
8
11
  include InstanceMethodsOnActivation
9
12
 
10
- before_create { self.otp_secret_key = ROTP::Base32.random_base32 }
13
+ before_create { self.otp_column = ROTP::Base32.random_base32 }
11
14
 
12
15
  if respond_to?(:attributes_protected_by_default)
13
16
  def self.attributes_protected_by_default #:nodoc:
14
- super + ["otp_secret_key"]
17
+ super + [self.otp_column_name]
15
18
  end
16
19
  end
17
20
  end
@@ -19,7 +22,7 @@ module ActiveModel
19
22
 
20
23
  module InstanceMethodsOnActivation
21
24
  def authenticate_otp(code, options = {})
22
- totp = ROTP::TOTP.new(self.otp_secret_key)
25
+ totp = ROTP::TOTP.new(self.otp_column)
23
26
  if drift = options[:drift]
24
27
  totp.verify_with_drift(code, drift)
25
28
  else
@@ -28,12 +31,20 @@ module ActiveModel
28
31
  end
29
32
 
30
33
  def otp_code(time = Time.now)
31
- ROTP::TOTP.new(self.otp_secret_key).at(time)
34
+ ROTP::TOTP.new(self.otp_column).at(time)
32
35
  end
33
36
 
34
37
  def provisioning_uri(account = nil)
35
38
  account ||= self.email if self.respond_to?(:email)
36
- ROTP::TOTP.new(self.otp_secret_key).provisioning_uri(account)
39
+ ROTP::TOTP.new(self.otp_column).provisioning_uri(account)
40
+ end
41
+
42
+ def otp_column
43
+ self.send(self.class.otp_column_name)
44
+ end
45
+
46
+ def otp_column=(attr)
47
+ self.send("#{self.class.otp_column_name}=", attr)
37
48
  end
38
49
 
39
50
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveModel
2
2
  module Otp
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -1,5 +1,6 @@
1
1
  require "active_model"
2
2
  require "active_support/core_ext/class/attribute_accessors"
3
+ require "cgi"
3
4
  require "rotp"
4
5
  require "active_model/one_time_password"
5
6
 
@@ -0,0 +1,12 @@
1
+ class Visitor
2
+ extend ActiveModel::Callbacks
3
+ include ActiveModel::Validations
4
+ include ActiveModel::OneTimePassword
5
+
6
+ define_model_callbacks :create
7
+ attr_accessor :otp_token, :email
8
+
9
+ has_one_time_password :column_name => :otp_token
10
+
11
+ end
12
+
@@ -5,29 +5,39 @@ class OtpTest < MiniTest::Unit::TestCase
5
5
  @user = User.new
6
6
  @user.email = 'roberto@heapsource.com'
7
7
  @user.run_callbacks :create
8
+ @visitor = Visitor.new
9
+ @visitor.email = 'roberto@heapsource.com'
10
+ @visitor.run_callbacks :create
8
11
  end
9
12
 
10
13
  def test_authenticate_with_otp
11
14
  code = @user.otp_code
12
-
13
15
  assert @user.authenticate_otp(code)
16
+
17
+ code = @visitor.otp_code
18
+ assert @visitor.authenticate_otp(code)
14
19
  end
15
20
 
16
21
  def test_authenticate_with_otp_when_drift_is_allowed
17
22
  code = @user.otp_code(Time.now - 30)
18
-
19
23
  assert @user.authenticate_otp(code, drift: 60)
24
+
25
+ code = @visitor.otp_code(Time.now - 30)
26
+ assert @visitor.authenticate_otp(code, drift: 60)
20
27
  end
21
28
 
22
29
  def test_otp_code
23
- assert_match(/\d{6}/, @user.otp_code.to_s)
30
+ assert_match(/\d{5,6}/, @user.otp_code.to_s)
31
+ assert_match(/\d{5,6}/, @visitor.otp_code.to_s)
24
32
  end
25
33
 
26
34
  def test_provisioning_uri_with_provided_account
27
35
  assert_match %r{otpauth://totp/roberto\?secret=\w{16}}, @user.provisioning_uri("roberto")
36
+ assert_match %r{otpauth://totp/roberto\?secret=\w{16}}, @visitor.provisioning_uri("roberto")
28
37
  end
29
38
 
30
39
  def test_provisioning_uri_with_email_field
31
40
  assert_match %r{otpauth://totp/roberto@heapsource\.com\?secret=\w{16}}, @user.provisioning_uri
41
+ assert_match %r{otpauth://totp/roberto@heapsource\.com\?secret=\w{16}}, @visitor.provisioning_uri
32
42
  end
33
43
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_model_otp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Guillermo Iguaran
9
9
  - Roberto Miranda
10
- - Firebase.co
10
+ - Heapsource
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-07-11 00:00:00.000000000 Z
14
+ date: 2013-12-04 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activemodel
@@ -104,6 +104,7 @@ extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
106
  - .gitignore
107
+ - .travis.yml
107
108
  - Gemfile
108
109
  - LICENSE.txt
109
110
  - README.md
@@ -113,6 +114,7 @@ files:
113
114
  - lib/active_model/otp/version.rb
114
115
  - lib/active_model_otp.rb
115
116
  - test/models/user.rb
117
+ - test/models/visitor.rb
116
118
  - test/one_time_password_test.rb
117
119
  - test/test_helper.rb
118
120
  homepage: ''
@@ -142,5 +144,6 @@ specification_version: 3
142
144
  summary: Adds methods to set and authenticate against one time passwords.
143
145
  test_files:
144
146
  - test/models/user.rb
147
+ - test/models/visitor.rb
145
148
  - test/one_time_password_test.rb
146
149
  - test/test_helper.rb