How to add 2FA in the authentication process of Expressive app?

Hi,

I would like to add a Two Factor Authentication (2FA) in the login process of my expressive app.
I found some existing php library for Google Authenticator (can be a good choice) but i need to add a step between expressive authentication and the private area. I mean when the user enter his username and password, it doesn’t must to be valid until the step to check the 2FA code.

Someone already use something like that in expressive?

How can be the right workflow (if 2FA is already configured in the user account)?

  • ask username and password in a form
  • check only if valid, do not authenticate…
  • if valid, add username and password entered in the form to an temp variable somewhere in session
  • show the 2FA page with QRCode or number to enter
  • if 2FA is valid, use the username and password in session to authenticate
  • and enter in the private area

Is it realistic?

Thanks for your help

1 Like

So, i implemented the 2FA with expressive 3 and Google Authenticator and it’s works!
I used some resource that i found written by @akrabat for Slim and i adapted to Expressive.

But i have a potential security problem in my workflow in Expressive…
If a user wants to use 2FA authentication i must store the raw password in the session until the login is completed. (Because i have to pass in the AuthenticationMiddleware only at the end of the process, when 2FA is valided)

So, just after the initial login form (username, password) i only check if user exist and if yes compare the password with “password_verify” method and redirect to a specific 2FA handler. In that 2FA handler when the code is verified i pass the username and password from the session to the next middleware (authentication) like that:

...

// Unset in session
$session->unset('user_auth_in_progress');
$session->unset('raw_password');

// Set parameters for next middleware (authentication)
$request = $request->withMethod('POST');
$request = $request->withParsedBody(['username' => $userInProgress['username'],
                                                    'password' => $rawPassword]);

// And pass to the next middleware (auth)
$response = $handler->handle($request);

...

Do you think is the right way to do that?
**I don’t like to store a raw password in session… But a PRE-authentication method or something like that do not exist. Another idea? **

Thanks!

Present the user with the login form, once the user has successfully authenticated, store the authenticated user in a cache and clear the authentication storage before redirecting to mfa handler. After successful MFA restore the storage from cache.

Thanks @lostpacket, i didn’t thought of that. Now is better!