← Back to context

Comment by jillesvangurp

5 days ago

I adapted code for Java back in the day from here: https://github.com/j256/two-factor-auth/blob/master/src/main...

A bit longer but most of it is just boilerplate Java stuff to deal with polymorphism and a base32 implementation. I recall, stripping most of that away in our internal adapted version of that.

Key points:

- generate a 16 character base32 secret and stuff it in a totp link. otpauth://totp/Alice:alice@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Alice

- stuff that in a QR code and show it to the user so they point their phone authenticator app at it to store the secret. We used a js library for this.

- store the secret with the user account in a secure way (we used aes encryption for this)

- when verifying, use the secret, a timestamp in seconds after the epoch divided by 30 (simple normalization step applied on the client as well) and use the user provided number to construct a sha1 hmac and grab the last digits and prepend with zeros. The calculated string should be the same as what the user typed from their token app as long as their clock is in sync.

- we actually implemented a grace period by calculating the before and after code as well so the user isn't screwed over if the number rotates while they were tapping out the code.

While relatively easy to implement, we ran into a lot of friction rolling this out to normal users. Basically non technical people find this stuff super confusing and we had to hand hold quite a few people through the process and we also had to deal with people that lost their secret, or kept on using the wrong code (for a different account). The UX of this stuff is just terrible. Be prepared to deal with a lot of support overhead if you choose to roll this out. A non trivial percentage of users will manage to lock themselves out of their accounts.