Skip to content

Instantly share code, notes, and snippets.

@snmmaurya
Last active March 19, 2021 02:38
Show Gist options
  • Save snmmaurya/8aaf07cb76702bb867eb195100245d58 to your computer and use it in GitHub Desktop.
Save snmmaurya/8aaf07cb76702bb867eb195100245d58 to your computer and use it in GitHub Desktop.
Rails how to implement google 2fa (using rotp gem)

Step - 1

Install rotp gem

In my case I am using an user model to add google 2fa.

Setp - 2

Add a new column to store otp_secret in my case the column name is otp_secret.

for ex -

add_column :users, :otp_secret, :string, unique: true

On create of a user set (Base32 string) ROTP::Base32.random_base32 into otp_secret

for ex -

class User
  .............
  ..
  .

  before_create :set_otp_secret

  def set_otp_secret
    self.otp_secret = ROTP::Base32.random_base32
  end
  .
  ..
  .............
end

For existing users you have to manually set otp_secret.

for ex -

User.query_to_exiting_users.each do |user|
  user.otp_secret = ROTP::Base32.random_base32
  user.save!
end

RECOMENDATION

you should store encrypted otp secret to database for reference - https://gist.github.com/snmmaurya/f49dbf1f4d2ba5ced1ff302a2e8ade90

STEP - 3

How to create QR code -

user = User.find(...)
totp = ROTP::TOTP.new(user.otp_secret, issuer: "Service")
qrcode_provisioning_uri = totp.provisioning_uri(user.email)
qrcode_generator_url = "https://chart.googleapis.com/chart?chs=256x256&cht=qr&chl=#{qrcode_provisioning_uri}"

qrcode_generator_url will look like -

https://chart.googleapis.com/chart?chs=256x256&cht=qr&chl=otpauth://totp/snmmaurya@gmail.com?secret=qnujcfrgxmlpuygb&issuer=Service

visit on above url, to get QR code image.

if you don't have google authenticator install it and scan QR code image.

for ex-

class User
  .............
  ..
  .

  before_create :set_otp_secret

  def qrcode_provisioning_uri
    totp = ROTP::TOTP.new(self.otp_secret, issuer: "Service")
    totp.provisioning_uri(self.email)
  end
  .
  ..
  .............
end
user = User.find(...)
qrcode_generator_url = user.qrcode_provisioning_uri

qrcode_image_generator_url = "https://chart.googleapis.com/chart?chs=256x256&cht=qr&chl=#{qrcode_generator_url}"

Step - 4

How to verify otp at authentication label -

user = User.find .....

rotp = ROTP::TOTP.new(user.otp_secret)
rotp.verify(OTP) # returns true if otp is correct
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment