Creating a Login Form with OTP Verification through Email in PHP Tutorial

In this tutorial, I will show how to create a simple 2 Factor Authentication when logging in using PHP Language. This will help you to create a more secure authentication for your system users in your current or future PHP Projects. The system will generate an OTP or the One-Time-PIN every time the users attempt to login into the system. Here, the OTP will be through an email using GMail SMTP.

The application that we'll be crating in this tutorial has simple functionalities such registration, login, verification, home page, and logout. I hope this will help you.

Getting Started

Download and Install XAMPP as your virtual server in your local machine. Also, download Bootstrap and jQuery for the design of the application that we will be creating.

Setting-Up the XAMPP to send Mail

First, locate your XAMPP's php.ini file and open it with your favorite text editor such as notepad++ or sublime text. Next, in your text editor find the mail configuration by searching it using "[mail function]". Then, follow the configuration shown in the image below.

Next, setup the XAMPP's sendmail configuration. Locate and open the sendmail.ini file in your text editor. Then, follow the configuration shown in the image below.

Note: Use your gmail credential of the account you want use to send mail.

Allowing Less Secure Apps

Next, allow your gmail to be access by less secure apps so you can send mail locally using the app that we'll be creating. Follow the steps below.

Step 1

Open you google account's settings.

Step 2

Navigate the page into the 'security' and click the link on turning on less secure apps.

Step 3

Toggle to allow less secure apps.

Creating the Database

In your browser, browse the XAMPP's PHPMyAdmin [http://localhost/phpmyadmin] and create a new database naming login_otp_db. Next, navigate the page into the SQL Tab and copy/paste the mysql script below in the provided text field in the page. Then, click the 'GO'button.

  1. CREATE TABLE `users` (
  2. `firstname` text NOT NULL,
  3. `middlename` text DEFAULT NULL,
  4. `lastname` text NOT NULL,
  5. `email` text NOT NULL,
  6. `password` text NOT NULL,
  7. `otp` varchar(6) DEFAULT NULL,
  8. `otp_expiration` datetime DEFAULT NULL,

Creating the PHP Main Class

The application that we are creating will be using an OOP Approach in writing the back-end scripts of the app. The class includes the database configuration and send mail function. Save the code file below as MainClass.php.

  1. <?php
  2. if(session_status() === PHP_SESSION_NONE)
  3. Class MainClass{
  4. protected $db;
  5. function __construct(){
  6. $this->db = new mysqli('localhost','root','','login_otp_db');
  7. if(!$this->db){
  8. die("Database Connection Failed. Error: ".$this->db->error);
  9. }
  10. }
  11. function db_connect(){
  12. return $this->db;
  13. }
  14. public function register(){
  15. foreach($_POST as $k => $v){
  16. $$k = $this->db->real_escape_string($v);
  17. }
  18. $password = password_hash($password, PASSWORD_DEFAULT);
  19. $check = $this->db->query("SELECT * FROM `users` where `email`= '$email}' ")->num_rows;
  20. if($check > 0){
  21. $resp['status'] = 'failed';
  22. $_SESSION['flashdata']['type']='danger';
  23. $_SESSION['flashdata']['msg'] = ' Email already exists.';
  24. }else{
  25. $sql = "INSERT INTO `users` (firstname,middlename,lastname,email,`password`) VALUES ('$firstname','$middlename','$lastname','$email','$password')";
  26. $save = $this->db->query($sql);
  27. if($save){
  28. $resp['status'] = 'success';
  29. }else{
  30. $resp['status'] = 'failed';
  31. $resp['err'] = $this->db->error;
  32. $_SESSION['flashdata']['type']='danger';
  33. $_SESSION['flashdata']['msg'] = ' An error occurred.';
  34. }
  35. }
  36. return json_encode($resp);
  37. }
  38. public function login(){
  39. extract($_POST);
  40. $sql = "SELECT * FROM `users` where `email` = ? ";
  41. $stmt = $this->db->prepare($sql);
  42. $stmt->bind_param('s',$email);
  43. $stmt->execute();
  44. $result = $stmt->get_result();
  45. if($result->num_rows > 0){
  46. $data = $result->fetch_array();
  47. $pass_is_right = password_verify($password,$data['password']);
  48. $has_code = false;
  49. if($pass_is_right && (is_null($data['otp']) || (!is_null($data['otp']) && !is_null($data['otp_expiration']) && strtotime($data['otp_expiration']) < time()) ) ){
  50. $otp = sprintf("%'.06d",mt_rand(0,999999));
  51. $expiration = date("Y-m-d H:i" ,strtotime(date('Y-m-d H:i')." +1 mins"));
  52. $update_sql = "UPDATE `users` set otp_expiration = '{$expiration}', otp = '{$otp}' where id='{$data['id']}' ";
  53. $update_otp = $this->db->query($update_sql);
  54. if($update_otp){
  55. $has_code = true;
  56. $resp['status'] = 'success';
  57. $_SESSION['otp_verify_user_id'] = $data['id'];
  58. $this->send_mail($data['email'],$otp);
  59. }else{
  60. $resp['status'] = 'failed';
  61. $_SESSION['flashdata']['type'] = 'danger';
  62. $_SESSION['flashdata']['msg'] = ' An error occurred while loggin in. Please try again later.';
  63. }
  64.  
  65. }else if(!$pass_is_right){
  66. $resp['status'] = 'failed';
  67. $_SESSION['flashdata']['type'] = 'danger';
  68. $_SESSION['flashdata']['msg'] = ' Incorrect Password';
  69. }
  70. }else{
  71. $resp['status'] = 'failed';
  72. $_SESSION['flashdata']['type'] = 'danger';
  73. $_SESSION['flashdata']['msg'] = ' Email is not registered.';
  74. }
  75. return json_encode($resp);
  76. }
  77. public function get_user_data($id){
  78. extract($_POST);
  79. $sql = "SELECT * FROM `users` where `id` = ? ";
  80. $stmt = $this->db->prepare($sql);
  81. $stmt->bind_param('i',$id);
  82. $stmt->execute();
  83. $result = $stmt->get_result();
  84. $dat=[];
  85. if($result->num_rows > 0){
  86. $resp['status'] = 'success';
  87. foreach($result->fetch_array() as $k => $v){
  88. if(!is_numeric($k)){
  89. $data[$k] = $v;
  90. }
  91. }
  92. $resp['data'] = $data;
  93. }else{
  94. $resp['status'] = 'false';
  95. }
  96. return json_encode($resp);
  97. }
  98. public function resend_otp($id){
  99. $otp = sprintf("%'.06d",mt_rand(0,999999));
  100. $expiration = date("Y-m-d H:i" ,strtotime(date('Y-m-d H:i')." +1 mins"));
  101. $update_sql = "UPDATE `users` set otp_expiration = '{$expiration}', otp = '{$otp}' where id = '{$id}' ";
  102. $update_otp = $this->db->query($update_sql);
  103. if($update_otp){
  104. $resp['status'] = 'success';
  105. $email = $this->db->query("SELECT email FROM `users` where id = '{$id}'")->fetch_array()[0];
  106. $this->send_mail($email,$otp);
  107. }else{
  108. $resp['status'] = 'failed';
  109. $resp['error'] = $this->db->error;
  110. }
  111. return json_encode($resp);
  112. }
  113. public function otp_verify(){
  114. extract($_POST);
  115. $sql = "SELECT * FROM `users` where id = ? and otp = ?";
  116. $stmt = $this->db->prepare($sql);
  117. $stmt->bind_param('is',$id,$otp);
  118. $stmt->execute();
  119. $result = $stmt->get_result();
  120. if($result->num_rows > 0){
  121. $resp['status'] = 'success';
  122. $this->db->query("UPDATE `users` set otp = NULL, otp_expiration = NULL where id = '{$id}'");
  123. $_SESSION['user_login'] = 1;
  124. foreach($result->fetch_array() as $k => $v){
  125. if(!is_numeric($k))
  126. $_SESSION[$k] = $v;
  127. }
  128. }else{
  129. $resp['status'] = 'failed';
  130. $_SESSION['flashdata']['type'] = 'danger';
  131. $_SESSION['flashdata']['msg'] = ' Incorrect OTP.';
  132. }
  133. return json_encode($resp);
  134. }
  135. function send_mail($to="",$pin=""){
  136. if(!empty($to)){
  137. try{
  138. $email = '[email protected]';
  139. $headers = 'From:' .$email . '\r\n'. 'Reply-To:' .
  140. $email. "\r\n" .
  141. 'X-Mailer: PHP/' . phpversion()."\r\n";
  142. $headers .= "MIME-Version: 1.0" . "\r\n";
  143. $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
  144. // the message
  145. $msg = "
  146. <html>
  147. <body>
  148. <h2>You are Attempting to Login in XYZ Simple PHP Web Application</h2>
  149. <p>Here is yout OTP (One-Time PIN) to verify your Identity.</p>
  150. <h3><b>".$pin."</b></h3>
  151. </body>
  152. </html>
  153. ";
  154.  
  155. // send email
  156. mail($to,"OTP",$msg,$headers);
  157. // die("ERROR<br>".$headers."<br>".$msg);
  158.  
  159. }catch(Exception $e){
  160. $_SESSION['flashdata']['type']='danger';
  161. $_SESSION['flashdata']['msg'] = ' An error occurred while sending the OTP. Error: '.$e->getMessage();
  162. }
  163. }
  164. }
  165. function __destruct(){
  166. $this->db->close();
  167. }
  168. }
  169. $class = new MainClass();
  170. $conn= $class->db_connect();

Creating the System Authentication Check Script

The code below is a PHP Script that checks if the user is allowed to access the application page. This will make the user to redirect to the login page if they haven't logged in yet. Save the file as auth.php.

  1. <?php
  2. if(session_status() === PHP_SESSION_NONE)
  3. $link = $_SERVER['PHP_SELF'];
  4. if(!strpos($link,'login.php') && !strpos($link,'login_verification.php') && !strpos($link,'registration.php') && !isset($_SESSION['user_login'])){
  5. echo "<script>location.replace('./login.php');</script>";
  6. }
  7. if(strpos($link,'login_verification.php') && !isset($_SESSION['otp_verify_user_id'])){
  8. echo "<script>location.replace('./login.php');</script>";
  9. }
  10. if(strpos($link,'login.php') > -1 && isset($_SESSION['user_login'])){
  11. echo "<script>location.replace('./');</script>";
  12. }

Creating the Interfaces

Next, create the login page of the application. Copy/Paste the code below and configure it the way you want the UI looks. Save the file as login.php.

  1. <?php
  2. require_once('auth.php');
  3. require_once('MainClass.php');
  4. if($_SERVER['REQUEST_METHOD'] == 'POST'){
  5. $login = json_decode($class->login());
  6. if($login->status == 'success'){
  7. echo "<script>location.replace('./login_verification.php');</script>";
  8. }
  9. }
  10. ?>
  11. <!DOCTYPE html>
  12. <html lang="en">
  13. <meta charset="UTF-8">
  14. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  15. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  16. <title>Login with OTP</title>
  17. <link rel="stylesheet" href="./Font-Awesome-master/css/all.min.css">
  18. <link rel="stylesheet" href="./css/bootstrap.min.css">
  19. <script src="./js/jquery-3.6.0.min.js"></script>
  20. <script src="./js/popper.min.js"></script>
  21. <script src="./js/bootstrap.min.js"></script>
  22. <script src="./Font-Awesome-master/js/all.min.js"></script>
  23. html,body{
  24. height:100%;
  25. width:100%;
  26. }
  27. main{
  28. height:calc(100%);
  29. width:calc(100%);
  30. display:flex;
  31. flex-direction:column;
  32. align-items:center;
  33. justify-content:center;
  34. }
  35. </style>
  36. </head>
  37. <body class="bg-dark bg-gradient">
  38. <main>
  39. <div class="col-lg-7 col-md-9 col-sm-12 col-xs-12 mb-4">
  40. <h1 class="text-light text-center">XYZ Simple PHP Web Application</h1>
  41. </div>
  42. <div class="col-lg-3 col-md-8 col-sm-12 col-xs-12">
  43. <div class="card shadow rounded-0">
  44. <div class="card-header py-1">
  45. <h4 class="card-title text-center">LOGIN</h4>
  46. </div>
  47. <div class="card-body py-4">
  48. <div class="container-fluid">
  49. <form action="./login.php" method="POST">
  50. <?php
  51. if(isset($_SESSION['flashdata'])):
  52. ?>
  53. <div class="dynamic_alert alert alert-<?php echo $_SESSION['flashdata']['type'] ?> my-2 rounded-0">
  54. <div class="d-flex align-items-center">
  55. <div class="col-11"><?php echo $_SESSION['flashdata']['msg'] ?></div>
  56. <div class="col-1 text-end">
  57. <div class="float-end"><a href="javascript:void(0)" class="text-dark text-decoration-none" onclick="$(this).closest('.dynamic_alert').hide('slow').remove()">x</a>
  58. </div>
  59. </div>
  60. </div>
  61. </div>
  62. <?php unset($_SESSION['flashdata']) ?>
  63. <?php endif; ?>
  64. <div class="form-group">
  65. <label for="email" class="label-control">Email</label>
  66. <input type="email" name="email" id="email" class="form-control rounded-0" value="<?= isset($_POST['email']) ? $_POST['email'] : '' ?>" autofocus required>
  67. </div>
  68. <div class="form-group">
  69. <label for="password" class="label-control">Password</label>
  70. <input type="password" name="password" id="password" class="form-control rounded-0" value="<?= isset($_POST['password']) ? $_POST['password'] : '' ?>" required>
  71. </div>
  72. <div class="clear-fix mb-4"></div>
  73. <div class="form-group text-end">
  74. <button class="btn btn-primary bg-gradient rounded-0">LOGIN</button>
  75. </div>
  76. <div class="form-group text-cneter">
  77. <a href="registration.php">Create a New Account</a>
  78. </div>
  79. </form>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. </main>
  85. </body>
  86. </html>

Output

Next, create the registration page of the application. Copy/Paste the code below and configure it the way you want the UI looks. Save the file as registration.php.

  1. <?php
  2. require_once('auth.php');
  3. require_once('MainClass.php');
  4. if($_SERVER['REQUEST_METHOD'] == 'POST'){
  5. $register = json_decode($class->register());
  6. if($register->status == 'success'){
  7. $_SESSION['flashdata']['type']='success';
  8. $_SESSION['flashdata']['msg'] = ' Account has been registered successfully.';
  9. echo "<script>location.href = './login_verification.php';</script>";
  10. exit;
  11. }else{
  12. echo "<script>console.error(".json_encode($register).");</script>";
  13. }
  14. }
  15. ?>
  16. <!DOCTYPE html>
  17. <html lang="en">
  18. <meta charset="UTF-8">
  19. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  20. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  21. <title>Login with OTP</title>
  22. <link rel="stylesheet" href="./Font-Awesome-master/css/all.min.css">
  23. <link rel="stylesheet" href="./css/bootstrap.min.css">
  24. <script src="./js/jquery-3.6.0.min.js"></script>
  25. <script src="./js/popper.min.js"></script>
  26. <script src="./js/bootstrap.min.js"></script>
  27. <script src="./Font-Awesome-master/js/all.min.js"></script>
  28. html,body{
  29. height:100%;
  30. width:100%;
  31. }
  32. main{
  33. height:calc(100%);
  34. width:calc(100%);
  35. display:flex;
  36. flex-direction:column;
  37. align-items:center;
  38. justify-content:center;
  39. }
  40. </style>
  41. </head>
  42. <body class="bg-dark bg-gradient">
  43. <main>
  44. <div class="col-lg-7 col-md-9 col-sm-12 col-xs-12 mb-4">
  45. <h1 class="text-light text-center">XYZ Simple PHP Web Application</h1>
  46. </div>
  47. <div class="col-lg-3 col-md-8 col-sm-12 col-xs-12">
  48. <div class="card shadow rounded-0">
  49. <div class="card-header py-1">
  50. <h4 class="card-title text-center">Create an Account</h4>
  51. </div>
  52. <div class="card-body py-4">
  53. <div class="container-fluid">
  54. <form action="./registration.php" method="POST">
  55. <?php
  56. if(isset($_SESSION['flashdata'])):
  57. ?>
  58. <div class="dynamic_alert alert alert-<?php echo $_SESSION['flashdata']['type'] ?> my-2 rounded-0">
  59. <div class="d-flex align-items-center">
  60. <div class="col-11"><?php echo $_SESSION['flashdata']['msg'] ?></div>
  61. <div class="col-1 text-end">
  62. <div class="float-end"><a href="javascript:void(0)" class="text-dark text-decoration-none" onclick="$(this).closest('.dynamic_alert').hide('slow').remove()">x</a>
  63. </div>
  64. </div>
  65. </div>
  66. </div>
  67. <?php unset($_SESSION['flashdata']) ?>
  68. <?php endif; ?>
  69. <div class="form-group">
  70. <label for="firstname" class="label-control">First Name</label>
  71. <input type="text" name="firstname" id="firstname" class="form-control rounded-0" value="<?= isset($_POST['firstname']) ? $_POST['firstname'] : '' ?>" autofocus required>
  72. </div>
  73. <div class="form-group">
  74. <label for="middlename" class="label-control">Middle Name</label>
  75. <input type="text" name="middlename" id="middlename" class="form-control rounded-0" value="<?= isset($_POST['middlename']) ? $_POST['middlename'] : '' ?>" required>
  76. </div>
  77. <div class="form-group">
  78. <label for="lastname" class="label-control">Last Name</label>
  79. <input type="text" name="lastname" id="lastname" class="form-control rounded-0" value="<?= isset($_POST['lastname']) ? $_POST['lastname'] : '' ?>" required>
  80. </div>
  81. <div class="form-group">
  82. <label for="email" class="label-control">Email</label>
  83. <input type="email" name="email" id="email" class="form-control rounded-0" value="<?= isset($_POST['email']) ? $_POST['email'] : '' ?>" required>
  84. </div>
  85. <div class="form-group">
  86. <label for="password" class="label-control">Password</label>
  87. <input type="password" name="password" id="password" class="form-control rounded-0" value="<?= isset($_POST['password']) ? $_POST['password'] : '' ?>" required>
  88. </div>
  89. <div class="clear-fix mb-4"></div>
  90. <div class="form-group text-end">
  91. <button class="btn btn-primary bg-gradient rounded-0">Create Account</button>
  92. </div>
  93. </form>
  94. </div>
  95. </div>
  96. </div>
  97. </div>
  98. </main>
  99. </body>
  100. </html>

Output

Next, create the verification page of the application. This page will the one where the user will be redirected after successfully login the correct registered user credentials. This is where user will submit the OTP to confirm his/her identity. Copy/Paste the code below and configure it the way you want the UI looks. Save the file as login_verification.php.

  1. <?php
  2. require_once('auth.php');
  3. require_once('MainClass.php');
  4. $user_data = json_decode($class->get_user_data($_SESSION['otp_verify_user_id']));
  5. if($user_data->status){
  6. foreach($user_data->data as $k => $v){
  7. $$k = $v;
  8. }
  9. }
  10. if(isset($_GET['resend']) && $_GET['resend'] == 'true'){
  11. $resend = json_decode($class->resend_otp($_SESSION['otp_verify_user_id']));
  12. if($resend->status == 'success'){
  13. echo "<script>location.replace('./login_verification.php')</script>";
  14. }else{
  15. $_SESSION['flashdata']['type']='danger';
  16. $_SESSION['flashdata']['msg']=' Resending OTP has failed.';
  17. echo "<script>console.error(".$resend.")</script>";
  18. }
  19. }
  20. if($_SERVER['REQUEST_METHOD'] == 'POST'){
  21. $verify = json_decode($class->otp_verify());
  22. if($verify->status == 'success'){
  23. echo "<script>location.replace('./');</script>";
  24. }
  25. }
  26. ?>
  27. <!DOCTYPE html>
  28. <html lang="en">
  29. <meta charset="UTF-8">
  30. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  31. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  32. <title>Login with OTP</title>
  33. <link rel="stylesheet" href="./Font-Awesome-master/css/all.min.css">
  34. <link rel="stylesheet" href="./css/bootstrap.min.css">
  35. <script src="./js/jquery-3.6.0.min.js"></script>
  36. <script src="./js/popper.min.js"></script>
  37. <script src="./js/bootstrap.min.js"></script>
  38. <script src="./Font-Awesome-master/js/all.min.js"></script>
  39. html,body{
  40. height:100%;
  41. width:100%;
  42. }
  43. main{
  44. height:calc(100%);
  45. width:calc(100%);
  46. display:flex;
  47. flex-direction:column;
  48. align-items:center;
  49. justify-content:center;
  50. }
  51. a.disabled {
  52. pointer-events: none;
  53. cursor: default;
  54. }
  55. </style>
  56. </head>
  57. <body class="bg-dark bg-gradient">
  58. <main>
  59. <div class="col-lg-7 col-md-9 col-sm-12 col-xs-12 mb-4">
  60. <h1 class="text-light text-center">XYZ Simple PHP Web Application</h1>
  61. </div>
  62. <div class="col-lg-3 col-md-8 col-sm-12 col-xs-12">
  63. <div class="card shadow rounded-0">
  64. <div class="card-header py-1">
  65. <h4 class="card-title text-center">LOGIN - Verification</h4>
  66. </div>
  67. <div class="card-body py-4">
  68. <div class="container-fluid">
  69. <form action="./login_verification.php" method="POST">
  70. <input type="hidden" name="id" value="<?= isset($id) ? $id : '' ?>">
  71. <?php
  72. if(isset($_SESSION['flashdata'])):
  73. ?>
  74. <div class="dynamic_alert alert alert-<?php echo $_SESSION['flashdata']['type'] ?> my-2 rounded-0">
  75. <div class="d-flex align-items-center">
  76. <div class="col-11"><?php echo $_SESSION['flashdata']['msg'] ?></div>
  77. <div class="col-1 text-end">
  78. <div class="float-end"><a href="javascript:void(0)" class="text-dark text-decoration-none" onclick="$(this).closest('.dynamic_alert').hide('slow').remove()">x</a>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. <?php unset($_SESSION['flashdata']) ?>
  84. <?php endif; ?>
  85. <div class="form-group">
  86. <p class="">We have sent an OPT in your Email [<?= isset($email) ? $email : '' ?>].</p>
  87. </div>
  88. <div class="form-group">
  89. <label for="otp" class="label-control">Please Enter the OTP</label>
  90. <input type="otp" name="otp" id="otp" class="form-control rounded-0" value="" maxlength="6" pattern="{0-9}+" autofocus required>
  91. </div>
  92. <div class="clear-fix mb-4"></div>
  93. <div class="form-group text-end">
  94. <a class="btn btn-secondary bg-gradient rounded-0 <?= time() < strtotime($otp_expiration) ? 'disabled' : '' ?>" data-stat="<?= time() < strtotime($otp_expiration) ? 'countdown' : '' ?>" href="./login_verification.php?resend=true" id="resend"><?= time() < strtotime($otp_expiration) ? 'Resend in '.(strtotime($otp_expiration) - time()).'s' : 'Resend OTP' ?></a>
  95. <button class="btn btn-primary bg-gradient rounded-0">Confirm</button>
  96. </div>
  97. </form>
  98. </div>
  99. </div>
  100. </div>
  101. </div>
  102. </main>
  103. </body>
  104. $(function(){
  105. var is_countdown_resend = $('#resend').attr('data-stat') == 'countdown';
  106. if(is_countdown_resend){
  107. var sec = '<?= time() < strtotime($otp_expiration) ? (strtotime($otp_expiration) - time()) : 0 ?>';
  108. var countdown = setInterval(() => {
  109. if(sec > 0){
  110. sec--;
  111. $('#resend').text("Resend in "+(sec)+'s')
  112. }else{
  113. $('#resend').attr('data-stat','')
  114. .removeClass('disabled').text('Resend OTP')
  115. clearInterval(countdown)
  116. }
  117. }, 1000);
  118. }
  119. })
  120. </html>

Output

Next, create the index page of the application where the user will be redirected after the successful 2 Factor Authentication. Copy/Paste the code below and configure it the way you want the UI looks. Save the file as index.php.

  1. <?php
  2. require_once('auth.php');
  3. require_once('MainClass.php');
  4. ?>
  5. <!DOCTYPE html>
  6. <html lang="en">
  7. <meta charset="UTF-8">
  8. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  10. <title> Home | Login with OTP</title>
  11. <link rel="stylesheet" href="./Font-Awesome-master/css/all.min.css">
  12. <link rel="stylesheet" href="./css/bootstrap.min.css">
  13. <script src="./js/jquery-3.6.0.min.js"></script>
  14. <script src="./js/popper.min.js"></script>
  15. <script src="./js/bootstrap.min.js"></script>
  16. <script src="./Font-Awesome-master/js/all.min.js"></script>
  17. html,body{
  18. height:100%;
  19. width:100%;
  20. }
  21. main{
  22. height:100%;
  23. display:flex;
  24. flex-flow:column;
  25. }
  26. </style>
  27. </head>
  28. <main>
  29. <nav class="navbar navbar-expand-lg navbar-dark bg-dark bg-gradient" id="topNavBar">
  30. <div class="container">
  31. <a class="navbar-brand" href="#">
  32. XYZ Simple PHP Web Application
  33. </a>
  34. </div>
  35. </nav>
  36. <div class="container py-3" id="page-container">
  37. <div class="row justify-content-center">
  38. <div class="col-lg-5 col-md-8 col-sm-12 col-xs-12">
  39. <div class="card shadow rounded-0">
  40. <div class="card-body py-4">
  41. <h1>Welcome <?= ucwords($_SESSION['firstname'].' '.$_SESSION['middlename'].' '.$_SESSION['lastname']) ?></h1>
  42. <hr>
  43. <p>You are logged in using <?= $_SESSION['email'] ?></p>
  44. <div class="clear-fix mb-4"></div>
  45. <div class="text-end">
  46. <a href="./logout.php" class="btn btn btn-secondary bg-gradient rounded-0">Logout</a>
  47. </div>
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. </div>
  53. </main>
  54. </body>
  55. </html>

Output

Here's the Sample Snapshot of the OTP Mail

DEMO VIDEO

There you go. You can now test the application on your end and check if it is working properly and achieves the goal I stated above. If there's an error occurred on your end, review your codes with the codes I provided above. You can also download the source code I created for this tutorial. The download link/button is located after this article.

That ends this tutorial. I hope this will help you with what you are looking for and you'll find it useful with your current or future projects.

Explore more on this website for more Tutorials and Free Source Codes.

Related Links:

Happy Coding :)

Comments

Submitted bySome Random Guy (not verified)on Thu, 12/01/2022 - 21:21

Yow bro, upon check your code I found a possible typo in 'MainClass.php' in line 20 where the '$email}' in the query should not have a closing curly bracket. This probably will bypass the checking of existing email.
Submitted byuknown (not verified)on Sun, 01/22/2023 - 00:10

not getting any emails cuz cant turn on the secured etc on google account

Add new comment