heapsource / active_model_otp Goto Github PK
View Code? Open in Web Editor NEWAdds methods to set and authenticate against one time passwords (Two-Factor Authentication). Inspired in AM::SecurePassword
License: MIT License
Adds methods to set and authenticate against one time passwords (Two-Factor Authentication). Inspired in AM::SecurePassword
License: MIT License
I'm having an issue with last_otp_at not being set
in the user model and migration:
## user model
has_one_time_password backup_codes_count: 6, one_time_backup_codes: true, after_column_name: :last_otp_at
## migration
class AddLastOtpAtToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :last_otp_at, :integer, description: 'Preventing reuse of Time based OTPs'
end
end
[11] pry(main)> u.authenticate_otp u.otp_code
true
[12] pry(main)> u.authenticate_otp u.otp_code
true
[13] pry(main)> u.last_otp_at
nil
any ideas why this would happen?
ROTP changed their implementation of verify
to return timestamp (eg 1561654770) when the otp is valid and nil otherwise instead of a true
or false
. README still says that authenticate_otp
returns true
or false
.
Is there any Plans to release a new version?
Hi, I'm facing a problem trying to generate a Visual QR code I'm getting this error message.
I'm using this Githubto generate the Visual QR Code.
undefined method
dark?' for #<RQRCode::QRCode:0x00005649dee622a0 @qrcode=QRCodeCore: @DaTa='#RQRCodeCore::QRSegment:0x00005649dee61f58', @error_correct_level=2, @Version=4, @module_count=33>`
I noticed this is the part generating the error.
data[y + 1][x + 1] = true if qr.dark?(x, y)
From here.
def self.create(string, bgimg, options = {})
options[:size] ||= 4
options[:level] ||= :h
options[:modified] ||= (options[:level] == :h ? 0.03 : 0)
options[:bgcolor] ||= ChunkyPNG::Color(255, 255, 255)
options[:dotpadding] ||= 0.25
size = size(options[:size])
qr = RQRCode::QRCode.new( string, :size => options[:size], :level => options[:level] )
bw = (1.0 * bgimg.width / size).ceil
bh = (1.0 * bgimg.height / size).ceil
qrcode = ChunkyPNG::Image.new(bw * size, bh * size, ChunkyPNG::Color::TRANSPARENT)
bb = bgimg.resample_bilinear(qrcode.width, qrcode.height)
data = size.times.map { size.times.map { false } }
qr.modules.each_index do |x|
qr.modules.each_index do |y|
data[y + 1][x + 1] = true if qr.dark?(x, y)
end
end
Followed the Counter based OTP guide.
$ rails g migration AddOtpSecretKeyToUsers otp_secret_key:string
$ rails g migration AddCounterForOtpToUsers otp_counter:integer
$ rails g migration AddCounterForOtpToUsers my_otp_counter:integer
# Set the default value to `1` manually
$ rake db:migrate
class User < ActiveRecord::Base
has_one_time_password :counter_based => true
end
u = User.new
# => #<User id: nil, email: nil, otp_counter: 1, otp_secret_key: nil, created_at: nil, updated_at: nil, my_otp_counter: 1>
u.otp_counter
SystemStackError: stack level too deep
from /usr/local/rbenv/versions/2.0.0-p481/lib/ruby/2.0.0/irb/workspace.rb:86
Maybe IRB bug!
class User < ActiveRecord::Base
has_one_time_password :counter_based => true, :counter_column_name => :my_otp_counter
end
u = User.new
# => #<User id: nil, email: nil, otp_counter: 1, otp_secret_key: nil, created_at: nil, updated_at: nil, my_otp_counter: 1>
u.otp_counter
# => 1
Not sure why the same problem isn't exhibited by the specs, but the following seems to fix the problem:
module ActiveModel
module OneTimePassword
module InstanceMethodsOnActivation
def otp_counter
if self.class.otp_counter_column_name != 'otp_counter'
self.public_send(self.class.otp_counter_column_name)
else
super
end
end
def otp_counter=(attr)
if self.class.otp_counter_column_name != 'otp_counter'
self.public_send("#{self.class.otp_counter_column_name}=", attr)
else
super
end
end
end
end
end
Hello
After the last update ... OTP codes generated by the Google Authenticator app don't work.
The OTP codes generated by "user.otp_code" work well
( Everything was working fine before the gem update)
Hi @robertomiranda,
Thank you for the nice gem. It is really helpful for the OTP generation.
I am using it in my project however we have requirement of 4 digit otp code instead of 6 digit.
Would like to know is there a way to customise it to make it 4 digit or any number of digit?
Another question about Padding a otp code. I have seen that one of the issue has been closed and there has been a pull request. However I am using active_model_otp (1.0.0) version in my project. But still I am getting 5 digit digit some times randomly. And also I did not set any "padding: false"
Is that change related to padding has been published ?
Thanks
Shivani
irb(main):003:0> user.respond_to?(:new_record)
=> false
irb(main):004:0> user.respond_to?(:new_record?)
=> true
Since instances of ActiveRecord::Persistence
have a method #new_record?
not #new_record
Hey everyone! ๐
Recently, the support for Ruby 3 was added in gem ๐
@robertomiranda and other maintainers, can you please (when you have time) to release a official release with this changes? ๐
Thanks a lot! ๐ป
Hi, I'm using this gem to generate OTP for User. As specified in the documentation I've provided the length attribute as 4. But still the OTP being generated is more than 4 characters.
Below is my code snippet :
`class User < ActiveRecord::Base
has_one :user_detail
has_many :products
has_one_time_password length: 4
before_create :generate_authentication_token!
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
accepts_nested_attributes_for :user_detail
def generate_authentication_token!
begin
self.auth_token = Devise.friendly_token
puts self.auth_token
end while self.class.exists?(auth_token: auth_token)
end
end`
Can someone tell if possibly I'm going wrong somewhere?
ruby 2.5.3
rails 5.2.2
I tried multiple gem version and rotp version the result is this
Gemfile
gem 'active_model_otp'
gem 'rotp'
produce error as in #48
when calling otp_code
ArgumentError: wrong number of arguments (given 2, expected 1)
Gemfile
gem 'active_model_otp', :git => 'https://github.com/heapsource/active_model_otp.git'
gem 'rotp', '~> 3.3.1'
otp_code
working
authenticate_otp
working but
when calling authenticate_otp
with :drift option it produce error
`NoMethodError (undefined method `to_i' for {:drift_behind=>60}:Hash)`
Gemfile
gem 'active_model_otp', :git => 'https://github.com/heapsource/active_model_otp.git'
gem 'rotp'
otp_code
working
but authenticate_otp
only returning nil
Please bump rotp
dependency from 4.0.2
to 5.0.0
I've followed #46 Two Factor Authentication episode of DriftingRuby and I can get the TFA works well in my development environment. Unluckily, there is a strange behavior when I deploy my feature to Staging environment.
Here is my QRCode generator:
qr = RQRCode::QRCode.new(resource.provisioning_uri, level: :h)
The rest of the implementation are the same as described in the epicode.
A strange thing is that the QR code looks differently between development and staging environment. The problem is that I can scan the QR code in staging environment, but when I use that code to verify, it is always not matched.
Can somebody figure whether this is a bug of Active Model OTP or RQRCode gem?
I'm using:
gem 'rails', '4.2.2'
gem 'devise', '~> 3.5', '>= 3.5.2'
gem 'active_model_otp', '~> 1.2'
gem 'rqrcode', '~> 0.10.1'
It looks like I can upgrade this gem to 2.0.1 already, but there is no changelog entry describing the breaking changes. Can someone please update this?
I have encrypted my otp_secret_key in database using Gibberish. When I am trying to call authenticate_otp it is giving me this error ROTP::Base32::Base32Error Exception: Invalid Base32 Character - '{' .
Kindly please look into it.
user.otp_code
raises error
ArgumentError: wrong number of arguments (given 2, expected 1)
gemfile lock
GEM
remote: https://rubygems.org/
specs:
actioncable (5.2.1.1)
actionpack (= 5.2.1.1)
nio4r (> 2.0)> 2.5, >= 2.5.4)
websocket-driver (>= 0.6.1)
actionmailer (5.2.1.1)
actionpack (= 5.2.1.1)
actionview (= 5.2.1.1)
activejob (= 5.2.1.1)
mail (
rails-dom-testing (> 2.0)> 2.0)
actionpack (5.2.1.1)
actionview (= 5.2.1.1)
activesupport (= 5.2.1.1)
rack (
rack-test (>= 0.6.3)
rails-dom-testing (> 2.0)> 1.0, >= 1.0.2)
rails-html-sanitizer (
actionview (5.2.1.1)
activesupport (= 5.2.1.1)
builder (> 3.1)> 1.4)
erubi (
rails-dom-testing (> 2.0)> 1.0, >= 1.0.3)
rails-html-sanitizer (
active_hash (2.2.0)
activesupport (>= 5.0.0)
active_model_otp (1.2.0)
activemodel
rotp
activejob (5.2.1.1)
activesupport (= 5.2.1.1)
globalid (>= 0.3.6)
activemodel (5.2.1.1)
activesupport (= 5.2.1.1)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (> 3.1)> 0.3.1)
activerecord (5.2.1.1)
activemodel (= 5.2.1.1)
activesupport (= 5.2.1.1)
arel (>= 9.0)
activestorage (5.2.1.1)
actionpack (= 5.2.1.1)
activerecord (= 5.2.1.1)
marcel (
activesupport (5.2.1.1)
concurrent-ruby (> 1.0, >= 1.0.2)> 5.1)
i18n (>= 0.7, < 2)
minitest (
tzinfo (> 1.1)> 0.2.3)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
adequate_crypto_address (0.1.3)
base58 (
digest-sha3 (> 1.1.0)> 1.0)
arel (9.0.0)
ast (2.4.0)
awesome_print (1.8.0)
aws-eventstream (1.0.1)
aws-partitions (1.118.0)
aws-sdk-core (3.41.0)
aws-eventstream (
aws-partitions (> 1.0)> 1.0)
aws-sigv4 (
jmespath (> 1.0)> 3, >= 3.39.0)
aws-sdk-kms (1.13.0)
aws-sdk-core (
aws-sigv4 (> 1.0)> 3, >= 3.39.0)
aws-sdk-s3 (1.27.0)
aws-sdk-core (
aws-sdk-kms (> 1)> 1.0)
aws-sigv4 (
aws-sdk-sns (1.9.0)
aws-sdk-core (> 3, >= 3.39.0)> 1.0)
aws-sigv4 (
aws-sdk-sqs (1.10.0)
aws-sdk-core (> 3, >= 3.39.0)> 1.0)
aws-sigv4 (
aws-sigv4 (1.0.3)
base58 (0.2.3)
bcrypt (3.1.12)
bindex (0.5.0)
bootsnap (1.3.2)
msgpack (> 1.0)> 1.2)
brakeman (4.3.1)
browser (2.5.3)
builder (3.2.3)
bundler-audit (0.6.0)
bundler (
thor (> 0.18)> 1.2.1)
byebug (10.0.2)
capybara (2.18.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
chartkick (3.0.1)
chunky_png (1.3.11)
cocoon (1.2.12)
coderay (1.1.2)
concurrent-ruby (1.1.3)
config (1.7.0)
activesupport (>= 3.0)
deep_merge (
dry-validation (>= 0.10.4)
countries (2.1.4)
i18n_data (> 0.8.0)> 6.9)
money (
sixarm_ruby_unaccent (> 1.1)> 1.4)
unicode_utils (
country_select (3.1.1)
countries (> 2.0)> 1.0)
sort_alphabetical (
crack (0.4.3)
safe_yaml (> 1.0.0)> 2.5)
crass (1.0.4)
daemons (1.2.6)
data_migrate (5.2.0)
rails (>= 4.2)
deep_merge (1.2.1)
diff-lcs (1.3)
digest-sha3 (1.1.0)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.5.0)
dotenv-rails (2.5.0)
dotenv (= 2.5.0)
railties (>= 3.2, < 6.0)
down (4.7.0)
addressable (
draper (3.0.1)
actionpack (> 5.0)> 5.0)
activemodel (
activemodel-serializers-xml (> 1.0)> 5.0)
activesupport (
request_store (> 1.0)> 1.0)
dry-configurable (0.7.0)
concurrent-ruby (
dry-container (0.6.0)
concurrent-ruby (> 1.0)> 0.1, >= 0.1.3)
dry-configurable (
dry-core (0.4.7)
concurrent-ruby (> 1.0)> 0.2, >= 0.2.6)
dry-equalizer (0.2.1)
dry-inflector (0.1.2)
dry-logic (0.4.2)
dry-container (
dry-core (> 0.2)> 0.2)
dry-equalizer (
dry-monads (1.1.0)
concurrent-ruby (> 1.0)> 0.4, >= 0.4.4)
dry-core (
dry-equalizer
dry-types (0.13.3)
concurrent-ruby (> 1.0)> 0.3)
dry-container (
dry-core (> 0.4, >= 0.4.4)> 0.2)
dry-equalizer (
dry-inflector (> 0.1, >= 0.1.2)> 0.4, >= 0.4.2)
dry-logic (
dry-validation (0.12.2)
concurrent-ruby (> 1.0)> 0.1, >= 0.1.3)
dry-configurable (
dry-core (> 0.2, >= 0.2.1)> 0.2)
dry-equalizer (
dry-logic (> 0.4, >= 0.4.0)> 0.13.1)
dry-types (
enumerize (2.2.2)
activesupport (>= 3.2)
erubi (1.7.1)
eventmachine (1.2.7)
execjs (2.7.0)
faker (1.9.1)
i18n (>= 0.7)
ffi (1.9.25)
file_validators (2.3.0)
activemodel (>= 3.2)
mime-types (>= 1.0)
flamegraph (0.9.5)
font-awesome-rails (4.7.0.4)
railties (>= 3.2, < 6.0)
globalid (0.4.1)
activesupport (>= 4.2.0)
gon (6.2.1)
actionpack (>= 3.0)
multi_json
request_store (>= 1.0)
groupdate (4.1.0)
activesupport (>= 4.2)
haml (5.0.4)
temple (>= 0.8.0)
tilt
hashdiff (0.3.7)
high_voltage (3.1.0)
highline (2.0.0)
http (4.0.0)
addressable (> 2.3)> 1.0)
http-cookie (
http-form_data (> 2.0)> 0.6.0)
http_parser.rb (
http-cookie (1.0.3)
domain_name (> 0.5)> 3.0)
http-form_data (2.1.1)
http_parser.rb (0.6.0)
httparty (0.16.3)
mime-types (
multi_xml (>= 0.5.2)
i18n (1.1.1)
concurrent-ruby (> 1.0)> 0.9, >= 0.9.4)
i18n-js (3.2.0)
i18n (>= 0.8.0, < 2)
i18n-tasks (0.9.28)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
erubi
highline (>= 2.0.0)
i18n
parser (>= 2.2.3.0)
rails-i18n
rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1)
i18n_data (0.8.0)
jaro_winkler (1.5.1)
jbuilder (2.8.0)
activesupport (>= 4.2.0)
multi_json (>= 1.2)
jmespath (1.4.0)
jquery-rails (4.3.3)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.1.0)
jwt (2.1.0)
kaminari (1.1.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.1.1)
kaminari-activerecord (= 1.1.1)
kaminari-core (= 1.1.1)
kaminari-actionview (1.1.1)
actionview
kaminari-core (= 1.1.1)
kaminari-activerecord (1.1.1)
activerecord
kaminari-core (= 1.1.1)
kaminari-core (1.1.1)
listen (3.1.5)
rb-fsevent (
rb-inotify (> 0.9, >= 0.9.7)> 1.2)
ruby_dep (
lograge (0.10.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (> 1.0)> 1.0.2)
loofah (2.2.3)
crass (
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
mailcatcher (0.2.4)
eventmachine
haml
i18n
json
mail
sinatra
skinny (>= 0.1.2)
sqlite3-ruby
thin
mailgun-ruby (1.1.11)
rest-client (> 2.0.2)> 0.3.2)
marcel (0.3.3)
mimemagic (
memory_profiler (0.9.12)
method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (> 3.2015)> 2.3.0)
mime-types-data (3.2018.0812)
mimemagic (0.3.2)
mini_mime (1.0.1)
mini_portile2 (2.3.0)
minitest (5.11.3)
minitest-power_assert (0.3.0)
minitest
power_assert (>= 1.1)
minitest-profile (0.0.2)
money (6.13.1)
i18n (>= 0.6.4, <= 2)
msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
mustermann (1.0.3)
netrc (0.11.0)
nigilist (0.1.0)
nio4r (2.3.1)
nokogiri (1.8.5)
mini_portile2 (
oj (3.7.1)
parallel (1.12.1)
parser (2.5.3.0)
ast (> 2.4.0)> 1.1.0)
pg (1.1.3)
phony (2.16.8)
phony_rails (0.14.11)
activesupport (>= 3.0)
phony (> 2.15)
power_assert (1.1.3)
powerpack (0.1.2)
pry (0.12.2)
coderay (
method_source (> 0.9.0)> 10.0)
pry-byebug (3.6.0)
byebug (
pry (> 0.10)> 2.2, >= 2.2.2)
pry-rails (0.3.7)
pry (>= 0.10.4)
public_suffix (3.0.3)
puma (3.12.0)
rack (2.0.6)
rack-mini-profiler (1.0.0)
rack (>= 1.2.0)
rack-protection (2.0.4)
rack
rack-proxy (0.6.5)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.1.1)
actioncable (= 5.2.1.1)
actionmailer (= 5.2.1.1)
actionpack (= 5.2.1.1)
actionview (= 5.2.1.1)
activejob (= 5.2.1.1)
activemodel (= 5.2.1.1)
activerecord (= 5.2.1.1)
activestorage (= 5.2.1.1)
activesupport (= 5.2.1.1)
bundler (>= 1.3.0)
railties (= 5.2.1.1)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
loofah (
rails-i18n (5.1.2)
i18n (>= 0.7, < 2)
railties (>= 5.0, < 6)
railties (5.2.1.1)
actionpack (= 5.2.1.1)
activesupport (= 5.2.1.1)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
rainbow (3.0.0)
rake (12.3.1)
ransack (2.1.0)
actionpack (>= 5.0)
activerecord (>= 5.0)
activesupport (>= 5.0)
i18n
rb-fsevent (0.10.3)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
recaptcha (4.13.0)
json
request_store (1.4.1)
rack (>= 1.4)
rest-client (2.0.2)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (> 0.8)> 2.5)
rollbar (2.18.0)
multi_json
rotp (4.0.2)
addressable (
rqrcode (0.10.1)
chunky_png (> 1.0)> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (
rspec-support (3.8.0)
rubocop (0.60.0)
jaro_winkler (> 1.5.1)> 1.10)
parallel (
parser (>= 2.5, != 2.5.1.1)
powerpack (> 0.1)> 1.7)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (
unicode-display_width (> 1.4.0)> 1.9.6)
ruby-progressbar (1.10.0)
ruby_dep (1.5.0)
safe_yaml (1.0.4)
sassc (2.0.0)
ffi (
rake
sassc-rails (2.0.0)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
shoryuken (4.0.2)
aws-sdk-core (>= 2)
concurrent-ruby
thor
shrine (2.13.0)
down (> 4.1)> 2.2)
shrine-memory (0.3.0)
shrine (
simple_form (4.1.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
sinatra (2.0.4)
mustermann (> 1.0)> 2.0)
rack (
rack-protection (= 2.0.4)
tilt (> 2.0)> 1.0)
sixarm_ruby_unaccent (1.2.0)
skinny (0.2.2)
eventmachine (
thin
slack-notifier (2.3.2)
slim (4.0.1)
temple (>= 0.7.6, < 0.9)
tilt (>= 2.0.6, < 2.1)
slim-rails (3.2.0)
actionpack (>= 3.1)
railties (>= 3.1)
slim (>= 3.0, < 5.0)
sort_alphabetical (1.1.0)
unicode_utils (>= 1.2.2)
spring (2.0.2)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
sprockets (3.7.2)
concurrent-ruby (> 1.0)> 1.1, >= 1.1.1)
rack (> 1, < 3)
sprockets-rails (3.2.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
sqlite3-ruby (1.3.3)
sqlite3 (>= 1.3.3)
stackprof (0.2.12)
state_machines (0.5.0)
state_machines-activemodel (0.5.1)
activemodel (>= 4.1, < 6.0)
state_machines (>= 0.5.0)
state_machines-activerecord (0.5.2)
activerecord (>= 4.1, < 6.0)
state_machines-activemodel (>= 0.5.0)
temple (0.8.0)
terminal-table (1.8.0)
unicode-display_width (
thin (1.7.2)
daemons (> 1.0, >= 1.0.9)> 1.0, >= 1.0.4)
eventmachine (
rack (>= 1, < 3)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.8)
timecop (0.9.1)
tzinfo (1.2.5)
thread_safe (> 0.1)> 1.8)
uglifier (4.1.20)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.0)
unicode_utils (1.4.0)
web-console (3.7.0)
actionview (>= 5.0)
activemodel (>= 5.0)
bindex (>= 0.4.0)
railties (>= 5.0)
webdack-uuid_migration (1.2.0)
activerecord (>= 4.0)
webmock (3.4.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
webpacker (3.5.5)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
websocket-driver (0.7.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.4)
xpath (3.2.0)
nokogiri (
zonebie (0.6.1)
PLATFORMS
ruby
DEPENDENCIES
active_hash
active_model_otp
adequate_crypto_address
awesome_print
aws-sdk-s3
aws-sdk-sns
aws-sdk-sqs
bcrypt (> 3.1.7)> 2.13)
bootsnap (>= 1.1.0)
brakeman
browser
bundler-audit
byebug
capybara (
chartkick
cocoon
config
country_select
data_migrate
dotenv-rails
draper
dry-container
dry-monads
enumerize
faker
file_validators
flamegraph
font-awesome-rails
gon
groupdate
high_voltage
http
httparty
i18n-js
i18n-tasks (> 0.9.28)> 2.5)
jbuilder (
jquery-rails
jwt
kaminari
listen (>= 3.0.5, < 3.2)
lograge
mailcatcher
mailgun-ruby (> 1.1.6)> 3.7)
memory_profiler
minitest-power_assert
minitest-profile
money
nigilist
oj
pg
phony_rails
pry-byebug
pry-rails
puma (
rack-mini-profiler
rails (> 5.2.1)> 2.0)
ransack
recaptcha
rollbar
rqrcode
rspec-mocks
rubocop
sassc-rails
shoryuken
shrine (
shrine-memory
simple_form (~> 4.0)
slack-notifier
slim-rails
spring
spring-watcher-listen
stackprof
state_machines
state_machines-activerecord
timecop
tzinfo-data
uglifier (>= 1.3.0)
web-console (>= 3.3.0)
webdack-uuid_migration
webmock
webpacker
wicked_pdf
wkhtmltopdf-binary
zonebie
RUBY VERSION
ruby 2.5.3p105
BUNDLED WITH
1.16.6
I have pretty simple user model with otp_counter:integer
as provided in help:
class User < ActiveRecord::Base
has_one_time_password counter_based: true
end
If I try to create user I catch an error:
[1] pry(main)> user = User.create
(0.2ms) BEGIN
(0.2ms) ROLLBACK
SystemStackError: stack level too deep
from /home/user/.rvm/gems/ruby-2.3.0/gems/active_model_otp-1.2.0/lib/active_model/one_time_password.rb:100:in `otp_counter'
[2] pry(main)>
The problem is obviously in that lines:
def otp_counter
self.send(self.class.otp_counter_column_name)
end
Which basically call otp_counter method recursively again and again. Probably solution is to rename otp_counter
method to something like __otp_counter
.
Workaround is to rename otp_counter column to something else (both in migration and in model):
class User < ActiveRecord::Base
has_one_time_password counter_based: true, counter_column_name: :hotp_counter
end
Appraisals: Test against different spec (especially activemodel
versions)
Travis CI: Test whenever you changed something
This section describes how we can limit multiple use of the same OTP code, but does not clarify whether a new OTP code will be regenerated if a user decides to log in again within the interval set. Saw this comment
and assuming it does not regenerate the code during the interval.
Can you confirm my understanding? If so, could you update the README to reflect this? Or we can try to create a Pull Request to better document this scenario as soon as you can confirm the gem works this way.
2.3.0 :004 > user.authenticate_otp('xxxxxx')
NoMethodError: undefined method `scan' for nil:NilClass
from (irb):4
When i'm trying to get my QR-Code for the users to work I'm always getting this error message:
undefined method `dark?' for #RQRCode::QRCode:0x0000000009b81c18
I'm not sure why this happens, I did everything like mentioned and in my controller I require the gem like: require 'rqrcode'
Then I'm trying to generate the QR-Code for 2-Factor-Authentication:
@qr = RQRCode::QRCode.new(@user.provisioning_uri, :size => 8, :level => :h )
And in my view:
<table class="qr">
<% @qr.modules.each_index do |x| %>
<tr>
<% @qr.modules.each_index do |y| %>
<% if @qr.dark?(x,y) %>
<td class="black">
<% else %>
<td class="white">
<% end %>
<% end %>
</tr>
<% end %>
</table>
Any suggestions?
How can I implement in a way that connects to a TOTP Server for authorizing tokens?
Have an option if wish generate the opt_secret_key at the moment of create an user or can is in blank.
Hi,
In my current configuration :- has_one_time_password column_name: :otp_secret_key, length: 4
OTP is reusable. Any one can use a used otp code again.
Is there any way to make the otp code one time usable ?
Thanks,
Ranjan
Is it possible to prevent reuse of time bases OTP's by using this library?
I want to apply expiry time with otp counter.
I wrote as resource.authenticate_otp(params[:customer][:otp], drift: 900, auto_increment: true) but apparently otp is not getting expired after 15 minutes.
Is it possible for me to do it? or is there other way to do it?
require "active_model_otp"
class User
extend ActiveModel::Callbacks
include ActiveModel::Validations
include ActiveModel::OneTimePassword
define_model_callbacks :create
attr_accessor :otp_secret_key, :email
has_one_time_password
end
user = User.new
user.email = '[email protected]'
user.otp_secret_key = "anotherfakeOTPSecretKey!!"
puts "Current code #{user.otp_code}"
I am having this issue everytime the OTP secret key is containing non ASCII characters or numbers
.../rotp-1.4.1/lib/rotp/base32.rb:37:in `+': nil can't be coerced into Fixnum (TypeError)
I authenticate the token filled in by the user like this, where params[:otp_token]
is the user filled token from the view:
result = current_user.authenticate_otp(params[:otp_token], drift: 300)
I noticed when params[:otp_token]
is an empty string, that the result is true
, which should be false
?
In my opinion any empty or nil value should always result in a false
result?
I noticed a security vulnerability: the backup codes are stored as plain text in a database field. Specifically, authenticate_backup_code
function checks if the list of stored backup codes includes the code
entered by the user with backup_codes.include?(code)
command:
def authenticate_backup_code(code)
backup_codes_column_name = self.class.otp_backup_codes_column_name
backup_codes = public_send(backup_codes_column_name)
return false unless backup_codes.present? && backup_codes.include?(code)
The problem is, if the database leaks out, one can use the codes on the 2FA screen and bypass two factor authentication. A partial solution would be to encrypt the field that stores the backup codes with active record encryption or other methods. But it still makes the system vulnerable if both the database and the encryption key leaks out.
A conventional secure solution would be to generate a list of random backup codes but store only their hashes in the database. One of popular password hashing methods is bcrypt. Here is how to generate a code and its hash:
require 'bcrypt'
backup_code = SecureRandom.alphanumeric(BACKUP_CODE_LENGTH)
backup_code_hash = BCrypt::Password.create(backup_code)
And here is how to check if the code entered by the user corresponds to the generated hash:
BCrypt::Password.new(backup_code_hash) == backup_code_from_the_user
I was trying to update my rails app to ruby 3.0.0 and noticed that when I tried to sign up new users using devise I get the following error:
NoMethodError (undefined method `before_create' for {}:Hash):
The issue goes away when I comment has_one_time_password
out in the User
model so it seems quite likely that it is related to this gem.
Is this issue known / expected? Otherwise I can gladly post the exact steps to reproduce.
it would be nice the functionality for have a backup of OTP similar to https://github.com/tinfoil/devise-two-factor#backup-codes
Hi there,
I'm trying to implement two-factor-authentication with a ruby 1.9.3 app. In rubygems.org it says your gem depends on ruby >=0 but still I cannot use it due to dependencies:
Bundler could not find compatible versions for gem "ruby":
In Gemfile:
ruby (~> 1.9.3.0)
active_model_otp (>= 2.0.1, ~> 2.0) was resolved to 2.0.1, which depends on
rotp (~> 5.0.0) was resolved to 5.0.0, which depends on
addressable (~> 2.5) was resolved to 2.7.0, which depends on
ruby (>= 2.0)
Any idea if there is a workaround for that?
Thank you!
Hi team!
Thanks for your efforts maintaining this library. Appreciate it!
Just wondering when you're planning to release a new version of the gem incorporating the latest commit from last week (preventing reuse of OTP codes with ROTP). We'd love to use this feature in our app, so eager to hear when that might be released!
Cheers!
After updating otp_secret_key to ROTP::Base32.random_base32.
OTP doesn't match with Google Authenticator OTP
Hey folks,
this is exactly what I am. lookign for. I wonder what I need to do to get it working with a very simple Sinatra application. ActiveRecord is integrated
Thanks for a short info
Andy
There should be a note for the otp_counter migration to set default:0 and null:false.
Since if otp_counter is equal to nil and you try to fetch the otp_code
in the following code:
def otp_code(options = {})
if otp_counter_based
if options[:auto_increment]
self.otp_counter += 1
save if !new_record?
end
...
An error will occur because you cannot add 1 to nil. self.otp_counter += 1
There's couple of things to consider before using this library in production. Since their implementation take some time, I suggest to update documentation.
Probably the most serious is missing rate limitations. If the account's password is compromised then its security depends on the strength of the authentication code. Authentication code is small however, susceptible to brute force attacks. Should the password be compromised, then multiple failed attempts to authenticate should lest to account lockout. This is recommended by RFC 4226.
A good practice is to store security keys in DB encrypted. Using one-way hash like scrypt is not an option for TOTP, since we need it actual value, but simple encryption with a key not stored in DB would suffice. This is recommended by RFC 6238.
Lastly a minor enhancement - verified code should not be accepted twice. This prevents over the shoulder attacks. I don't see it absolutely critical, but RFC 6238 declares it as MUST.
I have applied this gem to my "User' Model like this:
class User < ApplicationRecord
has_one_time_password interval: 600, after_column_name: :last_otp_at
end
Here I have set interval of 10 minutes for otp. I want to make it invalid once authenticated. But even after authenticating once, It can be authnticated again.
User.last.otp_code => "985983"
User.last.authenticate_otp("985983") => true
User.last.authenticate_otp("985983") => true
Also there is no update in last_otp_at
column.
User.last.last_otp_at => nil
Am I missing something? What else I need to do?
To reproduce:
bundle update
call [model name].otp_code
response:
ArgumentError: wrong number of arguments (given 2, expected 1)
from .rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rotp-4.0.2/lib/rotp/totp.rb:17:in `at'
Trying to "authenticate_otp" ==> undefined method `verify_with_drift' for #ROTP::TOTP:0x00007fb24cee7c48
Is there any possibility to generate otp_secret_key only for some specific users not for all users?
Hi, currently the validity of the OTP is set to 30 seconds. Is there a possibilty to increase the OTP time to say 2mins. I dont know if it is correct to be done. I tried searching the internet but couldn't find anything
ROTP permits an issuer to be specified which Google Authenticator and others show as a label for the codes. It's a nice UI feature we'd like to support as well.
Hi,
First, thanks for this convenient gem.
This Issue mirrors for HOTP the already existing issue for TOTP here: #57
We are well aware that this gem only respects the response received from rotp
(cf. #57 (comment)), however this is currently breaking this gem's behavior
This issue is open for tracking purposes. A PR is coming as a proposal to ensure authenticate_otp
returns a boolean value
Hi all! I am trying to use onetime backup codes feature, but it is not working as expected. Not sure if it is a bug or I missed anything. Any help will be appreciated. Thanks!
a.otp_one_time_backup_codes
=> true
a.otp_backup_codes
=> "[\"115800\", \"262347\", \"495694\", \"737253\", \"636428\", \"661834\", \"859156\", \"287292\"]"
a.authenticate_otp('115800')
=> true
a.authenticate_otp('115800')
=> true
a.otp_backup_codes
=> "[\"115800\", \"262347\", \"495694\", \"737253\", \"636428\", \"661834\", \"859156\", \"287292\"]"
From
active_model_otp/lib/active_model/one_time_password.rb
Lines 203 to 207 in fb8b178
Versions:
active_model_otp (2.3.2)
activemodel
rotp (~> 6.2.0)
rails (7.0.6)
ruby 3.2.2
Every user, who is created with has_one_time_password
present in the User model, gets this error below if they try to log in or use the password.
BCrypt::Errors::InvalidHash
I need help to move past this, please. Thank you.
There is a CVE reported on rotp to 6.2.1 and 6.2.2
The fix is to update rotp to >= 6.3.0
Current gemspec prevents the update spec.add_dependency "rotp", "~> 6.2.0"
ruby-advisory-db:
advisories: 882 advisories
last updated: 2024-03-18 19:03:51 -0700
commit: 35ca69bb256418b4cec81327e659ed6c0257d25b
Name: rotp
Version: 6.2.2
CVE: CVE-2024-28862
GHSA: GHSA-x2h8-qmj4-g62f
Criticality: Medium
URL: https://github.com/mdp/rotp/security/advisories/GHSA-x2h8-qmj4-g62f
Title: ROTP 6.2.2 and 6.2.1 has 0666 permissions for the .rb files.
Solution: upgrade to '>= 6.3.0'
Hi!
First of all, thanks for this super convenient gem which works great. I'm using it for HOTP support and discovered 2 bugs in provisioning_url
:
Gemfile:
active_model_otp (2.0.1)
activemodel
rotp (~> 5.0.0)
User u:
...
otp_counter: 8,
...
Now if I run:
u.provisioning_uri(nil, issuer: 'My fancy issuer')
I get:
"otpauth://hotp/[email protected]?secret=XE7ZAMIPLYEHUOFFFMT5M52R6LO7762X&counter=0"
Cheers,
Kalsan
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.