You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

totp.rb 2.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. # frozen_string_literal: true
  2. # Redmine - project management software
  3. # Copyright (C) 2006-2020 Jean-Philippe Lang
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. module Redmine
  19. module Twofa
  20. class Totp < Base
  21. def init_pairing!
  22. @user.update!(twofa_totp_key: ROTP::Base32.random)
  23. # reset the cached totp as the key might have changed
  24. @totp = nil
  25. super
  26. end
  27. def destroy_pairing_without_verify!
  28. @user.update!(twofa_totp_key: nil, twofa_totp_last_used_at: nil)
  29. # reset the cached totp as the key might have changed
  30. @totp = nil
  31. super
  32. end
  33. def verify_otp!(code)
  34. # topt codes are white-space-insensitive
  35. code = code.to_s.remove(/[[:space:]]/)
  36. last_verified_at = @user.twofa_totp_last_used_at
  37. verified_at = totp.verify(code.to_s, drift_behind: allowed_drift, after: last_verified_at)
  38. if verified_at
  39. @user.update!(twofa_totp_last_used_at: verified_at)
  40. return true
  41. else
  42. return false
  43. end
  44. end
  45. def provisioning_uri
  46. totp.provisioning_uri(@user.mail)
  47. end
  48. def init_pairing_view_variables
  49. super.merge({
  50. provisioning_uri: provisioning_uri,
  51. totp_key: @user.twofa_totp_key
  52. })
  53. end
  54. private
  55. def totp
  56. @totp ||= ROTP::TOTP.new(@user.twofa_totp_key, issuer: Setting.app_title)
  57. end
  58. end
  59. end
  60. end