Email OTP
Verify Email by send OTP code (Rails)
Prepare package
Send otp to email
def send_otp_to_email
respond_to do |format|
format.json do
redis = Redis.new
if redis.ttl("email-otp-#{params[:email]}") > (300 - 60)
render json: { success: true, message: 'Already send otp code to email, please wait a moment' }
return
end
otp_secret = ROTP::Base32.random
totp = ROTP::TOTP.new(otp_secret, issuer: 'Validate Email otp')
otp = totp.now
redis.set("email-otp-#{params[:email]}", otp_secret)
# send otp mail to user
# MailWorker.perform_async(Mailer, :send_otp_to_email, { email: params[:email], otp: otp })
render json: { success: true, message: "Already send otp code to your email, please checkout" }
end
end
end
Explain:
redis.ttl("email-otp-#{params[:email]}") > (300 - 60)
we need to cauclate time, when first time send mail, and default time is 5 minutesotp_secret = ROTP::Base32.random
Generating a Base32 Secret keytotp = ROTP::TOTP.new(otp_secret, issuer: 'Validate Email otp')
we use rotp get otp code by otp_secretotp = totp.now
get otp coderedis.set("email-otp-#{params[:email]}", otp_secret)
we need to save temp token, we will use it later for validate
Verify otp
def verify_otp
redis = Redis.new
otp_secret = redis.get("email-otp-#{params[:email]}")
if otp_secret.nil?
render json: { success: false }
return
end
totp = ROTP::TOTP.new(otp_secret, issuer: 'Validate Email otp')
if totp.verify(params[:otp], drift_behind: 300)
token = SecureRandom.base58(20)
redis.setex("otp-token-#{params[:email]}", 5.minutes, token)
render json: { success: true, token: token }
else
render json: { success: false }
end
end
Explain:
otp_secret = redis.get("email-otp-#{params[:email]}")
get otp_secret for verifytotp = ROTP::TOTP.new(otp_secret, issuer: 'Validate Email otp')
we use rotp verify otp code by otp_secrettotp.verify(params[:otp], drift_behind: 300)
verify otp code, set 5 minutes expiredtoken = SecureRandom.base58(20)
generate random tokenredis.setex("otp-token-#{params[:email]}", 5.minutes, token)
set token for your application