I have more or less finalized an XData/Sphinx setup (as services on a VPS in the cloud) and all is working nicely (including customized log in screen ) but I am now facing some challenges regarding two factor authentication.
Unfortunately the documentation is quite sparse on this subject so I am looking for some guidance or clues how to fix these issues:
According to the documentation (Login web application | TMS Sphinx documentation), the user should be presented with a QR code after his/her first successful log in. Unfortunately, the QR is not showing. The user is taken straight to input of the 2FA one-time code (verify your ID). What am I missing or doing wrong? This is the code I execute when creating a user:
var
CoreOptions: ICoreOptions;
UsrMgr: IUserManager;
Usr: TSphinxUserEx; // Extended user class
AuthenticatorKey: string;
begin
CoreOptions := TConfigCoreOptions.Create(SphinxConfig);
UsrMgr := TUserManager.Create(CoreOptions, FObjMgr, false);
........
UsrMgr.CreateUser(Usr, dlgUser.Password);
UsrMgr.SetTwoFactorEnabled(Usr, dlgUser.TwoFactorEnabled);
UsrMgr.SetTwoFactorRequired(Usr, dlgUser.TwoFactorRequired);
if Usr.TwoFactorEnabled then
if UsrMgr.GetAuthenticatorKey(Usr) = '' then
UsrMgr.ResetAuthenticatorKey(Usr);
AuthenticatorKey := UsrMgr.GetAuthenticatorKey(Usr);
FMyMailer.SendNewAccountDetails(Usr.Email.Value, Usr.UserName.Value, dlgUser.Password);
FMyMailer.SendAuthenticatorKey(Usr.Email.Value, AuthenticatorKey);
On the off-chance that it was influenced by the customized login screens, I removed the css & img sub-folders and set SphinxConfig.UIOptions.LoginAppFolder := '';. Unfortunately this too makes no difference.
I am also struggling with SphinxConfig.LoginOptions.RequireTwoFactor. I have two users in my test database, one with TwoFactorEnabled AND TwoFactorRequiredfalse and one with both properties set to true. For the latter I have the above problem but setting SphinxConfig.LoginOptions.RequireTwoFactor to true, I would expect 2FA is enforced for ALL users even if individually set to false. I.e. I see no effect on the login process (workflow) for either user. Am I misunderstanding this property and if so, is it documented somewhere how it interacts the two user properties?
You should have TwoFactorRequired set to True and TwoFactorEnabled set to False.
TwoFactorRequired having True means the user must enable two-factor to proper login. Thus, if he doesn't have it enabled, Sphinx will show the QR Code for him to enable it.
TwoFactorEnabled having True means the two-factor is already enabled for the user, thus in every login the two-factor code will asked directly.
LoginOptions.RequireTwoFactor is a default value for TwoFactorRequired. If the latter is null (not set), then Sphinx will use the former as the default value. If the former was already set for that specific user, then its value will be used regardless of the value of the former.
Thanks for the quick response, Wagner. All is clear now (testing OK). It was was a clear case of "not seeing the forest for the trees".
It is a small yet important detail on LoginOptions.RequireTwoFactor that it is ignored if TwoFactorRequired is set to false for the user (i.e. only applies if this value is null). I mistook it as an general override switch (for lack of a better term) for all users. Thanks for noting this.
Whilst working on this, I see (from example code) that I am also using:
if User.TwoFactorEnabled then
if UserManager.GetAuthenticatorKey(User) = '' then
UserManager.ResetAuthenticatorKey(User);
What is the purpose of UserManager.ResetAuthenticatorKey(User)? I would think (likely mistakenly ) that it would "reset" User.TwoFactorEnabled to null (i.e. reset 2FA setup), so that on the next login a QR is shown to set it up again.
ResetAuthenticatorKey changes the internal key so that a new set of 2fa codes are required. That is an internal, low-level method. It won't set TwoFactorEnabled to false, you would have to do it yourself if you want to.
OK. So let's say the user somehow lost his authenticator setup and requires a new QR code. Is merely setting 2FA enabled to false sufficient, or should I also call ResetAuthenticatorKey for that user?
Settings 2fa to false should be enough. But for security reasons it's always better to reset authenticator key, why not, if user lost his setup anyway?