I am excited about 2FA! As someone who has built 2FA for another
company in the past, I have some thoughts which are hopefully helpful
in building out clean, effective workflows:
------
We probably want Oasis and other larger deployments to also support
2FA, so there should be a flow in which users are able to recover
their own account (say, because their phone died and they've lost the
shared secret) without requiring the server admin to authenticate the
user. This is traditionally done with your 10 one-time use passcodes
that you nudge users to save and print out.
I agree that we should retain a method by which the admin can also
either deactivate 2FA for a user or aid them in reenrolling a new
secret. Note that administrators cannot reasonably enroll most users
without the user being involved, since they can't install the secret
on the user's device.
------
As Kenton noted, 2FA should probably work with all the identity
providers, which makes me think that technically it might make more
sense to be attached to the *account* rather than the identity. It
would be surprising if I as a user enabled 2FA for my Google identity,
but an email login identity that is also able to log in to my account
could gain access with just the email code, and I don't think anyone
benefits from having multiple 2FA codes attached to the same account -
the risk profile is the same; you've just increased the odds that you
key in the wrong code and/or are confused. So let's think of 2FA as
something you control at the granularity of an account.
This means that you can't ask for the 2FA code up front for the other
login mechanisms - for at least Google, GitHub, and SAML login, the
Sandstorm server doesn't know a priori which account the user is going
to come back from the remote system authenticated as. For email
token, requiring the TOTP code up front would mean that users can't
click the link in their email any more either, which I think is a
valuable affordance.
I think we'll have to process an identity login first, and give the
user a "half-logged-in" state, where they have authenticated as an
identity, but must still prove possession of their second factor in
order to access to their account.
------
On the topic of "who gets 2FA": the appropriate answer depends on the
deployment.
Some organizations are likely to want to be able to require 2FA for
all users, so if the user has not enrolled a 2FA code yet, they are
required to do so before they can make other use of their account. At
a past company, this was a great way of providing additional security
against a potential email breach. Whatever we design should ideally
be compatible with such a feature.
Other organizations may already have 2FA implemented at their login
provider (e.g. SAML instance), so they may want to disable Sandstorm's
notion of 2FA, since it would only lead to confused users internally.
I suspect the appropriate setting for the server admin is a tristate:
* disallowed (users are not allowed to enroll, and no 2FA options are shown)
* opt-in (users may enroll in 2FA, but can elect to disable 2FA at any time)
* required (users must enroll in 2FA before taking other actions as
their logged-in account/identity)
and that the default value for a server should be opt-in, which allows
technically-inclined users to enable the additional security feature,
which is of particular interest to server admins, who we should
encourage to protect their higher-value accounts.
------
Supporting TOTP adds a requirement of accurate timekeeping for the
server that Sandstorm is running on. We may want to add some sort of
self-check to diagnose potential clock skew, if people run this on
servers without some sort of time sync daemon.
------
Since 2FA is intrinsically a security-impacting account action,
transactional emails should probably be sent to the account's primary
notification address whenever:
* the account enrolls a new 2FA code
* the accounts 2FA is disabled (whether that be triggered by self or
by an admin)
* one of the accounts' backup/recovery codes is used to authorize a login
* backup codes are regenerated/cycled.
-------
This is pretty great, and I'm excited to see where this goes!
-Drew