Node Js Sample Project

Posted on  by admin
In this tutorial, we’re gonna build a Node.js Express Rest API example that supports Token Based Authentication with JWT (JSONWebToken).
Appropriate Flow for User Signup & User Login with JWT Authentication. Node.js Express Architecture with CORS, Authentication & Authorization middlewares & Sequelize.
How to configure Express routes to work with JWT. How to define Data Models and association for Authentication and Authorization.

Way to use Sequelize to interact with MySQL Database. Related Posts: – Node.js Rest APIs example with Express, Sequelize & MySQL – Node.js + MongoDB: User Authentication & Authorization with JWT – Node.js + PostgreSQL: User Authentication & Authorization with JWT.

Fullstack (JWT Authentication & Authorization example): – Node.js Express + Vue.js – Node.js Express + Angular 8 – Node.js Express + Angular 10 – Node.js Express + Angular 11 – Node.js Express + Angular 12 – Node.js Express + React.

Configure Auth Key

  • Deployment: – Deploying/Hosting Node.js app on Heroku with MySQL database – Dockerize Node.js Express and MySQL example – Docker Compose.

The Hello user-email-address app

  • Create Controllers. Comparing with Session-based Authentication that need to store Session on Cookie, the big advantage of Token-based Authentication is that we store the JSON Web Token (JWT) on Client side: Local Storage for Browser, Keychain for IOS and SharedPreferences for Android… So we don’t need to build another backend project that supports Native Apps or an additional Authentication module for Native App users.

Node.js Express Architecture with Authentication & Authorization

  • There are three important parts of a JWT: Header, Payload, Signature.
  • Together they are combined to a standard structure: header.payload.signature.
  • The Client typically attaches JWT in Authorization header with Bearer prefix:.
  • Or only in x-access-token header:.
  • For more details, you can visit:In-depth Introduction to JWT-JSON Web Token.
  • We will build a Node.js Express application in that:.

User can signup new account, or login with username & password.

By User’s role (admin, moderator, user), we authorize the User to access resources.

This is our Node.js application demo running with MySQL database and test Rest Apis with Postman.

Configure MySQL database & Sequelize

  1. These are APIs that we need to provide:. The diagram shows flow of User Registration, User Login and Authorization process.
  2. A legal JWT must be added to HTTP x-access-token Header if Client accesses protected resources.
  3. You will need to implement Refresh Token:.

Source Code

More details at: JWT Refresh Token implementation in Node.js example. If you want to use Cookies, please visit:Node.js Express: Login and Registration example with JWT.

Conclusion

Create Middleware functions

You can have an overview of our Node.js Express App with the diagram below:.

Identity-Aware Proxy

Via Express routes, HTTP request that matches a route will be checked by CORS Middleware before coming to Security layer. Security layer includes:. JWT Authentication Middleware: verify SignUp, verify token. Authorization Middleware: check User’s roles with record in database.

If these middlewares throw any error, a message will be sent as HTTP response. Controllers interact with MySQL Database via Sequelize and send HTTP response (token, user information, data based on roles…) to client.

App-managed authentication

jsonwebtoken 8.5.1. Sequelize 5.21.3. This is directory structure for our Node.js Express application:. configure MySQL database & Sequelize. configure Auth Key. auth.routes.js: POST signup & signin. user.routes.js: GET public & protected resources.

verifySignUp.js: check duplicate Username or Email.

Token Based Authentication

authJwt.js: verify Token, check User roles in database. auth.controller.js: handle signup & signin actions.

user.controller.js: return public & protected content. – models for Sequelize Models.

– server.js: import and initialize necessary modules and routes, listen for connections. First, we create a folder for our project:. Then we initialize the Node.js App with a package.json file:. We need to install necessary modules: express, cors, sequelize, mysql2, jsonwebtoken and bcryptjs. Run the command:. The package.json file now looks like this:. In the root folder, let’s create a new server.js file:.

Let me explain what we’ve just done: – import express and cors modules:.

Express is for building the Rest apis. cors provides Express middleware to enable CORS. – create an Express app, then add request body parser and cors middlewares using app.use() method.

Notice that we set origin: http://localhost:8081.

Flow for Signup & Login with JWT Authentication

– define a GET route which is simple for test. – listen on port 8080 for incoming requests.

Now let’s run the app with command: node server.js. Open your browser with url http://localhost:8080/, you will see:.

In the app folder, create config folder for configuration with db.config.js file like this:.

First five parameters are for MySQL connection.pool is optional, it will be used for Sequelize connection pool configuration:.

max: maximum number of connection in pool. min: minimum number of connection in pool.

Create Controllers

  1. Express

    Fast, unopinionated, minimalist web framework for node.

    More details can be found at https://www.npmjs.com/package/express.

  2. body-parser

    Node.js body parsing middleware.

    Parse incoming request bodies in a middleware before your handlers, available under the req.body property.

  3. Mssql

    Microsoft SQL Server client for Node.js

  4. joi

    Object schema description language and validator for JavaScript objects.

idle: maximum time, in milliseconds, that a connection can be idle before being released. acquire: maximum time, in milliseconds, that pool will try to get connection before throwing error.

For more details, please visit API Reference for the Sequelize constructor. In models folder, create User and Role data model as following code:.

These Sequelize Models represents users & roles table in MySQL database.

After initializing Sequelize, we don’t need to write CRUD functions, Sequelize supports all of them:.

create a new User: create(object). find a User by id: findByPk(id). find a User by email: findOne({ where: { email: ..

get all Users: findAll(). find all Users by username: findAll({ where: { username: ..

Run & Test with Results

These functions will be used in our Controllers and Middlewares. Now create app/models/index.js with content like this:. The association between Users and Roles is Many-to-Many relationship: – One User can have several Roles.

– One Role can be taken on by many Users. We use User.belongsToMany(Role) to indicate that the user model can belong to many Roles and vice versa.

With through, foreignKey, otherKey, we’re gonna have a new table user_roles as connection between users and roles table via their primary key as foreign keys.

If you want to know more details about how to make Many-to-Many Association with Sequelize and Node.js, please visit:Sequelize Many-to-Many Association example – Node.js & MySQL.

Don’t forget to call sync() method in server.js.

initial() function helps us to create 3 rows in database.

In development, you may need to drop existing tables and re-sync database. So you can use force: true as code above.

For production, just insert these rows manually and use sync() without parameters to avoid dropping data:.

Learn how to implement Sequelize One-to-Many Relationship at:Sequelize Associations: One-to-Many example – Node.js, MySQL.

jsonwebtoken functions such as verify() or sign() use algorithm that needs a secret key (as String) to encode and decode token.

Initialize Sequelize

In the app/config folder, create auth.config.js file with following code:. You can create your own secret String.

To verify a Signup action, we need 2 functions: – check if username or email is duplicate or not – check if roles in the request is existed or not.

To process Authentication & Authorization, we have these functions: - check if token is provided, legal or not. We get token from x-access-token of HTTP headers, then use jsonwebtoken's verify() function. - check if roles of the user contains required role or not. There are 2 main functions for Authentication: - signup: create new User in database (role is user if not specifying role) - signin:.

Controller for Authentication

find username of the request in database, if it exists.

compare password with password in database using bcrypt, if it is correct. generate a token using jsonwebtoken.

Clean up

return user information & access Token. There are 4 functions: – /api/test/all for public access – /api/test/user for loggedin users (role: user/moderator/admin) – /api/test/mod for users having moderator role – /api/test/admin for users having admin role.

Now, do you have any question? Would you like to know how we can combine middlewares with controller functions? Let's do it in the next section. When a client sends request for an endpoint using HTTP request (GET, POST, PUT, DELETE), we need to determine how the server will response by setting up the routes. We can separate our routes into 2 part: for Authentication and for Authorization (accessing protected resources).

POST /api/auth/signup. POST /api/auth/signin. GET /api/test/all.

GET /api/test/user for loggedin users (user/moderator/admin).

GET /api/test/mod for moderator. GET /api/test/admin for admin. Don't forget to add these routes in server.js:. Run Node.js application with command: node server.js. Tables that we define in models package will be automatically generated in MySQL Database. If you check the database, you can see things like this:.

Define Routes

External authentication with OAuth2

If you don't use initial() function in Sequelize sync() method. You need to run following SQL script:.

3 records will be created in roles table:. Register some users with /signup API:. admin with admin role. mod with moderator and user roles. zkoder with user role. Our tables after signup could look like this.

Add authorized users to the app

Access public resource: GET /api/test/all.

Access protected resource: GET /api/test/user. Login an account (with wrong password): POST /api/auth/signin. Login an account: POST /api/auth/signin.

Overview of Node.js Express JWT Authentication example

Access protected resources: GET /api/test/user. Today we've learned so many interesting things about Node.js Token Based Authentication with JWT - JSONWebToken in just a Node.js Express Rest Api example.

Despite we wrote a lot of code, I hope you will understand the overall architecture of the application, and apply it in your project at ease. You should continue to know how to implement Refresh Token:JWT Refresh Token implementation in Node.js example.

If you need a working front-end for this back-end, you can find Client App in the post: - Vue.js JWT Authentication with Vuex and Vue Router - Angular 8 JWT Authentication example with Web Api - Angular 10 JWT Authentication example with Web Api - Angular 11 JWT Authentication example with Web Api - Angular 12 JWT Authentication example with Web Api - React JWT Authentication (without Redux) example - React Hooks: JWT Authentication (without Redux) example - React Redux: JWT Authentication example.

Authentication concepts

Understanding the code

Happy learning! Fullstack CRUD Application: - Vue.js + Node.js + Express + MySQL example - Vue.js + Node.js + Express + MongoDB example - Angular 8 + Node.js Express + MySQL example - Angular 10 + Node.js Express + MySQL example - Angular 11 + Node.js Express + MySQL example - Angular 12 + Node.js Express + MySQL example - React + Node.js + Express + MySQL example.

Deployment: - Deploying/Hosting Node.js app on Heroku with MySQL database - Dockerize Node.js Express and MySQL example – Docker Compose.
  • You can find the complete source code for this tutorial on Github.
  • If you want to use Cookies, please visit:Node.js Express: Login and Registration example with JWT.
  • Apps running on Google Cloud managed platforms such asApp Engine can avoid managinguser authentication and session management byusingIdentity-Aware Proxy (IAP) to control access to them.
  • IAP can not only control access to theapp, but it also providesinformation about the authenticated users, including the email address and apersistent identifier to the app in the form ofnew HTTP headers.

Require users of your App Engine app to authenticate themselves byusing IAP. Access users' identities in the app to display the current user'sauthenticated email address.

This tutorial uses the following billable components of Google Cloud: .

To generate a cost estimate based on your projected usage, use the pricing calculator.

New Google Cloud users might be eligible for a free trial.

When you finish this tutorial, you can avoid continued billing by deleting the resources you created.

For more information, seeClean up. Sign in to your Google Cloud account. If you're new to Google Cloud,create an account to evaluate how our products perform in real-world scenarios.

New customers also get $300 in free credits to run, test, and deploy workloads. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project.

After you finish these steps, you can delete the project, removing all resources associated with the project.

Install and initialize the Google Cloud CLI.

In the Google Cloud console, on the project selector page, select or create a Google Cloud project. Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project.

After you finish these steps, you can delete the project, removing all resources associated with the project. Install and initialize the Google Cloud CLI. This tutorial uses IAP to authenticate users.This is only one of several possible approaches.To learn moreabout the various methods to authenticate users, see theAuthentication concepts section.

The app for this tutorial is a minimal Hello world App Engine app,with one non-typical feature: instead of "Hello world" it displays"Hello user-email-address", whereuser-email-address is the authenticateduser's email address.

This functionality is possible by examining the authenticated informationthat IAP adds to each web request it passes through to your app.There arethree new request headers added to each web request that reaches your app.The first two headers are plain text strings that you can use toidentify the user.

The third header is a cryptographically signed objectwith that same information.

X-Goog-Authenticated-User-Email: A user's email address identifies them.Don't store personal information if your app can avoid it.

This app doesn'tstore any data; it just echoes it back to the user.

Setup Express web server

X-Goog-Authenticated-User-Id: This user ID assigned by Google doesn'tshow information about the user, but it does allow an app to knowthat a logged-in user is the same one that was previously seen before.

X-Goog-Iap-Jwt-Assertion: You can configure Google Cloud appsto accept web requests from other cloud apps, bypassingIAP, in addition to internet web requests.

If an app is soconfigured, it's possible for such requests to have forged headers.Instead of using either of the plain text headers previously mentioned, youcan use and verify this cryptographically signed header to check that the informationwas provided by Google.

Both the user's email address and a persistentuser ID are available as part of this signed header.

If you are certain that the app is configured so that only internetweb requests can reach it, and that no one can disable the IAPservice for the app, then retrieving a unique user ID takes only a single lineof code:.

However, a resilient app should expect things to go wrong, includingunexpected configuration or environmental issues, so we instead recommendcreating a function that uses and verifies the cryptographically signed header.That header's signature cannot be forged, and when verified, can be used toreturn the identification.

Use a text editor to create a file named app.js, and paste thefollowing code in it:. This app.js file is explained in detail in theUnderstanding the codesection later in this tutorial.

Create another file called package.json, and paste the followinginto it:. The package.json file lists any Node.js dependencies your app needs.

Costs

jsonwebtoken provides the JWT checking and decoding function.

Create a file named app.yaml and put the following text in it:. The app.yaml file tells App Engine which language environment your coderequires. This section explains how the code in the app.js file works.

Objectives

If you want to runthe app, you can skip ahead to theDeploy the appsection. The following code is in the app.js file.

Further Reading

When the app receives an HTTP GET, the switch case for / is invoked:. The function gets the JWT assertion header value thatIAP added fromthe incoming request and calls a function to validate that cryptographicallysigned value.

The first value returned (email address) is then used in a minimal webpage that it creates and returns. The validateAssertion function uses the verifySignedJwtWithCertsAsync() functionfrom google-auth-library to verify that the assertion is properly signed,and to extract the payload information from the assertion.

That information isthe authenticated user's email address and a persistent unique ID for the user.If the assertion cannot be decoded, this function throws and prints a message to log the error. Validating a JWT assertion requires knowing the public key certificates ofthe entity that signed the assertion (Google in this case), and the audiencethe assertion is intended for.

Enable IAP

For an App Engine app, the audience isa string with Google Cloud project identification information in it.This function getsthose certificates and the audience string from the functions preceding it.

You can look up the Google Cloud project's numeric ID and name and put them in thesource code yourself, but the audience function does that for you by queryingthe standard metadata service made available to every App Engine app.Because the metadata service is external to the app code, that result is savedin a global variable that is returned without having to look metadata upin subsequent calls.

The App Engine metadata service (and similar metadata services for otherGoogle Cloud computing services) looks like a web site and is queried bystandard web queries.

However, the metadata service isn't actually an external site, but aninternal feature that returns requested information about the runningapp, so it is safe to use http instead of https requests.It's used to get the current Google Cloud identifiers needed to define theJWT assertion's intended audience.

Verification of a digital signature requires the public key certificate ofthe signer.

Google provides a web site that returns all of the currently used publickey certificates. These results are cachedin case they're needed again in the same app instance.

Now you can deploy the app and then enable IAP to require usersto authenticate before they can access the app.

Define the Sequelize Model

In your terminal window, go to the directory containing the app.yaml file,and deploy the app to App Engine:.

When prompted, select a nearby region. When asked if you want to continue with the deployment operation, enter Y.

require('cloud').example

Within a few minutes, your app is live on the internet.

In the output, copy web-site-url, the web addressfor the app.

In a browser window, paste web-site-url to open theapp. No email is displayed because you're not yet using IAP so nouser information is sent to the app.

Now that an App Engine instance exists, you can protect it withIAP:. In the Google Cloud console, go to the Identity-Aware Proxy page. Because this is the first time you've enabled an authentication option forthis project, you see a message that you must configure your OAuth consentscreen before you can use IAP.

Controller for testing Authorization

Click Configure Consent Screen.

On the OAuth Consent Screen tab of the Credentials page, completethe following fields:. If your account is in a Google Workspace organization, select Externaland click Create.

Access the app

To start, the app will only be available to users youexplicitly allow. In the Application name field, enter IAP Example.

Project Structure

In the Support email field, enter your email address. In the Authorized domain field, enter the hostname portion of the app'sURL, for example, iap-example-999999.uc.r.appspot.com.

Press the Enter keyafter entering the hostname in the field.

  • In the Application homepage link field, enter the URL for your app, forexample, https://iap-example-999999.uc.r.appspot.com/.
  • In the Application privacy policy line field, use the same URL as thehomepage link for testing purposes.

When prompted to create credentials, you can close the window. In the Cloud console, go to the Identity-Aware Proxy page.

Technology

To refresh the page, clickRefreshrefresh. Thepage displays a list of resources you can protect. In the IAP column, click to turn on IAP for the app.

Create Node.js App

In your browser, go to web-site-url again. Instead of the web page, there is a login screen to authenticate yourself.When you log in, you're denied access because IAP doesn'thave a list of users to allow through to the app.

In the Cloud console, go to the Identity-Aware Proxy page. Select the checkbox for the App Engine app, and then clickAdd Principal. Enter allAuthenticatedUsers, and then select theCloud IAP/IAP-Secured Web App User role. Now any user that Google can authenticate can access the app.

If you want,you can restrict access further by only adding one or more people orgroups as principals:.

Create the source code

Any Gmail or Google Workspace email address.

A Google Group email address. A Google Workspace domain name. In your browser, go to web-site-url.

To refresh the page, click Refreshrefresh. On the login screen, log in with your Google credentials.

The page displays a "Hello user-email-address" page with youremail address. If you still see the same page as before, there might be an issue with thebrowser not fully updating new requests now that you enabledIAP. Close all browser windows, reopen them, and try again.

Focus on your app, not configuring routing

There are several ways an app can authenticate its users and restrict accessto only authorized users.

Common authentication methods, in decreasing level of effortfor the app, are listed in the following sections.

App can run on any platform, with or without an internet connection . Users don't need to use any other service to manage authentication .

App must manage user credentials securely, guard against disclosure . App must maintain session data for logged-in users . App must provide user registration, password changes, password recovery .

Before you begin

App can run on any internet-connected platform, including a developer workstation . App doesn't need user registration, password changes, or password recovery functions. Risk of user information disclosure is delegated to other service . New login security measures handled outside the app . Users must register with the identity service .

Leverage GitHub integration and powerful add-ons

App must maintain session data for logged-in users . App doesn't need to have any code to manage users, authentication, or session state .

App has no user credentials that might be breached . App can only run on platforms supported by the service.

Rollback to a binary copy of your app if you break production

Specifically, certain Google Cloud services that support IAP, such as App Engine.

With this method, the app manages every aspect of user authenticationon its own. The app must maintain its own database of user credentials and manageuser sessions, and it needs to provide functions to manage user accounts andpasswords, check user credentials, as well as issue, check, and update user sessionswith each authenticated login.

The following diagram illustrates the app-managedauthentication method. As shown in the diagram, after the user logs in, the app creates and maintainsinformation about the user's session.

When the user makes a request to the app,the request must include session information that the app is responsible forverifying. The main advantage of this approach is that it is self-contained and underthe control of the app.

The app doesn't even need to beavailable on the internet. The main disadvantage is thatthe app is now responsible for providing all account managementfunctionality and protecting all sensitive credential data.

Deploying the app

Background

Conclusion

A good alternative to handling everything within the app is to usean external identity service, such as Google, that handles all useraccount information and functionality and is responsible for safeguardingsensitive credentials. When a user tries to log in to the app therequest is redirected to the identity service, which authenticates theuser and then redirect the request back to the app with necessaryauthentication information provided.

For more information, seeAuthenticating as an end user. The following diagram illustrates the external authentication with the OAuth2method.

History

  • The flow in the diagram begins when the user sends a request to access theapp.