Skip to content

Web Development

How to Implement Google Authenticator 2FA Login in PHP

September 24, 2025 By @mritxperts 4 min read
Google Authenticator PHP PHP 2FA Login Two Factor Authentication in PHP Google Authenticator OTP PHP Secure PHP Login with 2FA PHP Login System with Google Authenticator

Passwords alone aren’t enough to keep your application secure. Attackers often crack or steal credentials, which is why Two-Factor Authentication (2FA) has become standard in modern applications.

In this tutorial, we’ll build a PHP login system with Google Authenticator that requires both a password and a one-time code from the user’s phone.


Prerequisites

  • PHP 7.4+ with MySQL/MariaDB
  • Composer installed
  • Basic understanding of PHP sessions and authentication

Step 1: Install Google Authenticator Library

Run this in your project folder:

composer require sonata-project/google-authenticator

Step 2: Database Setup

Create a table for storing users and their 2FA secret.

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(100) NOT NULL,
    password VARCHAR(255) NOT NULL,
    secret VARCHAR(255) DEFAULT NULL
);

Step 3: Registration with QR Code

When a user registers, generate a secret key and QR code.

<?php
// register.php
require 'vendor/autoload.php';
use Sonata\GoogleAuthenticator\GoogleAuthenticator;
use Sonata\GoogleAuthenticator\GoogleQrUrl;

$pdo = new PDO("mysql:host=localhost;dbname=yourdb", "root", "");

// Handle registration
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'];
    $password = password_hash($_POST['password'], PASSWORD_BCRYPT);

    $g = new GoogleAuthenticator();
    $secret = $g->generateSecret();

    $stmt = $pdo->prepare("INSERT INTO users (username, password, secret) VALUES (?, ?, ?)");
    $stmt->execute([$username, $password, $secret]);

    $qrCodeUrl = GoogleQrUrl::generate($username, $secret, 'MySecureApp');
}
?>
<!DOCTYPE html>
<html>
<head><title>Register</title></head>
<body>
<h2>Register</h2>
<form method="post">
    Username: <input type="text" name="username" required><br>
    Password: <input type="password" name="password" required><br>
    <button type="submit">Register</button>
</form>

<?php if (!empty($qrCodeUrl)): ?>
    <h3>Scan this QR Code in Google Authenticator</h3>
    <img src="<?= $qrCodeUrl ?>">
<?php endif; ?>
</body>
</html>

👉 After registration, users must scan the QR code in the Google Authenticator app.


Step 4: Login with Password + OTP

First, verify username/password. If correct, ask for OTP.

<?php
// login.php
require 'vendor/autoload.php';
session_start();

$pdo = new PDO("mysql:host=localhost;dbname=yourdb", "root", "");

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['username'])) {
    $username = $_POST['username'];
    $password = $_POST['password'];

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username=?");
    $stmt->execute([$username]);
    $user = $stmt->fetch();

    if ($user && password_verify($password, $user['password'])) {
        $_SESSION['pending_user'] = $user;
        header("Location: verify.php");
        exit;
    } else {
        echo "❌ Invalid username or password";
    }
}
?>
<!DOCTYPE html>
<html>
<head><title>Login</title></head>
<body>
<h2>Login</h2>
<form method="post">
    Username: <input type="text" name="username" required><br>
    Password: <input type="password" name="password" required><br>
    <button type="submit">Login</button>
</form>
</body>
</html>

Step 5: OTP Verification

<?php
// verify.php
require 'vendor/autoload.php';
use Sonata\GoogleAuthenticator\GoogleAuthenticator;
session_start();

if (!isset($_SESSION['pending_user'])) {
    header("Location: login.php");
    exit;
}

$user = $_SESSION['pending_user'];
$g = new GoogleAuthenticator();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $code = $_POST['otp_code'];
    if ($g->checkCode($user['secret'], $code)) {
        $_SESSION['authenticated'] = true;
        $_SESSION['username'] = $user['username'];
        unset($_SESSION['pending_user']);
        header("Location: dashboard.php");
        exit;
    } else {
        echo "❌ Invalid OTP, try again.";
    }
}
?>
<!DOCTYPE html>
<html>
<head><title>Verify OTP</title></head>
<body>
<h2>Enter 6-digit code from Google Authenticator</h2>
<form method="post">
    <input type="text" name="otp_code" required maxlength="6"><br>
    <button type="submit">Verify</button>
</form>
</body>
</html>

Step 6: Dashboard Page (Protected)

<?php
// dashboard.php
session_start();
if (!isset($_SESSION['authenticated'])) {
    header("Location: login.php");
    exit;
}
?>
<!DOCTYPE html>
<html>
<head><title>Dashboard</title></head>
<body>
<h2>Welcome, <?= htmlspecialchars($_SESSION['username']) ?> 🎉</h2>
<p>You are logged in with 2FA enabled!</p>
<a href="logout.php">Logout</a>
</body>
</html>

Step 7: Logout

<?php
// logout.php
session_start();
session_destroy();
header("Location: login.php");
exit;

Security Best Practices

  • Use HTTPS in production.
  • Store passwords with password_hash() and password_verify().
  • Protect against brute-force by limiting login attempts.
  • Provide backup codes or an option to disable 2FA via email verification in case the user loses their phone.

✅ Conclusion

We built a complete Google Authenticator 2FA login system in PHP:

  1. User registers → gets QR code.
  2. User logs in → enters username & password.
  3. User enters OTP from Google Authenticator.
  4. If correct, access is granted.

This simple setup greatly improves account security and can be integrated into any existing PHP application.

Tags

Share Article

Spread to your network