Posts from the “Web Development” Category

Secure Gmail Access with OAuth2 and 2LO in Express Backend

Scenario

Use Express backend to send email from a gmail account.

Approach

Use nodemailer to send email with OAuth2 for obtaining access token, during which “two-legged OAuth” (2LO) is used for signature, which directly obtain the access token without manual user consent.

Prerequisites

  • A gmail account belonging to a G Suite Domain. We’ll configure the gmail account for 2LO and use it to send emails in the Express backend
  • A google project used to keep the service account we’ll create. The google project doesn’t necessarily the node project we’re talking about. The main purpose of creating a google project is to use it create a service account

Libraries

  • “googleapis” for handling authentication and authorization using JWT [1]
  • “nodemailer” for sending email using the gmail account [2]

Steps

  • Create service account [7]
    • Select the google project demonstrated in the “Prerequisites” section during creating service account
    • Select “Service Account Token Creator” as the role for the service account as we’re using the service account to generate auth tokens
  • Authorize domain-wide authorization to the service account. The G Suite Account used in domain-wide authorization contains the gmail used to send email from Express backend [8]
  • Preparing to make an authorized API call with Google API Client Libraries:
    • Instruction: prepare to make an authorized API call [2]
    • Google API NodeJS Client Repo [1]
  • Send email from the gmail account with the created service account and access token obtained in the previous step
    • explanation of 2LO in nodemailer [3]
    • instruction of using access token [4]
    • example of using access token [5]
    • here’s a full example of NodeJS code of sending email with OAuth2 and 2LO:

send_email_oauth2_2ol

References

[1] Google API NodeJS Client. https://github.com/google/google-api-nodejs-client

[2] Preparing to Make an Authorized API Call. https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests

[3] Explanation of Two-Legged OAuth (2LO) in nodemailer. http://nodemailer.com/smtp/oauth2/#oauth-2lo

[4] Using access token for HTTP request. “HTTP/REST” section of https://developers.google.com/identity/protocols/OAuth2ServiceAccount#callinganapi

[5] Example of using access token in nodemailer. http://nodemailer.com/smtp/oauth2/#oauth-2lo

[6] Nodemailer. https://nodemailer.com/about/

[7] Create Service Account in Google. https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount

[8] Authorize domain-wide authorization to the service account. The G Suite Account used in domain-wide authorization contains the gmail used to send email from Express backend. https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority

Case Study: Debug HTTP ERROR 500 of Azure Web App Which Works Locally

The purpose of this blog is to record the turning points of fixing a crashed web app on Azure, which works locally.

Background

The web app is built with ExpressJS as the backend, sequelize as the ORM, Azure PostgreSQL as the database, React and Redux as frontend. It’s hosted on Azure.

Problem

The web app runs on local browser, but crashes on Azure after it’s deployed. The broken website on Azure shows “HTTP ERROR 500”.

Turning Points

  • Azure log stream

Log stream printed out a detailed error when the deployed web app is browsed from azure portal: “TypeError: Cannot read property ‘use_env_variable’ of undefined”. This error happens on the first line of the following code block on model/index.js:

if (config.use_env_variable) {
var sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
var sequelize = new Sequelize(config.database, config.username, config.password, config);
}

  • Debug var values with console.log

The real issue was unveiled by seeing different value of the same var `env` when assessing var values related to “config” in the import-header section:

var env = process.env.NODE_ENV || ‘development’;
var configFile = require(__dirname + ‘/../config/config.json’);
var config = configFile[env];
var db = {};

console.log(“[DEBUGGING] __dirname”, __dirname);
console.log(“[DEBUGGING] configFile: “, configFile);
console.log(“[DEBUGGING] env: “, env);
console.log(“[DEBUGGING] config: “, config);

Specifically, `var` is `development` on local machine, but is `production` on Azure. Whereas the config.json file specifying database configuration doesn’t have the `production` key.

Thoughts

Looking back, I realize the key to fix the “HTTP ERROR 500” error of the Azure web app is precisely identifying the problem. That means, I needed to figure out on which line of code and which vars didn’t work as expected. This statement holds firmly because that’s the nature of an application wrote by a programming language.

Then, what’s the most effective way of precisely identifying the problem? Turns out using debugging tool to log as much related values of the application as possible is the right way, at least for this case.

However, I didn’t take the most effective approach at the first sight! Specifically, for “HTTP ERROR 500”, I searched online, and got hints of logging application states. That directed me to check Azure’s log stream. But for “TypeError: Cannot read property ‘use_env_variable’ of undefined”, I had wrong guess of the cause of the issue: I imagined the compilers on Azure and on my local machine are different – the compiler on local machine ignores the TypeError detected on Azure. Even worse, I firmly believed my imagination of the cause of the issue is true.. It was me randomly logged the var values that helped me unveiling the real issue.

The native approach I took to fix the problem unveils some mistakes I made for solving tech problems:

  • I should’ve directly check Azure’s diagnostic tools when saw “HTTP ERROR 500”. But understanding and learning “HTTP ERROR 500” was necessary.
  • I should’ve realized “TypeError: Cannot read property ‘use_env_variable’ of undefined” means “config” is undefined, and should’ve logged out related vars of “config”, instead of imagining the difference between local machine and Azure compiler. I think what I really miss here is that for a web app, the first priority of debugging is logging out vars, then consider system and compilers issues. But learning “TypeError: Cannot read property ‘use_env_variable’ of undefined” was necessary too.

So, a couple lessons here to solve an issue

  • Learn the error by googling
  • Use the right debugging tool to precisely identify the issue – it should be specific to code level

React + Redux and HTTP Request

It’s a bit confusing for starters to get how does React + Redux and HTTP Request work together. For example, how does the HTTP Request influence registered app states? How is it related to action?

It all melted down to fully understand what is each of React, Redux and HTTP Request designed for, and how does it work. So here we go:

React renders the UI with states and props.

Redux manages the states of React.

HTTP Request fired by an action doesn’t necessarily affect the states in Redux’s store. There’re two cases here:

  • If the action firing a HTTP Request changes the UI, we need to design app states, register them to Redux store, dispatch them to change the UI
  • If the action firing a HTTP Request doesn’t change any UI, we don’t need to add app states related to the HTTP Request. We can directly fire the HTTP Response from React

Web App with Redux and Microsoft Azure

So, I’m building the official website for my startup Dopamine. The website has a subscription system to get user email, and a few pages introducing the company. To fulfill these requirements, it needs three things:

  • Web api as backend
  • Database to store subscription data
  • Frontend

To have the website up in the shortest time while remaining security on user data, flexible content updates of the UI in the future, the technologies used to build the website need to be:

  • Easy to pick up
  • Have supportive community
  • Have a robust mechanism to secure data
  • Flexible on frontend UI update

After researching around, Microsoft Azure + Redux arises as the perfect combination to achieve short-term and long-term goals as described above for the following reason:

Microsoft Azure has a complete framework building and hosting a web app [1].  Most importantly, Azure compiles with modern web technologies, such as Redux [2] [4] [5]. Thus, multiplying these two should be enough to build a web app with easy steps.

In case there’re issues using Redux in Visual Studio on Windows, [3] writes down potential issues could be encountered as well as the corresponding solutions.

References

[1] Build an ASP.NET app in Azure with SQL Database. https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-dotnet-sqldatabase

[2] How to Use React with Visual Studio and ASP.NET Web API. https://blog.pusher.com/how-to-use-react-with-visual-studio-and-asp-net-web-api

[3] Visual Studio 2015 with ASP.Net, React and Modern JavaScript Development. https://medium.com/@jai_75697/visual-studio-2015-with-asp-net-react-and-modern-javascript-development-625fd9487fa7

[4] Using React with Redux. https://mva.microsoft.com/en-us/training-courses/using-react-with-redux-17730?l=8VEwsDb2D_411787177

[5] Deploying create-react-app on Microsoft Azure. https://medium.com/@to_pe/deploying-create-react-app-on-microsoft-azure-c0f6686a4321