Creating a Login Form with Google Authentication (oAuth2) in PHP and JavaScript Tutorial

In this tutorial, we will tackle about how to create a web application Login Form with Google Authentication/ Google OAuth API. Here, you will learn how to set up a project and register the app in google console developer. Also, we will be creating a simple login form web application with the said login authentication. The scripts will be written in HTML, CSS, JavaScript, and PHP. In the application, the user credential will also be stored in the database using MySQL Database.

Let's Get Started!

Google Console Setup

First, we have to setup a project in the Google Console Developer to achieve our goal. Here, we will register our web application oAuth API. Follow the step below. Here is the the Google Console Developer link, https://console.developers.google.com/

Step 1: Create a New Project

Follow the step that you can in the image below.

Next,

Next, select your newly created project. After that you will be redirected to the Project's Dashboard. You will see an APIs Panel, click the Go to APIs overview. Then proceed to next step.

Step 2: Setup App OAuth

In your APIs & Services Page, navigate the page to the OAuth consent screen. Register your app API like.

Next, navigate the page to Credentials and proceed to the next step.

Step 3: Creating OAuth Client ID

In the Credential Page, create an OAuth Client ID. Refer to the images below on how to do it.

Next, copy the generated Client ID. We will use this in coding later.

Note: URI's fields in OAuth Client ID Form will not accept localhost. To setup Virtual Host using XAMPP, follow the configuration below.

XAMPP Virtual Host Configuration

Open your XAMPP's http-vhost.conf file. This file is located inside the C:\xampp\apache\conf\extra directory. Follow the changes below. Change the values according to you setup.

Next, check the virtual host if already uncommented just like below image. The file is located at C:\xampp\apache\conf\httpd.conf

Lastly, follow the below image host configuration to allow your local machine browse your localhost using your given Virtual Host's Server name.

Creating the Database

Open your XAMPP's Control Panel and start the Apache and MySQL. If you already started the said servers, please restart them to ensure that the changes of above configuration will be executed.

Open your XAMPP's PHPMyAdmin and create a new database naming glogin_db. Then navigate the page to the SQL Page and copy paste the SQL Script below to create the database table and columns.

  1. CREATE TABLE `user_list` (
  2. `access_token` text NOT NULL,
  3. `email` text NOT NULL,
  4. `password` text DEFAULT NULL,
  5. `firstname` text NOT NULL,
  6. `lastname` text NOT NULL,
  7. `image_path` text DEFAULT NULL,
  8. `oauth_login` tinyint(1) NOT NULL DEFAULT 0,
  9. `last_login` datetime DEFAULT NULL,

Let's do the Coding...

Creating the Database Connection

In your source code folder, create a new PHP File naming db_connect.php. Then copy and paste the following code.

  1. <?php
  2. $host = "localhost";
  3. $username = "root";
  4. $pw = "";
  5. $dbname = "glogin_db";
  6. $conn = new mysqli($host, $username, $pw, $dbname);
  7. if(!$conn){
  8. die('Cannot connect to the database. Error: '.$conn->error);
  9. }
  10. ?>

Creating the Interfaces

In this tutorial , I am using Bootstrap and jQuery. Kindly download it also in your end.

Creating the Custom Style Sheet

This script contains the scripts of the custom styles. This a CSS or Cascading Style Sheet File. Save this file as styles.css. In my cas this file is located inside the css directory.

  1. html,
  2. body {
  3. height: 100%;
  4. width: 100%;
  5. }
  6.  
  7. main {
  8. display: block;
  9. min-height: 100%;
  10. }
  11.  
  12. main * {
  13. font-family: Comic Sans MS;
  14. }
  15.  
  16. #project-title {
  17. padding: 2.5em 1em !important;
  18. text-shadow: 3px 3px 7px #000;
  19. }

Login Page

Create a new file in your source code folder naming index.php and copy the following script.

Important: kindly change the client ID in the google-signin-client_id meta in the header. This is located at the Line 7.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <meta charset="UTF-8">
  4. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta name="google-signin-client_id" content="526197692348-jeir3g34trr0utasmecj3doo4i8haagq.apps.googleusercontent.com">
  7. <title>Login with Google</title>
  8. <link rel="stylesheet" href="./font-awesome/css/all.min.css">
  9. <link rel="stylesheet" href="./css/bootstrap.min.css">
  10. <link rel="stylesheet" href="./css/styles.css">
  11. <script src="./font-awesome/js/all.min.js"></script>
  12. <script src="./js/jquery-3.6.0.min.js"></script>
  13. <script src="./js/bootstrap.min.js"></script>
  14. <script src="./js/script.js"></script>
  15. <script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
  16.  
  17. </head>
  18. <body class="bg-gradient bg-dark">
  19. <div class="conteiner">
  20. <h1 class="text-center my-2 text-light" id="project-title">Login Form with Google Authentication</h1>
  21. <div class="clear-fix py-3"></div>
  22. <div class="col-lg-12">
  23. <div class="row justify-content-center">
  24. <div class="col-lg-5 col-md-6 col-sm-12 col-sm-12">
  25. <div class="card shadow rounded-0">
  26. <div class="card-body">
  27. <form action="" id="login-form">
  28. <div class="form-group mb-3 ">
  29. <label for="email" class="control-label">Email</label>
  30. <div class="input-group rounded-0">
  31. <input type="email" name="email" required class="form-control rounded-0">
  32. <span class="input-group-text rounded-0"><i class="fa fa-user"></i></span>
  33. </div>
  34. </div>
  35. <div class="form-group mb-3 ">
  36. <label for="password" class="control-label">Password</label>
  37. <div class="input-group rounded-0">
  38. <input type="password" name="password" required class="form-control rounded-0">
  39. <span class="input-group-text rounded-0"><i class="fa fa-key"></i></span>
  40. </div>
  41. </div>
  42. <div class="form-group mb-3 text-end">
  43. <button class="btn btn-primary bg-gradient rounded-0">Login</button>
  44. </div>
  45. <hr>
  46. <center><small>Login with:</small></center>
  47. <div class="form-group mb-3 text-center">
  48. <center> <div id="gAuth-btn"></div></center>
  49. </div>
  50. </form>
  51. </div>
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. </body>
  58. </html>

Setting Up User's Password Page

Save the following script as set_password.php. This is the page where the new user set ups their password.

  1. <?php
  2. session_start();
  3. if(!isset($_SESSION['id'])){
  4. header('location:./');
  5. }
  6. if(isset($_SESSION['password']) && (!empty($_SESSION['password']) || !is_null($_SESSION['password']))){
  7. header('location:./home.php');
  8. }
  9. ?>
  10. <!DOCTYPE html>
  11. <html lang="en">
  12. <meta charset="UTF-8">
  13. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  14. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  15. <title>Login with Google</title>
  16. <link rel="stylesheet" href="./font-awesome/css/all.min.css">
  17. <link rel="stylesheet" href="./css/bootstrap.min.css">
  18. <link rel="stylesheet" href="./css/styles.css">
  19. <script src="./font-awesome/js/all.min.js"></script>
  20. <script src="./js/jquery-3.6.0.min.js"></script>
  21. <script src="./js/bootstrap.min.js"></script>
  22. <script src="./js/script.js"></script>
  23.  
  24. </head>
  25. <body class="bg-gradient bg-dark">
  26. <div class="conteiner">
  27. <h1 class="text-center my-2 text-light" id="project-title">Login Form with Google Authentication</h1>
  28. <div class="clear-fix py-3"></div>
  29. <div class="col-lg-12">
  30. <div class="row justify-content-center">
  31. <div class="col-lg-5 col-md-6 col-sm-12 col-sm-12">
  32. <div class="card shadow rounded-0">
  33. <div class="card-body">
  34. <form action="" id="update_password">
  35. <input type="hidden" name="id" value="<?= $_SESSION['id'] ?>">
  36. <div class="form-group mb-3 ">
  37. <label for="password" class="control-label">New Password</label>
  38. <div class="input-group rounded-0">
  39. <input type="password" name="password" id="password" required class="form-control rounded-0">
  40. <span class="input-group-text rounded-0"><i class="fa fa-key"></i></span>
  41. </div>
  42. </div>
  43. <div class="form-group mb-3 ">
  44. <label for="cpassword" class="control-label">Confirm New Password</label>
  45. <div class="input-group rounded-0">
  46. <input type="password" id="cpassword" required class="form-control rounded-0">
  47. <span class="input-group-text rounded-0"><i class="fa fa-key"></i></span>
  48. </div>
  49. </div>
  50. <div class="form-group mb-3 text-end">
  51. <button class="btn btn-primary bg-gradient rounded-0">Save</button>
  52. </div>
  53. </form>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. </body>
  61. </html>

Home Page

This is the page where the users will be redirected after login in the system. Save the file as home.php

  1. <pre>
  2. <?php
  3. session_start();
  4. if(!isset($_SESSION['id'])){
  5. header('location:./');
  6. }
  7. if(!isset($_SESSION['password']) || (isset($_SESSION['password']) && (empty($_SESSION['password']) || is_null($_SESSION['password'])))){
  8. header('location:./set_password.php');
  9. }
  10. ?>
  11. </pre>
  12. <!DOCTYPE html>
  13. <html lang="en">
  14. <meta charset="UTF-8">
  15. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  16. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  17. <title>Home - Login with Google</title>
  18. <link rel="stylesheet" href="./font-awesome/css/all.min.css">
  19. <link rel="stylesheet" href="./css/bootstrap.min.css">
  20. <link rel="stylesheet" href="./css/styles.css">
  21. <script src="./font-awesome/js/all.min.js"></script>
  22. <script src="./js/jquery-3.6.0.min.js"></script>
  23. <script src="./js/bootstrap.min.js"></script>
  24. <script src="./js/script.js"></script>
  25. </head>
  26. <body class="bg-gradient bg-dark">
  27. <div class="conteiner">
  28. <h1 class="text-center my-2 text-light" id="project-title">Welcome to XYZ Web Application</h1>
  29. <div class="clear-fix py-3"></div>
  30. <div class="col-lg-12">
  31. <div class="row justify-content-center">
  32. <div class="col-lg-5 col-md-6 col-sm-12 col-sm-12">
  33. <div class="card shadow rounded-0">
  34. <div class="card-body">
  35. <div class="d-flex w-100 mb-3">
  36. <div class="col-auto px-2 py-3">
  37. <center><img src="<?= isset($_SESSION['image_path']) ? $_SESSION['image_path'] : "" ?>" alt="" class="img-fluid bg-gradient bg-dark img-thumbnail" id="profilePicture"></center>
  38. </div>
  39. <div class="col-auto flex-shrink-1 flex-grow-1 px-2 py-3">
  40. <dl>
  41. <dt class="text-muted">Fullname</dt>
  42. <dd><?= (isset($_SESSION['firstname']) && isset($_SESSION['lastname'])) ? ucwords($_SESSION['firstname'] . " " .$_SESSION['lastname']) : "" ?></dd>
  43. <dt class="text-muted">Email</dt>
  44. <dd><?= (isset($_SESSION['firstname'])) ? $_SESSION['email'] : "" ?></dd>
  45. <dt class="text-muted">Google Authenticated Login</dt>
  46. <dd>
  47. <?php if(isset($_SESSION['oauth_login'])): ?>
  48. <?php if($_SESSION['oauth_login'] == 1): ?>
  49. <span class="badge bg-success rounded-pill">Yes</span>
  50. <?php else: ?>
  51. <span class="badge bg-danger rounded-pill">No</span>
  52. <?php endif; ?>
  53. <?php else: ?>
  54. <span class="badge badge-default border rounded-pill">N/A</span>
  55. <?php endif; ?>
  56. </dd>
  57. <dt class="text-muted">Last Login:</dt>
  58. <dd><?= (isset($_SESSION['last_login'])) ? date("M d, Y h:i A", strtotime($_SESSION['last_login'])) : "" ?></dd>
  59. </dl>
  60. </div>
  61. </div>
  62. <div class="text-end">
  63. <a class="btn btn-sm btn-danger bg-gradient rounded-0" href="./logout.php">Logout</a>
  64. </div>
  65. </div>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. </div>
  71. </body>
  72. </html>

Creating the JavaScript File

This is a JavaScript file that contains the scripts of the Google Sign Button, Form Submission scripts, etc. Save this file as script.js. In my case this file is located in side the js directory.

  1. var _googleUser = {};
  2.  
  3. function onSuccess(googleUser) {
  4. if (googleUser.isSignedIn()) {
  5. $('.err-msg').remove()
  6. var el = $('<div>')
  7. el.addClass("alert alert-danger err-msg");
  8. el.hide()
  9. var data = {
  10. access_token: googleUser.getAuthResponse().id_token,
  11. firstname: googleUser.getBasicProfile().getGivenName(),
  12. lastname: googleUser.getBasicProfile().getFamilyName(),
  13. email: googleUser.getBasicProfile().getEmail(),
  14. image_path: googleUser.getBasicProfile().getImageUrl(),
  15. }
  16. gapi.auth2.getAuthInstance().disconnect()
  17.  
  18. $.ajax({
  19. url: "./action.php?f=glogin",
  20. method: 'POST',
  21. data: data,
  22. dataType: 'json',
  23. error: err => {
  24. console.error(err)
  25. },
  26. success: function(resp) {
  27. if (resp.status == 'success') {
  28. location.replace("./home.php");
  29. } else if (!!resp.msg) {
  30. el.text(resp.msg)
  31. $('#login-form').prepend(el)
  32. el.show('slow')
  33. } else {
  34. el.text("An error occurred.")
  35. $('#login-form').prepend(el)
  36. el.show('slow')
  37. }
  38. }
  39. })
  40. }
  41. }
  42.  
  43. function onFailure(error) {
  44. console.log(error);
  45. }
  46.  
  47. function renderButton() {
  48. gapi.signin2.render('gAuth-btn', {
  49. 'scope': 'profile email',
  50. 'width': 240,
  51. 'height': 50,
  52. 'longtitle': true,
  53. 'theme': 'dark',
  54. 'onsuccess': onSuccess,
  55. 'onfailure': onFailure
  56. });
  57. }
  58. $(document).ready(function() {
  59. var auth2;
  60.  
  61. $('#update_password').submit(function(e) {
  62. e.preventDefault();
  63. var _this = $(this)
  64. $('.err-msg').remove()
  65. var el = $('<div>')
  66. el.addClass("alert alert-danger err-msg");
  67. el.hide()
  68. _this.find('button').attr('disabled', true)
  69. if ($('#password').val() != $('#cpassword').val()) {
  70. el.text('Password does not match')
  71. _this.prepend(el)
  72. el.show('slow')
  73. _this.find('button').attr('disabled', false)
  74. return false;
  75. }
  76.  
  77. $.ajax({
  78. url: "./action.php?f=update_password",
  79. method: 'POST',
  80. data: $(this).serialize(),
  81. dataType: 'json',
  82. error: err => {
  83. console.error(err)
  84. },
  85. success: function(resp) {
  86. if (resp.status == 'success') {
  87. alert("Password has been set.");
  88. location.replace("./home.php");
  89. } else if (!!resp.msg) {
  90. el.text(resp.msg)
  91. _this.prepend(el)
  92. el.show('slow')
  93. } else {
  94. el.text("An error occurred.")
  95. _this.prepend(el)
  96. el.show('slow')
  97. }
  98. _this.find('button').attr('disabled', false)
  99. }
  100. })
  101. })
  102. $('#login-form').submit(function(e) {
  103. e.preventDefault();
  104. var _this = $(this)
  105. $('.err-msg').remove()
  106. var el = $('<div>')
  107. el.addClass("alert alert-danger err-msg");
  108. el.hide()
  109. _this.find('button').attr('disabled', true)
  110. $.ajax({
  111. url: "./action.php?f=login",
  112. method: 'POST',
  113. data: $(this).serialize(),
  114. dataType: 'json',
  115. error: err => {
  116. console.error(err)
  117. },
  118. success: function(resp) {
  119. if (resp.status == 'success') {
  120. location.replace("./home.php");
  121. } else if (!!resp.msg) {
  122. el.text(resp.msg)
  123. _this.prepend(el)
  124. el.show('slow')
  125. } else {
  126. el.text("An error occurred.")
  127. _this.prepend(el)
  128. el.show('slow')
  129. }
  130. _this.find('button').attr('disabled', false)
  131. }
  132. })
  133. })
  134. })

Creating the PHP APIs

The following PHP Files contains the login, logout, and the update password scripts. Save the following files according to the given name above each scritps.

action.php
  1. <?php
  2. require_once('db_connect.php');
  3. if($_SERVER['REQUEST_METHOD'] != "POST" || !isset($_GET['f'])){
  4. echo '<script> alert("Unable to access the page."); location.reload();</script>';
  5. }
  6. $action = $_GET['f'];
  7. extract($_POST);
  8. if($action == "glogin"){
  9. $register_check = $conn->query("SELECT * FROM `user_list` where email = '{$email}' ");
  10. if($register_check->num_rows > 0){
  11. $get = $register_check->fetch_array();
  12. foreach($get as $k=> $v){
  13. if(!is_numeric($k)){
  14. $_SESSION[$k] = $v;
  15. }
  16. }
  17. $_SESSION['user_type'] = 'registered';
  18.  
  19. $resp['status'] = 'success';
  20. $data = " access_token = '{$access_token}'";
  21. $data .= ", oauth_login = 1";
  22. $data .= ", last_login = CURRENT_TIMESTAMP";
  23. $update = $conn->query("UPDATE `user_list` set {$data} where id = '{$get['id']}'");
  24. if($update){
  25. $_SESSION['oauth_login'] = 1;
  26. $_SESSION['access_token'] = $access_token;
  27. $_SESSION['last_login'] =date("Y-m-d H:i");
  28. }
  29. }else{
  30. $data= "";
  31. foreach($_POST as $k => $v){
  32. if(!empty($data)) $data .=", ";
  33. $data .= "`$k`='{$v}'";
  34. }
  35. $insert = $conn->query("INSERT INTO `user_list` set {$data} ");
  36. if($insert){
  37. $_SESSION['user_type'] = 'newly_registered';
  38. $resp['status'] = "success";
  39. $id = $conn->insert_id;
  40. $get = $conn->query("SELECT * FROM `user_list` where id = '{$id}' ")->fetch_array();
  41. foreach($get as $k=> $v){
  42. if(!is_numeric($k)){
  43. $_SESSION[$k] = $v;
  44. }
  45. }
  46. $data = " access_token = '{$access_token}'";
  47. $data .= ", oauth_login = 1";
  48. $data .= ", last_login = CURRENT_TIMESTAMP";
  49. $update = $conn->query("UPDATE `user_list` set {$data} where id = '$id'");
  50. if($update){
  51. $_SESSION['oauth_login'] = 1;
  52. $_SESSION['access_token'] = $access_token;
  53. $_SESSION['last_login'] =date("Y-m-d H:i");
  54. }
  55. }else{
  56. $resp['status'] = 'failed';
  57. $resp['msg'] = "An error occured while signing in.";
  58. $resp['error'] = $conn->error;
  59. }
  60. }
  61.  
  62. echo json_encode($resp);
  63. }
  64. if($action == 'update_password'){
  65. $password = password_hash($password, PASSWORD_DEFAULT);
  66. $update = $conn->query("UPDATE `user_list` set `password` = '{$password}' where id = '{$id}'");
  67. if($update){
  68. $resp['status'] = 'success';
  69. $_SESSION['password'] = $password;
  70. }else{
  71. $resp['status'] = 'failed';
  72. $resp['msg'] = "An error occurred";
  73. $resp['error'] = $conn->error;
  74. }
  75. echo json_encode($resp);
  76. }
  77. if($action == 'login'){
  78. $stmt = $conn->prepare("SELECT * FROM `user_list` where email = ?");
  79. $stmt->bind_param('s',$email);
  80. $stmt->execute();
  81. $result = $stmt->get_result();
  82. if($result->num_rows > 0){
  83. $get = $result->fetch_array();
  84. if(password_verify($password, $get['password'])){
  85. foreach($get as $k => $v){
  86. if(!is_numeric($k)){
  87. $_SESSION[$k] = $v;
  88. }
  89. }
  90. $data = " oauth_login = 0";
  91. $data .= ", last_login = CURRENT_TIMESTAMP";
  92. $update = $conn->query("UPDATE `user_list` set {$data} where id = '{$get['id']}'");
  93. if($update){
  94. $_SESSION['oauth_login'] = 0;
  95. $_SESSION['last_login'] =date("Y-m-d H:i");
  96. }
  97. $resp['status'] = 'success';
  98. }else{
  99. $resp['status'] = 'failed';
  100. $resp['msg'] = "Incorrect Password";
  101. }
  102. }else{
  103. $resp['status'] = 'failed';
  104. $resp['msg'] = "Incorrect Email or Password";
  105. }
  106. echo json_encode($resp);
  107. }
  108. ?>
logout.php
  1. <?php
  2. if(isset($_SESSION['id'])){
  3. }
  4. header('location:./');
  5. ?>

There you go. You can now test the application on your end. Check if it works like we planned to. You can also download the working source code I created for this tutorial. The download button is located below this article. Don't forget to change the Client ID in the index.php file.

That's it! i hope this Login Form with Google Authentication (OAuth) will help you with what you are looking for and you'll find it useful for your future PHP Projects..

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

Enjoy Coding :)

Comments

Submitted byFuyu (not verified)on Mon, 08/15/2022 - 17:37

I do not see the download link. Can you update it, please? Thank you so much!

Add new comment