Create an Email/Password Login System for Your Chrome Extension

An Object Is A
The Startup
Published in
5 min readAug 25, 2020

--

Create a basic login system using NodeJS, Express, and Javascript

This tutorial uses a boiler-plate Google Chrome Extension setup.

If you want to know how to get that setup,
Check out my write-up here:

Or the video tutorial here:

Let’s Begin.

We’ll start by creating our REST API.
A very basic Express server with two main routes, ‘/login’ and ‘/logout’.

We’ll need the express package of course.

>>npm init -y
>>npm install express

Note:
We’ve built an “authentication” middle ware function. It just simulates the act of looking up a user’s credentials on a database.
We won’t be creating an entire database for this lesson. Use SQL, MongoDb, whichever you like.

Let’s do some web development work before we get to actual Chrome Extension work.

We’ll create three pages.
A “Sign In” page, a “Sign Out” page, and a “Welcome Back” page. Nothing fancy.

Notice that we’ve attached scripts to each of our HTML pages.

Note:
A lot of this code is completely unnecessary. It’s just used to make the page look nice and animate.
The only code that matters in the scripts are the ‘click’ listeners for the buttons.

Now that we have the Web Dev portion out of the way, let’s take a look at our ‘manifest.json’.

{
"name": "basic email login system",
"description": "testing basic email login system",
"version": "0.1.0",
"manifest_version": 2,
"icons": {
"16": "./obj-16x16.png",
"32": "./obj-32x32.png",
"48": "./obj-48x48.png",
"128": "./obj-128x128.png"
},
"background": {
"scripts": ["./background.js"]
},
"options_page": "./options.html",
"browser_action": {
},
"permissions": [
"storage",
"http://localhost:3000/"
]
}

Note:
1. We need to “storage” permission so we can store user credentials and allow for persistence.
2. We need to put down our ‘localhost’ domain so our Chrome Extension can access the REST API.

Let’s do some actual Chrome Extension programming.

We’ll start by coding the basic skeletal logic flow of our app.

In the ‘popup-sign-in-script.js’, when the user clicks on the button, we’ll send a message to the ‘background’ script asking to “login”.
If we get a “success” from the ‘background’ we’ll change the page to the “Sign Out” page.

//...
if (email && password) {
// send message to background script with email and password
chrome.runtime.sendMessage({ message: 'login',
payload: { email, pass }},
function (response) {
if (response === 'success')
window.location.replace('./popup-sign-out.html');
}
});
} else {
//...

That’s it for the ‘popup-sign-in-script.js’. You can close the file.
The ‘popup-sign-out-script.js’ is almost identical.

In the ‘popup-sign-out-script.js’, when the user clicks on the button, we’ll send a message to the ‘background’ script asking to “logout”.
If we get a “success” from the ‘background’ we’ll change the page to the “Sign In” page.

button.addEventListener('click', () => {
chrome.runtime.sendMessage({ message: 'logout' },
function (response) {
if (response === 'success')
window.location.replace('./popup-sign-in.html');
}
});
});

This file is done. You can close it.

Our ‘popup-welcome-back-script.js’ ‘click’ listener is identical to our
Sign Out” script’s.
So we can copy and paste that logic.

button.addEventListener('click', () => {
chrome.runtime.sendMessage({ message: 'logout' },
function (response) {
if (response === 'success')
window.location.replace('./popup-sign-in.html');
}
});
});

Moving to the ‘background.js’ script, we create a variable to monitor the user’s status and a conditional tree that catches the messages from above.

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === 'login') {
flip_user_status(true, request.payload)
.then(res => sendResponse(res))
.catch(err => console.log(err));
return true;
} else if (request.message === 'logout') {
flip_user_status(false, null)
.then(res => sendResponse(res))
.catch(err => console.log(err));
return true;
}
});

Note:
We’re calling a function ‘flip_user_status()’. It changes the user status to ‘true’ (signed in) or ‘false’ (signed out). It returns a promise that resolves into a “success” or “fail”.

Let’s create that ‘flip_user_status()’ function.

If the user wants to sign in, we ping our ‘/login’ route from the REST API.
If the user is permitted, we’ll store their credentials on the local hard drive.

IMPORTANT: DO NOT STORE PASSWORDS IN PLAIN TEXT ANYWHERE.

For this video, we won’t be going into encryption.

If the user wants to sign out, we first get the user’s credentials, then ping our ‘/logout’ route from the REST API.
If the user’s credentials are authenticated, then we remove those credentials from the local storage.

Before we leave the background script, let’s add a function that tells us whether or not the user is signed in, create an ‘onMessage’ route
that sends back this status, and handle our browser icon being clicked.

function is_user_signed_in() {
return new Promise(resolve => {
chrome.storage.local.get(['userStatus', 'user_info'],
function (response) {
if (chrome.runtime.lastError) resolve({ userStatus:
false, user_info: {} })
resolve(response.userStatus === undefined ?
{ userStatus: false, user_info: {} } :
{ userStatus: response.userStatus, user_info:
response.user_info }
)
});
});
}
// add to the 'chrome.runtime.onMessage.addListener()' routes...
} else if (request.message === 'userStatus') {
is_user_signed_in()
.then(res => {
sendResponse({
message: 'success',
userStatus: user_info: res.user_info.email
});
})
.catch(err => console.log(err));
return true;
}
chrome.browserAction.onClicked.addListener(function () {
is_user_signed_in()
.then(res => {
if (res.userStatus) {
if (return_session) {
chrome.windows.create({
url: './popup-welcome-back.html',
width: 300,
height: 600,
focused: true
}, function () { return_session = false });
} else {
chrome.windows.create({
url: './popup-sign-out.html',
width: 300,
height: 600,
focused: true
});
}
} else {
chrome.windows.create({
url: './popup-sign-in.html',
width: 300,
height: 600,
focused: true
});
}
})
.catch(err => console.log(err));
});

Let’s bring this all together.

Finally, in our ‘popup-welcome-back-script.js’ we’ll just message our background script to tell us whether or not the user is signed in.

If they are returning to a session they didn’t sign out of, we’ll display a welcome message for them.

chrome.runtime.sendMessage({ message: 'userStatus' },
function (response) {
if (response.message === 'success') {
document.getElementById('name').innerText =
response.user_info;
}
}
});

We’re done.

Start the REST server with an “node app.js” and you’re good to go.

If you would like a more in-depth guide, check out my full video tutorial on YouTube, An Object Is A.

Be sure to follow us on Instagram and Twitter to keep up with our latest Web Development tutorials.

Create A Basic Login System for Your Google Chrome Extension

--

--