Create a Picture Competition Website in Express JS, MEVN

Sign-in with Google

You should let users sign in quickly with Google. It will be just a one-tap sign-in. It will be easy for users to signup because nowadays almost every day have their Gmail logged in all the time. To enable Google sign-in in your website, first, you need to add a meta tag in your “header.ejs”:

<meta name="google-signin-client_id" content="your_client_id" />

You can get your Google sign-in client ID by following this tutorial. Then in your “footer.ejs” include this file:

<script src="https://apis.google.com/js/platform.js" async defer></script>

After that, in “login.ejs” we need to create a button where we will render the Google sign-in.

<div class="row">
	<div class="col-md-6">
		<div class="g-signin2" data-onsuccess="onSignIn" onclick="googleSigninClick();" style="margin-top: 10px;"></div>
	</div>

    [facebook login button]
</div>

Now initialize the library using the following JS code:

<script>
	var googleSigninClicked = false;

	function googleSigninClick() {
	    googleSigninClicked = true;
	}

	function googleLogin(id_token) {
		var formData = new FormData();
		formData.append("id_token", id_token);

		myApp.callAjax(mainURL + "/googleLogin", formData, function (response) {
            // convert the JSON string into Javascript object
            var response = JSON.parse(response);
            // console.log(response);

            // if the user is created, then redirect to login
            if (response.status == "success") {
            	// get access token from server
                var accessToken = response.accessToken;

                // save in local storage
                localStorage.setItem(accessTokenKey, accessToken);

                // redirect to home page
                window.location.href = "/";
            } else {
            	swal("Error", response.message, "error");
            }
		});
	}

	function onSignIn (googleUser) {
		if (!googleSigninClicked) {
			return false;
		}
		googleSigninClicked = false;

		var profile = googleUser.getBasicProfile();
		var id_token = googleUser.getAuthResponse().id_token;

		console.log(id_token);

		// Do not send to your backend! Use an ID token instead.
		console.log('ID: ' + profile.getId());

		console.log('Name: ' + profile.getName());
		console.log('Image URL: ' + profile.getImageUrl());

		// This is null if the 'email' scope is not present.
		console.log('Email: ' + profile.getEmail());

		googleLogin(id_token);
	}
</script>

We have created a separate function for googleLogin(id_token) because we will need that later in this tutorial. When the user is logged in with his Gmail, we need to store it in Mongo DB and also we need to authenticate it on the server-side as well.

On the server-side, we first need to install the Google OAuth library which you can install by running the following command in your terminal:

npm install google-auth-library

Then include the following lines at the top of your “server.js”:

const GOOGLE_AUTH_CLIENT_ID = "your_google_client_id";

const {OAuth2Client} = require('google-auth-library');
const googleAuthClient = new OAuth2Client(GOOGLE_AUTH_CLIENT_ID);

Then create a POST route to authenticate the user and save his data in Mongo DB.

app.post("/googleLogin", async function (request, result) {
	const idToken = request.fields.id_token;

	const ticket = await googleAuthClient.verifyIdToken({
		idToken: idToken,
		audience: GOOGLE_AUTH_CLIENT_ID
	});
	const payload = ticket.getPayload();
	const userid = payload['sub'];
	const name = payload["name"];
	const picture = payload["picture"];
	const email = payload["email"];

	// check if email already exists
    var user = await db.collection("users").findOne({
        "email": email
    });

    if (user == null) {
    	// insert in database
        await db.collection("users").insertOne({
            "name": name,
            "email": email,
            "password": "",
            "picture": picture,
            "accessToken": "",
            "notifications": [],
            "bio": "",
            "dob": "",
            "country": "",
            "phone": "",
            "website": "",
            "twitter": "",
            "facebook": "",
            "googlePlus": "",
            "linkedIn": "",
            "instagram": "",
            "resetToken": "",
            "isVerified": true,
            "verificationToken": "",
            "createdAt": new Date().getTime()
        });
    }

    // generate JWT of user
    var accessToken = jwt.sign({
        "email": email
    }, accessTokenSecret);

    // update JWT token in database
    await db.collection("users").findOneAndUpdate({
        "email": email
    }, {
        $set: {
            "accessToken": accessToken,
            "google": {
            	"userid": userid,
            	"name": name,
            	"email": email,
            	"picture": picture
            }
        }
    });

	result.json({
        "status": "success",
        "message": "Login successfully",
        "accessToken": accessToken
    });
});

Now users will be able to log in to the website using their Google account.