Fixed: So, there is nothing we can do to help you, sorry. - system clock issue.
Also, at least in my view as a cybersecurity person, there is no real reason (for non staff members) to use 2FA here as there is little risk, as it's just a forum, not a bank account or anything where using 2FA is critical or even important.
So, if you cannot make it work our Discourse forum, @Mekando, there is no risk or loss to you as you are not a staff member with any special privs here.
Regarding other Discourse forums, I have no idea because I do not enable 2FA for forums, sorry; and I don't consider 2FA important for a discussion forum for regular members and so will not spend any time on this, sorry again.
This is hard coded in the Discourse code, but it should be an admin config setting:
TOTP_ALLOWED_DRIFT_SECONDS = 30
Did not measure the offset before correcting, because we simply used ntpdate to update the system time on the server, and at the same time, used chrony on the client end, and it worked. Should have recorded the clock skew first, but were just testing for a fix and forgot to record before running both chrony and ntpdate.
See
Now, we are running ntpdate in the cron to keep the server clock more accurate :). Thanks @Mekando for poking us about this.
The problem is more of a Discourse issue, not a server issue.
The problem is here in the Discourse code:
def invalid_totp_or_backup_code_result
invalid_second_factor_authentication_result(
I18n.t("login.invalid_second_factor_code"),
"invalid_second_factor"
)
end
If you look at the code a bit deeper you can see that the error message is incorrect when the drift time is exceeded.
If the error message was correct, in this case, something like:
Drift time exceeded.
Instead of:
Each code can only be used once.
Then, the error message would have not been misleading (or in this case, totally wrong), causing confusion for users.
Its a case of poor error message coding / management in the Discourse code base.
Even though the problem is fixed now because the clocks are correct, when clocks are not correct and the hard coded drift time is exceeded (or the user waits too long to enter the TOTP), users will see the wrong error message, as in this case.
Anyway, we cannot complain. Discourse is open source and we are not going to submit a PR to fix these issues:
Incorrect error message.
Hard-coded 30 second drift tolerance value for TOTP.