Currently building authentication for a mobile app, and the flow goes as follows:
User inputs phone # > User receives TOTP SMS > User inputs TOTP > User is logged in
Would you store TOTP in DB or in memory (ETS or GenServer)?
Currently building authentication for a mobile app, and the flow goes as follows:
User inputs phone # > User receives TOTP SMS > User inputs TOTP > User is logged in
Would you store TOTP in DB or in memory (ETS or GenServer)?
Database. It lets you run multiple versions of your app easily, and if your app goes offline, that doesn’t nuke people’s code.
GenServers / ets are a great way to store ephemeral state or cache values. TOTP codes are short lived but not ephemeral.
That answer was FAST man
Makes sense, follow up question, would you have a separate table for them, or just stick them in the account/user table ?
What’s the difference ?
It means that if you store them in memory and your server goes off or restarts before the user receives the TOPT and inputs it, then the application will not recognize the valid TOPT and the user is forced to repeat the process.
would you have a separate table for them, or just stick them in the account/user table ?
Definitely a separate table. You want to track individual issuances of these codes.
You want to track individual issuances of these codes
For what purpose ? I naively assumed that even though they would be in a separate table, that they should be cleaned up after verification.
Hmm on second thought, attempt limiting I guess?
Yeah it’s worth cleaning them out eventually but we like to keep them around for customer support and security purposes for a bit. If someone is having issues it’s easier to help if you can see all of their attempts.
Why store individual TOTPs at all? " Time-based" in TOTP mean that knowing shared secret you can always generate all past and future tokens, so storing them is pointless.
@WestKeys probably meant OTP not specifically TOTP. TOTP do not need to be stored at all (except the shared secret).
Yes you’re right. Naively assumed OTP’s with an expiry == TOTP.
I would highly suggest “real TOTP” instead of SMS based 2FA, as the latter can work even with offline devices. It is also much easier and cheaper to implement.
I have not used it personally but you should check out NimbleTOTP v0.1.1 — Documentation, it seems as though they have implemented most of what you need already. Just store the secret after the user has confirmed it and then you can get codes from an authenticator app or text them to a user yourself.
text them to a user yourself
That will not really work, as the lifetime of the TOTP can be too narrow for such unreliable messaging system like SMS.
I’ve never implemented such a system myself so you’re probably right, but I know that I can get a text message with a 2fa code from basically every provider who offers 2fa, so there must be a way to do that.
message with a 2fa code from basically every provider who offers 2fa, so there must be a way to do that.
It probably uses exactly what OP is trying to do - generate token that have some timeout and is assigned to your account. Now you just send message and wait for a code. The problem with using TOTP is that these have (by default) have 30s lifetime, and using the same secret with different lifetimes can cause problems AFAIK. Of course you could generate several secrets and then just use different when trying different auth method (with different lifetimes).
Pretty sure NimbleTOTP and TOTP in general requires authenticator app, and can’t support SMS workflow. The verification code is actually generated by the authenticator app itself, based on the secret provided to it by, in this case, NimbleTOTP.
I may be wrong. All ears.
I’m building a chat app. Imagine the onboarding friction of having to download a 2nd app for 95% of users.
I do agree though that TOTP is cheaper, easier and much more secure.
I’m building a chat app. Imagine the onboarding friction of having to download a 2nd app for 95% of users.
If that is corporate, then screw all that and force SAML/LDAP/OpenID/other centralised corporate authentication system. Also many password managers already support TOTP generators (for example 1password does) and some corporations require usage of such.
If it is “civil” user facing, then it can be a little bit irritating, but maybe email would be easier in such environment instead of SMS (I assume that login is email-based, if it is phone-based, then SMS probably make more sense).
Do we also store the secrets from the TOTP algorithm in the same table or separate? Thanks!!
EDIT: just found this and it suggests that we would store it in a separate table:
defmodule Bytepack.Accounts.UserTOTP do
use Bytepack.Schema
import Ecto.Changeset
schema "users_totps" do
field :secret, :binary
field :code, :string, virtual: true
belongs_to :user, Bytepack.Accounts.User
embeds_many :backup_codes, BackupCode, on_replace: :delete do
field :code, :string
field :used_at, :utc_datetime_usec
end
timestamps()
end
def changeset(totp, attrs) do
changeset =
totp
This file has been truncated. show original
super helpful reference in case anyone else needs it!