Code Monkey home page Code Monkey logo

otp-jwt's Issues

otp_secret is not being saved for preexisting data

I have a User table that has preexisting data, and I start using otp-jwt recently.
It is not working at the beginning because otp_secret column is always empty for preexisting User record

The active record does give the User record a default otp_secret

def setup_otp
self.otp_secret ||= ROTP::Base32.random_base32
self.otp_counter ||= 0

My workaround is to go through each user record and save the default otp_secret

User.all.each do |u|
  u.save()
end

Not sure whether we can make it better by updating the documentation, or always save the default secret if there are otp_secret column is empty

verify_otp returns otp_counter or nil

First of all, awesome gem! :-)

In the docs is stated that verify_otp will return true on success and false on failure. In my case if it's true it returns the otp_counter and if its false nil. I made a local patch that return !otp_status.nil? instead of otp_status.

Is retuning the counter or nil intended?

Sponsors

Just a placeholder issue where I can upload logos lol

Fix docs

I think include OTP::ActiveRecord should be this include OTP::JWT::ActiveRecord.

Encrypting OTP Secret in the database

Hey @stas
First off thanks so much for your work on this project. I want to use it on a small project that I am working on and just wanted to get your thoughts on if you think its worthwhile to encrypt the the OTP secret/counter in the database.

I know most of the time that sensitive information such as one time use tokens or passwords are stored in the database it is usually hashed (I think devise does this with its reset password links), but that wont be possible with this project as we would need to get the data back, so was thinking encryption was another option.

Was just thinking that if anyone was to get read access to the database (for example if a database backup was leaked) they would be able to get the secrets/counters for all the users and possibly log in as anyone.

Was thinking i could use a project like lockbox to handle the encryption for me which should work seamlessly with this project. Do you think this would be worthwhile or unnecessary and wont really improve anything.

Provided `jwt_algorithm` isn't being considered on `OTP::JWT::Token.verify`

I set the jwt_algorithm to RS256 and provided a valid RSA private key to it, but for some reason, the from_jwt started to return a nil value. I managed to track down a possible issue. The jwt_algorithm isn't being considered in the current implementation of the OTP::JWT::Token.verify method and the from_jwt doesn't allow us to pass otps to the verify method.

The block bellow should solve the issue.

      def self.verify(token, opts = nil)
        verify = self.jwt_algorithm != 'none'
        default_opts = verify ? { algorithm: self.jwt_algorithm } : {}

        ::JWT.decode(token.to_s, self.jwt_signature_key, verify, opts || default_opts)
      end

to_jwt and from_jwt multiple user models

I don't see anything about this gem supporting two user models, however, the documentation does seem to indicate the use on multiple active record models. So this could be a bug if used on multiple models.

I have a User and Admin model
I generate a JWT for each instance and then can find that instance using from_jwt as expected.
However, what I didn't expect was to be able to use the same JWT for an Admin instance and find a User instance. Either the JWT is not unique, or the from_jwt method has a bug.

Here is a JWT for a particular User instance eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxNX0.gZvAxDmz4eBQQLmc_-Zxj0bWUkvaWnWKzKOLHQw-uRM

I can find an Admin using that same JWT as shown below

[47] pry(#<Api::V1::Admins::UsersController>)> Admin.from_jwt("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxNX0.gZvAxDmz4eBQQLmc_-Zxj0bWUkvaWnWKzKOLHQw-uRM")

  CACHE Admin Load (0.1ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<Admin id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:33", updated_at: "2019-07-05 21:06:25", account_id: 1, role: "super", first_name: "Super", last_name: "Test", title: "yes", authentication_token: "zavi5k8_5HLNxqLSYN2N", otp_secret: "4bpzyy7ugnsb5x3v3u2d634cpbsnztjd", otp_counter: 0>



[48] pry(#<Api::V1::Admins::UsersController>)> User.from_jwt("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxNX0.gZvAxDmz4eBQQLmc_-Zxj0bWUkvaWnWKzKOLHQw-uRM")

  CACHE User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:35", updated_at: "2019-07-05 21:06:34", account_id: 1, first_name: "Sherill", last_name: "test", employee_number: nil, tenure: nil, title: "GM", department: nil, gender: nil, region: nil, location: nil, brand: nil, ancestry: "2", manager_id: nil, hire_date: nil, relocate: nil, short_term_plan: nil, long_term_plan: nil, last_email_sent: nil, authentication_token: "WpYq7HypQzytMp1GxkiE", otp_secret: "7r6ooydbzlsodbxluyhswcuxpubfybfj", otp_counter: 0>
[49] pry(#<Api::V1::Admins::UsersController>)>

Here is a complete terminal output to highlight each instances and their respective JWT's.

[39] pry(#<Api::V1::Admins::UsersController>)> @user
=> #<User id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:35", updated_at: "2019-07-05 21:06:34", account_id: 1, first_name: "Sherill", last_name: "test", employee_number: nil, tenure: nil, title: "GM", department: nil, gender: nil, region: nil, location: nil, brand: nil, ancestry: "2", manager_id: nil, hire_date: nil, relocate: nil, short_term_plan: nil, long_term_plan: nil, last_email_sent: nil, authentication_token: "WpYq7HypQzytMp1GxkiE", otp_secret: "7r6ooydbzlsodbxluyhswcuxpubfybfj", otp_counter: 0>
[40] pry(#<Api::V1::Admins::UsersController>)> @admin
=> #<Admin id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:33", updated_at: "2019-07-05 21:06:25", account_id: 1, role: "super", first_name: "Super", last_name: "Test", title: "yes", authentication_token: "zavi5k8_5HLNxqLSYN2N", otp_secret: "4bpzyy7ugnsb5x3v3u2d634cpbsnztjd", otp_counter: 0>
[41] pry(#<Api::V1::Admins::UsersController>)> @admin.to_jwt
=> "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxNX0.gZvAxDmz4eBQQLmc_-Zxj0bWUkvaWnWKzKOLHQw-uRM"
[42] pry(#<Api::V1::Admins::UsersController>)> @user.to_jwt
=> "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxOH0._Uqisk_hpYYdIgS4MNfl8mwW-_lfCprzhOXkJ7OI8FM"
[43] pry(#<Api::V1::Admins::UsersController>)> Admin.from_jwt("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxNX0.gZvAxDmz4eBQQLmc_-Zxj0bWUkvaWnWKzKOLHQw-uRM")

  CACHE Admin Load (0.1ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<Admin id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:33", updated_at: "2019-07-05 21:06:25", account_id: 1, role: "super", first_name: "Super", last_name: "Test", title: "yes", authentication_token: "zavi5k8_5HLNxqLSYN2N", otp_secret: "4bpzyy7ugnsb5x3v3u2d634cpbsnztjd", otp_counter: 0>
[44] pry(#<Api::V1::Admins::UsersController>)> User.from_jwt("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxOH0._Uqisk_hpYYdIgS4MNfl8mwW-_lfCprzhOXkJ7OI8FM")
  CACHE User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:35", updated_at: "2019-07-05 21:06:34", account_id: 1, first_name: "Sherill", last_name: "test", employee_number: nil, tenure: nil, title: "GM", department: nil, gender: nil, region: nil, location: nil, brand: nil, ancestry: "2", manager_id: nil, hire_date: nil, relocate: nil, short_term_plan: nil, long_term_plan: nil, last_email_sent: nil, authentication_token: "WpYq7HypQzytMp1GxkiE", otp_secret: "7r6ooydbzlsodbxluyhswcuxpubfybfj", otp_counter: 0>
[45] pry(#<Api::V1::Admins::UsersController>)> Admin.from_jwt("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxOH0._Uqisk_hpYYdIgS4MNfl8mwW-_lfCprzhOXkJ7OI8FM")
  CACHE Admin Load (0.1ms)  SELECT  "admins".* FROM "admins" WHERE "admins"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<Admin id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:33", updated_at: "2019-07-05 21:06:25", account_id: 1, role: "super", first_name: "Super", last_name: "Test", title: "yes", authentication_token: "zavi5k8_5HLNxqLSYN2N", otp_secret: "4bpzyy7ugnsb5x3v3u2d634cpbsnztjd", otp_counter: 0>
[46] pry(#<Api::V1::Admins::UsersController>)> User.from_jwt("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImV4cCI6MTU2MjcxNDcxNX0.gZvAxDmz4eBQQLmc_-Zxj0bWUkvaWnWKzKOLHQw-uRM")
  CACHE User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, email: "[email protected]", created_at: "2019-07-04 22:27:35", updated_at: "2019-07-05 21:06:34", account_id: 1, first_name: "Sherill", last_name: "test", employee_number: nil, tenure: nil, title: "GM", department: nil, gender: nil, region: nil, location: nil, brand: nil, ancestry: "2", manager_id: nil, hire_date: nil, relocate: nil, short_term_plan: nil, long_term_plan: nil, last_email_sent: nil, authentication_token: "WpYq7HypQzytMp1GxkiE", otp_secret: "7r6ooydbzlsodbxluyhswcuxpubfybfj", otp_counter: 0>
[47] pry(#<Api::V1::Admins::UsersController>)>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.