jeremyevans/rodauth

Required Features

Closed this issue · 3 comments

Thanks to @janko, I've been able to play with this lib with Rails. I have some "missing" features that are required for my apps.

I'm willing to create them but I'd like your opinion if it's possible to create them or if it needs to be a separate plugin (and maybe a separate gem)

  • Send OTP via email
    • Similar to the verify email, send an email with a code to enter to validate login
  • Request OTP before an action
    • Right now, when logging with OTP, session[authenticated_by_session_key] is an array that contains strings
    • We should add a new key otp_used_at that contains the last time the OTP has been entered. Thus, we should be able to specify a delay after which the OTP is required again
  • Request password before an action
    • Same as "Request OTP before an action"
    • We should add a new key password_used_at that contains the last time the password has been entered
  • Block disposable emails
    • I'll create a separate gem for that
janko commented

Request password before an action

This one is already possible using #require_password_authentication method from the confirm_password feature, together with password_grace_period feature which remembers an entered password for a period of time (in a session, as far as I remember). For example:

configure do
  enable :confirm_password, :password_grace_period
  # ...
end

route do |r|
  # ...
  if r.path == "/action"
    rodauth.require_password_authentication
  end
  # ...
end

Send OTP via email

In general, the email_authentication feature works the exact same way, but is more secure as it uses a link instead of a 6-digit code. Is there a reason you wouldn't want to use that?

Assuming you did have a specific reason for using a short code instead of a link, this would probably need to be implemented as a separate feature similar to the SMS implementation, but without having to register a phone number. You wouldn't want to build it on top of the OTP feature (which uses TOTP).

Request OTP before an action

The otp feature stores the last time used. We could probably add a method you could call get to get the last use time, then you could do something like the following at the top of the routing tree:

if rodauth.authenticated_by&.include?('otp') && rodauth.otp_last_use < Time.now - 3600
  rodauth.authenticated_by.delete('otp')
end
rodauth.require_authentication

However, this assumes you are using the otp feature, and not OTP codes via email.

I implemented otp_last_use. You can use it pretty much in the same way the code example I gave, though using 'totp' instead of 'otp' as the string.

Note that this probably isn't the best way to handle the issue, since otp_last_use is not limited to the current session. You are probably better off using after_two_factor_authentication, setting the session key to the current time, and checking that:

  after_two_factor_authentication do
    session['mfa_at'] = Time.now.to_i
  end

Then you can check session['mfa_at'] and use it to implement your expiration.

Still, I think otp_last_use is a good general method to add, even if not particularly useful for expiration.

I did not implement the other features you requested, though potentially we could discuss the possibility of adding them on the Google Group. As reminder, per the contribution guidelines, GitHub Issues should only be used for reporting bugs in the library, not for feature requests. Please discuss feature requests on the Google Group.