![](https://keeplearning.dev/images/featured/what-are-array-reduce-and-array-walk-in-php-f141f123f41.png)
PHP
Here is the story of how to implement a 2FA Authentication.
Two-factor authentication (2FA) is an identity and access management security method that requires two forms of identification to access resources and data. (Microsoft)
There are different types of 2FA authentications.
Some of them are;
In this article, I implement TOTP-based 2FA.
The algorithm uses a form of symmetric key cryptography: the same key is used by both parties to generate and validate the token.
The TOTP algorithm follows an open standard documented in RFC 6238. The inputs include a shared secret key and the system time.
I used some open-source packages for this purpose.
This package (Google2FA) is a PHP implementation of the Google Two-Factor Authentication Module, supporting the HMAC-Based One-time Password (HOTP) algorithm specified in RFC 4226 and the Time-based One-time Password (TOTP) algorithm specified in RFC 6238.
This package provides us to;
We need to set each user a secret key. With this secret key, we will generate a QR and the Authenticator Apps will easily scan them. After that, with this secret key, we will be able to validate generated codes from the device.
Example for generating a secret;
$google2fa = new Google2FA();
$secret = $google2fa->generateSecretKey();
// you can give length as first parameter for specify key length
So we need to generate a QR code for scanning with any device. For doing this, basically, we need this code block.
public function createInlineQRCode($email, $secret)
{
$google2fa = new Google2FA();
$inlineUrl = $google2fa->getQRCodeInline(
'APP_NAME',
$email,
$secret
);
return $inlineUrl;
}
This will create an inline QR code. You need to echo this. If any page you can easily use these headers and echo a QR code.
header('Content-Type: image/svg+xml');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
echo $this->createInlineQRCode($user->email, $user->secret);
In the last step, we need to verify generated code. With this library, you need to use this code block for verifying entered code.
public function verify($secret, $code)
{
$google2fa = new Google2FA();
return $google2fa->verifyKey($secret, $code);
}
Basically, you need to pass the secret and code (entered code from the user) to verifyKey method.
I said basic things about the technical part. Let’s deep dive into real implementation with the flow.
This is the main flow of my implementation. Of course, there are different types and different flows but for this implementation, it is enough.
I created basic 2 endpoints to implement this flow in the backend part.
$app->router->get('/2fa/qr-code', 'TwoFAController@printQRCode');
$app->router->post('/2fa/verify', 'TwoFAController@verify2FA');
QR-code endpoint basically prints a QR code image with proper HTPP headers, and I use it to scan from any device.
Verify endpoint is for verifying the given code from the user with a related security key. This endpoint just gets the code parameter, we store the secrets in the database and do not show them to the client.
We need to store secret keys, and we can store them in users tables or the user_settings table if you have them. It is totally up to you and your design.
If you decide to store it in the users table your SQL query is like this;
ALTER TABLE users ADD COLUMN secret varchar(32) DEFAULT NULL;
Note: To be compatible with Google Authenticator we need to store Base32 strings.
It is important to give you the option to disable or enable 2FA for your users. You can store a boolean in your DB for this option. Like named two_factor_enabled.
This is before enabling 2FA. Users need to scan QR and must enter the code to enable 2FA.
QR code generated by 2fa/qr-code endpoint on the fly.
After enabling this 2FA, it is asking to enter 6 digits verification code.