In this tutorial, we’re gonna build a Node.js Express Rest API example that supports Token Based Authentication with JWT (JSONWebToken). You’ll know:
- 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 Express + Vue
– Node Express + Angular 8
– Node Express + Angular 10
– Node Express + Angular 11
– Node Express + Angular 12
– Node Express + Angular 13
– Node Express + Angular 14
– Node Express + Angular 15
– Node Express + Angular 16
– Node Express + React
Deployment:
– Deploying/Hosting Node.js app on Heroku with MySQL database
– Dockerize Node.js Express and MySQL example β Docker Compose
Contents
- Token Based Authentication
- Overview of Node.js JWT Authentication example
- Flow for Signup & Login with JWT Authentication
- Node.js Express Architecture with Authentication & Authorization
- Technology
- Project Structure
- Create Node.js App
- Setup Express web server
- Configure MySQL database & Sequelize
- Define the Sequelize Model
- Initialize Sequelize
- Configure Auth Key
- Create Middleware functions
- Create Controllers
- Define Routes
- Run & Test with Results
- Conclusion
- Source Code
- Further Reading
Token Based Authentication
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.
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:
Authorization: Bearer [header].[payload].[signature]
Or only in x-access-token header:
x-access-token: [header].[payload].[signature]
For more details, you can visit:
In-depth Introduction to JWT-JSON Web Token
Overview of Node.js Express JWT Authentication example
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.
These are APIs that we need to provide:
Methods | Urls | Actions |
---|---|---|
POST | /api/auth/signup | signup new account |
POST | /api/auth/signin | login an account |
GET | /api/test/all | retrieve public content |
GET | /api/test/user | access User’s content |
GET | /api/test/mod | access Moderator’s content |
GET | /api/test/admin | access Admin’s content |
Flow for Signup & Login with JWT Authentication
The diagram shows flow of User Registration, User Login and Authorization process.
A legal JWT must be added to HTTP x-access-token Header if Client accesses protected resources.
You will need to implement Refresh Token:
More details at: JWT Refresh Token implementation in Node.js example
If you want to use Httponly Cookies, please visit:
Node.js Express: Login and Registration example with JWT
Node.js Express Architecture with Authentication & Authorization
You can have an overview of our Node.js Express App with the diagram below:
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.
Technology
- Express 4.18.2
- bcryptjs 2.4.3
- jsonwebtoken 9.0.0
- Sequelize 6.32.1
- MySQL
Project Structure
This is directory structure for our Node.js Express application:
– config
- configure MySQL database & Sequelize
- configure Auth Key
– routes
- auth.routes.js: POST signup & signin
- user.routes.js: GET public & protected resources
– middlewares
- verifySignUp.js: check duplicate Username or Email
- authJwt.js: verify Token, check User roles in database
– controllers
- auth.controller.js: handle signup & signin actions
- user.controller.js: return public & protected content
– models for Sequelize Models
- user.model.js
- role.model.js
– server.js: import and initialize necessary modules and routes, listen for connections.
Create Node.js App
First, we create a folder for our project:
$ mkdir node-js-jwt-auth
$ cd node-js-jwt-auth
Then we initialize the Node.js App with a package.json file:
npm init
name: (node-js-jwt-auth)
version: (1.0.0)
description: Node.js Demo for JWT Authentication
entry point: (index.js) server.js
test command:
git repository:
keywords: node.js, express, jwt, authentication, mysql
author: bezkoder
license: (ISC)
Is this ok? (yes) yes
We need to install necessary modules: express
, cors
, sequelize
, mysql2
, jsonwebtoken
and bcryptjs
.
Run the command:
npm install express sequelize mysql2 cors jsonwebtoken bcryptjs --save
The package.json file now looks like this:
{
"name": "node-js-jwt-auth",
"version": "1.0.0",
"description": "Node.js Demo for JWT Authentication",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"node.js",
"jwt",
"authentication",
"express",
"mysql"
],
"author": "bezkoder",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"mysql2": "^2.3.3",
"sequelize": "^6.32.1"
}
}
Setup Express web server
In the root folder, let’s create a new server.js file:
const express = require("express");
const cors = require("cors");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
// simple route
app.get("/", (req, res) => {
res.json({ message: "Welcome to bezkoder application." });
});
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
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
.
– 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:
Configure MySQL database & Sequelize
In the app folder, create config folder for configuration with db.config.js file like this:
module.exports = {
HOST: "localhost",
USER: "root",
PASSWORD: "123456",
DB: "testdb",
dialect: "mysql",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
};
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 poolmin
: minimum number of connection in poolidle
: maximum time, in milliseconds, that a connection can be idle before being releasedacquire
: 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.
Define the Sequelize Model
In models folder, create User
and Role
data model as following code:
models/user.model.js
module.exports = (sequelize, Sequelize) => {
const User = sequelize.define("users", {
username: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
}
});
return User;
};
models/role.model.js
module.exports = (sequelize, Sequelize) => {
const Role = sequelize.define("roles", {
id: {
type: Sequelize.INTEGER,
primaryKey: true
},
name: {
type: Sequelize.STRING
}
});
return Role;
};
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: ... } })
These functions will be used in our Controllers and Middlewares.
Initialize Sequelize
Now create app/models/index.js with content like this:
const config = require("../config/db.config.js");
const Sequelize = require("sequelize");
const sequelize = new Sequelize(
config.DB,
config.USER,
config.PASSWORD,
{
host: config.HOST,
dialect: config.dialect,
pool: {
max: config.pool.max,
min: config.pool.min,
acquire: config.pool.acquire,
idle: config.pool.idle
}
}
);
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.user = require("../models/user.model.js")(sequelize, Sequelize);
db.role = require("../models/role.model.js")(sequelize, Sequelize);
db.role.belongsToMany(db.user, {
through: "user_roles"
});
db.user.belongsToMany(db.role, {
through: "user_roles"
});
db.ROLES = ["user", "admin", "moderator"];
module.exports = db;
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
, 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.
...
const app = express();
app.use(...);
const db = require("./app/models");
const Role = db.role;
db.sequelize.sync({force: true}).then(() => {
console.log('Drop and Resync Db');
initial();
});
...
function initial() {
Role.create({
id: 1,
name: "user"
});
Role.create({
id: 2,
name: "moderator"
});
Role.create({
id: 3,
name: "admin"
});
}
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:
...
const app = express();
app.use(...);
const db = require("./app/models");
db.sequelize.sync();
...
Learn how to implement Sequelize One-to-Many Relationship at:
Sequelize Associations: One-to-Many example β Node.js, MySQL
Configure Auth Key
jsonwebtoken functions such as verify()
or sign()
use algorithm that needs a secret key (as String) to encode and decode token.
In the app/config folder, create auth.config.js file with following code:
module.exports = {
secret: "bezkoder-secret-key"
};
You can create your own secret
String.
Create Middleware functions
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
middleware/verifySignUp.js
const db = require("../models");
const ROLES = db.ROLES;
const User = db.user;
checkDuplicateUsernameOrEmail = (req, res, next) => {
// Username
User.findOne({
where: {
username: req.body.username
}
}).then(user => {
if (user) {
res.status(400).send({
message: "Failed! Username is already in use!"
});
return;
}
// Email
User.findOne({
where: {
email: req.body.email
}
}).then(user => {
if (user) {
res.status(400).send({
message: "Failed! Email is already in use!"
});
return;
}
next();
});
});
};
checkRolesExisted = (req, res, next) => {
if (req.body.roles) {
for (let i = 0; i < req.body.roles.length; i++) {
if (!ROLES.includes(req.body.roles[i])) {
res.status(400).send({
message: "Failed! Role does not exist = " + req.body.roles[i]
});
return;
}
}
}
next();
};
const verifySignUp = {
checkDuplicateUsernameOrEmail: checkDuplicateUsernameOrEmail,
checkRolesExisted: checkRolesExisted
};
module.exports = verifySignUp;
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.
middleware/authJwt.js
const jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
const db = require("../models");
const User = db.user;
verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send({
message: "No token provided!"
});
}
jwt.verify(token,
config.secret,
(err, decoded) => {
if (err) {
return res.status(401).send({
message: "Unauthorized!",
});
}
req.userId = decoded.id;
next();
});
};
isAdmin = (req, res, next) => {
User.findByPk(req.userId).then(user => {
user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "admin") {
next();
return;
}
}
res.status(403).send({
message: "Require Admin Role!"
});
return;
});
});
};
isModerator = (req, res, next) => {
User.findByPk(req.userId).then(user => {
user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "moderator") {
next();
return;
}
}
res.status(403).send({
message: "Require Moderator Role!"
});
});
});
};
isModeratorOrAdmin = (req, res, next) => {
User.findByPk(req.userId).then(user => {
user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "moderator") {
next();
return;
}
if (roles[i].name === "admin") {
next();
return;
}
}
res.status(403).send({
message: "Require Moderator or Admin Role!"
});
});
});
};
const authJwt = {
verifyToken: verifyToken,
isAdmin: isAdmin,
isModerator: isModerator,
isModeratorOrAdmin: isModeratorOrAdmin
};
module.exports = authJwt;
middleware/index.js
const authJwt = require("./authJwt");
const verifySignUp = require("./verifySignUp");
module.exports = {
authJwt,
verifySignUp
};
Create Controllers
Controller for Authentication
There are 2 main functions for Authentication:
- signup
: create new User in database (role is user if not specifying role)
- signin
:
- find
username
of the request in database, if it exists - compare
password
withpassword
in database using bcrypt, if it is correct - generate a token using jsonwebtoken
- return user information & access Token
controllers/auth.controller.js
const db = require("../models");
const config = require("../config/auth.config");
const User = db.user;
const Role = db.role;
const Op = db.Sequelize.Op;
var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");
exports.signup = (req, res) => {
// Save User to Database
User.create({
username: req.body.username,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8)
})
.then(user => {
if (req.body.roles) {
Role.findAll({
where: {
name: {
[Op.or]: req.body.roles
}
}
}).then(roles => {
user.setRoles(roles).then(() => {
res.send({ message: "User was registered successfully!" });
});
});
} else {
// user role = 1
user.setRoles([1]).then(() => {
res.send({ message: "User was registered successfully!" });
});
}
})
.catch(err => {
res.status(500).send({ message: err.message });
});
};
exports.signin = (req, res) => {
User.findOne({
where: {
username: req.body.username
}
})
.then(user => {
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
var passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);
if (!passwordIsValid) {
return res.status(401).send({
accessToken: null,
message: "Invalid Password!"
});
}
const token = jwt.sign({ id: user.id },
config.secret,
{
algorithm: 'HS256',
allowInsecureKeySizes: true,
expiresIn: 86400, // 24 hours
});
var authorities = [];
user.getRoles().then(roles => {
for (let i = 0; i < roles.length; i++) {
authorities.push("ROLE_" + roles[i].name.toUpperCase());
}
res.status(200).send({
id: user.id,
username: user.username,
email: user.email,
roles: authorities,
accessToken: token
});
});
})
.catch(err => {
res.status(500).send({ message: err.message });
});
};
Controller for testing Authorization
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
controllers/user.controller.js
exports.allAccess = (req, res) => {
res.status(200).send("Public Content.");
};
exports.userBoard = (req, res) => {
res.status(200).send("User Content.");
};
exports.adminBoard = (req, res) => {
res.status(200).send("Admin Content.");
};
exports.moderatorBoard = (req, res) => {
res.status(200).send("Moderator Content.");
};
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.
Define Routes
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).
Authentication:
- POST
/api/auth/signup
- POST
/api/auth/signin
routes/auth.routes.js
const { verifySignUp } = require("../middleware");
const controller = require("../controllers/auth.controller");
module.exports = function(app) {
app.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
app.post(
"/api/auth/signup",
[
verifySignUp.checkDuplicateUsernameOrEmail,
verifySignUp.checkRolesExisted
],
controller.signup
);
app.post("/api/auth/signin", controller.signin);
};
Authorization:
- 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
routes/user.routes.js
const { authJwt } = require("../middleware");
const controller = require("../controllers/user.controller");
module.exports = function(app) {
app.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
app.get("/api/test/all", controller.allAccess);
app.get(
"/api/test/user",
[authJwt.verifyToken],
controller.userBoard
);
app.get(
"/api/test/mod",
[authJwt.verifyToken, authJwt.isModerator],
controller.moderatorBoard
);
app.get(
"/api/test/admin",
[authJwt.verifyToken, authJwt.isAdmin],
controller.adminBoard
);
};
Don't forget to add these routes in server.js:
...
// routes
require('./app/routes/auth.routes')(app);
require('./app/routes/user.routes')(app);
// set port, listen for requests
...
Run & Test with Results
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:
mysql> describe users;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(255) | YES | | NULL | |
| email | varchar(255) | YES | | NULL | |
| password | varchar(255) | YES | | NULL | |
| createdAt | datetime | NO | | NULL | |
| updatedAt | datetime | NO | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> describe roles;
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | YES | | NULL | |
| createdAt | datetime | NO | | NULL | |
| updatedAt | datetime | NO | | NULL | |
+-----------+--------------+------+-----+---------+-------+
mysql> describe user_roles;
+-----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| createdAt | datetime | NO | | NULL | |
| updatedAt | datetime | NO | | NULL | |
| roleId | int(11) | NO | PRI | NULL | |
| userId | int(11) | NO | PRI | NULL | |
+-----------+----------+------+-----+---------+-------+
If you don't use initial()
function in Sequelize sync()
method. You need to run following SQL script:
mysql> INSERT INTO roles VALUES (1, 'user', now(), now());
mysql> INSERT INTO roles VALUES (2, 'moderator', now(), now());
mysql> INSERT INTO roles VALUES (3, 'admin', now(), now());
3 records will be created in roles
table:
mysql> select * from roles;
+----+-----------+---------------------+---------------------+
| id | name | createdAt | updatedAt |
+----+-----------+---------------------+---------------------+
| 1 | user | 2020-01-13 09:05:39 | 2020-01-13 09:05:39 |
| 2 | moderator | 2020-01-13 09:05:39 | 2020-01-13 09:05:39 |
| 3 | admin | 2020-01-13 09:05:39 | 2020-01-13 09:05:39 |
+----+-----------+---------------------+---------------------+
Register some users with /signup
API:
- admin with
admin
role - mod with
moderator
anduser
roles - zkoder with
user
role
Our tables after signup could look like this.
mysql> select * from users;
+----+----------+--------------------+--------------------------------------------------------------+---------------------+---------------------+
| id | username | email | password | createdAt | updatedAt |
+----+----------+--------------------+--------------------------------------------------------------+---------------------+---------------------+
| 1 | admin | [email protected] | $2a$08$w3cYCF.N0UQZO19z8CQSZ.whzxFS5vMoi9k51g3TQx9r5tkwrIXO2 | 2020-01-13 09:21:51 | 2020-01-13 09:21:51 |
| 2 | mod | [email protected] | $2a$08$tTj1l28esAxPSSvl3YqKl./nz35vQF7Y76jGtzcYUhHtGy6d.1/ze | 2020-01-13 09:22:01 | 2020-01-13 09:22:01 |
| 3 | zkoder | [email protected] | $2a$08$U2F07dLyYZjzTxQbFMCAcOd1k8V1o9f6E4TGVJHpy0V6/DC7iS0CS | 2020-01-13 09:23:25 | 2020-01-13 09:23:25 |
+----+----------+--------------------+--------------------------------------------------------------+---------------------+---------------------+
mysql> select * from user_roles;
+---------------------+---------------------+--------+--------+
| createdAt | updatedAt | roleId | userId |
+---------------------+---------------------+--------+--------+
| 2020-01-13 09:22:01 | 2020-01-13 09:22:01 | 1 | 2 |
| 2020-01-13 09:23:25 | 2020-01-13 09:23:25 | 1 | 3 |
| 2020-01-13 09:22:01 | 2020-01-13 09:22:01 | 2 | 2 |
| 2020-01-13 09:21:51 | 2020-01-13 09:21:51 | 3 | 1 |
+---------------------+---------------------+--------+--------+
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
Access protected resources: GET /api/test/user
Conclusion
Congratulation!
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
- Angular 13 JWT Authentication example with Web Api
- React JWT Authentication (without Redux) example
- React Hooks: JWT Authentication (without Redux) example
- React Redux: JWT Authentication example
Happy learning! See you again.
Further Reading
- https://www.npmjs.com/package/express
- http://expressjs.com/en/guide/routing.html
- In-depth Introduction to JWT-JSON Web Token
- Sequelize Associations
Fullstack CRUD Application:
- Vue.js + Node.js + Express + MySQL 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
- Angular 13 + Node.js Express + MySQL example
- Angular 14 + Node.js Express + MySQL example
- Angular 15 + Node.js Express + MySQL example
- Angular 16 + 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
Source Code
You can find the complete source code for this tutorial on Github.
If you want to use Httponly Cookies, please visit:
Node.js Express: Login and Registration example with JWT
Thanks!
I am hosting my database on AWS, but once I created the User and Role models in my backend and run the code. It does not automatically create anything in mySQL database on AWS. Do you know what is wrong with this?
Thank You, for this tutorial, its very helpful tutorial, all methods works correctly,
but when i am calling get method http://localhost:8080/api/test/mod
message will return “no token provided” why, whats my mistake, please help me
I solved this problem….again thanks a lot bezkoder
Hey, how did u solve this?
Hello,
First of all thanks you for your work, everything works perfectly except the capacities of adding multiple roles to one user. Adding one role is working but when i try to add two of them with postman i have the same error :
“Unhandled rejection SequelizeDatabaseError: You have an error in your SQL syntax;”.
The user is created and added to the database without any role, not even user who is set by default.
I tried to modify the roles models, like it seems it’s not build to be an array with multiple string i don’t really know i’m still very new to this.
Thanks in advance for you help
hi , when i re run the server all the data that I have saved will be removed how to change that please !!
solved thanks .
i tried but this error not resolved
TypeError: Cannot read property 'username' of undefined at checkDuplicateUsernameOrEmail (C:\SRIHARI\my-projects\project-management\angular-node\node-pms\app\middleware\verifySignUp.js:8:26) at Layer.handle [as handle_request] (C:\SRIHARI\my-projects\project-management\angular-node\node-pms\node_modules\express\lib\router\layer.js:95:5) at next (C:\SRIHARI\my-projects\project-management\angular-node\node-pms\node_modules\express\lib\router\route.js:137:13) at Route.dispatch
Hi, kindly make sure that you use
Content-Type: application/json
in your HTTP request header. πGetting these issues from the nuxt portion of the project:
ERROR in ./node_modules/pg-connection-string/index.js
Module not found: Error: Can’t resolve ‘fs’ in ‘node_modules\pg-connection-string’
ERROR in ./node_modules/sequelize/dist/lib/dialects/sqlite/connection-manager.js
Module not found: Error: Can’t resolve ‘fs’ in ‘node_modules\sequelize\dist\lib\dialects\sqlite’
ERROR in ./node_modules/sequelize/dist/lib/dialects/postgres/hstore.js
Module not found: Error: Can’t resolve ‘pg-hstore’ in ‘node_modules\sequelize\dist\lib\dialects\postgres’
Installing fs and pg-hstore does not seem to resolve the issue, and besides that I don’t understand where this is coming from anyways. The frontend nuxt app shouldn’t be concerned about any of this stuff. Any ideas of where I should look? I did put all the folders for this project in the root folder of my Nuxt app instead of in a different folder.
Thank you so much!! ππ
Hey, great work on this one!! I have been following you for a while and being new to react and all, you have really contributed to my letting loose. I only need some clarification for a certain addition to the server.js file, after the creation of the /models/index.js file.
At that point in the tutorial you add the following lines to the server.js:
………………………………..
const app = express();
app.use(…);
const db = require(“./app/models”);
const Role = db.role;
………………………………..
I do not understand why there is a spread operator inside the app.use function. What does app.use(…) do? Or is there something else implied there? Anyhow, running –node server.js — is blocked by the editor, because of that line. Thank you very much!
Hi, the
'...'
just implies something else there πYou can read the source code on Github for details.
Love your tutorial man. Cannot thank you more for this,
Hai bezkoder. You give this tutorial it’s really awesome. I just tried it for the first time and understand. Thanks so much.
great bezkode i have a question we can control other user or deleat or see profile other user like a admin role ? can u help me or send a tutorial for admin role
Hello bezkoder
I tried the tutorial and I think it is very geat job.
I tried it in my local dev machine (localhost) and then published it on my cloud dev machine.
I wanted to test the tutorial on my dev cloud machine with the usecase I provide old token when signing
so i used the token (for the same user) used some minutest ago in my local dev machine
the token i used before in my local dev machine worked also in my cloud dev machine.
Is it because the token has 24hrs validity ?
could we think to link the token also to the domain of the express application ?
Regards
hi, thanks a lot, I am learning so much!
Thanks bezkoder. Very happy with your tutorial
This was very very helpful; thank you!
Hi, can anyone help me, i try to select all from my table: i do have tb1.models.js in the models folder
The error here
TypeError: Cannot read property ‘findAll’ of undefined
I found the issue. the code can not connect other tables except: users, user_roles and roles.
in the sql-management the db-account can access all tables.
where is in the code to register other tables?
Why the table name system add ‘s’ to the end and add more columns when execute that make me sick and need to findout where is the configuration.
original table name tbl1: id, name
log:
Executing (default): SELECT [id], [name], [createdAt], [updatedAt] FROM [tbl1s] AS [tbl1];
Finally i found the solution:
add your original table name and set option timestamp in your model.js:
NOTED: you can add timestamps: false to the model/index.js as an option to all your models.
Please help: what does it mean?
{//post
“username”: “mod”,
“email”: “[email protected]”,
“password”: “test”,
“roles”: [“moderator”, “user”]
}
I get the below message from postman
{
“message”: “Conversion failed when converting date and/or time from character string.”
}
the datatype or id of roles is not matched the structure then i drop my table and use the initial fuction now is working thank you.
Hi Bezkoder,
Thank you very much for your tutorial, it is amazing! I followed it step by step and everything worked fine until when I tried to access the protected source. The signup and signin functions work well and I can get the token as well. However, when I tried to do “/api/test/user” (there is a user in my database), it said “no token provided” and when I tried to do”console.log(req.headers[“x-access-token”], it was undefined. The same thing happened when I downloaded your source code from git and ran it on my mac. Can you please tell me what happened and how I could fix it?
Thank you so much.
Same
everything working fine but i get the msg: No token provided!
Please make sure to select the right back-end (Node or Spring Boot) in the src/services/auth-header.js file of your front-end implementation.
Working great! Thanks alot π
Hello Bezkoder,
Great job,kudos for your effort.
I am new to MERN with mysql,and Sequelize,I tried to follow the steps in this tutorial,but it seems I have missed some important step,that prevent me from creating a new user,each time I execute the code,I get “TypeError: User.create is not a function” error message at User.create({}) of auth.controller.js. Kindly assist in resolving this issue.
Thank you
Hey There. A very great article which helped me from the beginning till the end.
Cheers.
In server.js, line 23:
db.sequelize.sync();
// force: true will drop the table if it already exists
// db.sequelize.sync({force: true}).then(() => {
// console.log(‘Drop and Resync Database with { force: true }’);
// initial();
// });
The call to initial() is never done so db.roles stays empty causing no insert into db.user_roles when a new user is inserted using /api/auth/signup
Hello, can u help me?, im get stuck here after POST to localhost:3000/api/auth/daftar
Executing (default): SELECT `id`, `namalengkap`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `penggunas` AS `penggunas` WHERE `penggunas`.`username` = ‘madiajijah7’ LIMIT 1;
Executing (default): SELECT `id`, `namalengkap`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `penggunas` AS `penggunas` WHERE `penggunas`.`email` = ‘[email protected]’ LIMIT 1;
there no error in Postman just a seinding request like this : https://prntscr.com/119eg9i
already fix it, forgot to add next() at end the code
Hi,
This such a great tutorial man. So gladly i found it. Btw i wanna ask something, what the next(); meaning in every functions you’ve make it ?
Thanks.
Hi, Great Tutorial! , can i can add permissions to this project , roles , rules, permissions may be come from database , have y some idea to do it ?
Hi, great tutorial. I have one question how to inital roleId & userId ?
Hi Bezcoder,
A very nice tutorials and well documented.
I have issue with ROLE not assigned to a respective (Moderator & admin) user, during signup, is there a suggestion on how to fix that please.
warm regards
Excellent tutorial. I am trying to convert to typescript, but it has a lot of errors. Do you have any examples with TS?
Thanks,
Hello bezkoder … Thanks for this post … Congrats from Colombia!
Hello bezkoder, when I try to signup users using Postman, I get a error response saying socket hang up or read Econnreset. Can you help me with it?
All other get requests work perfectly fine.
Thank you for this tutorial. I’m facing these messages when I try to restart node server.js:
(node:14036) [SEQUELIZE0004] DeprecationWarning: A boolean value was passed to options.operatorsAliases. This is a no-op with v5 and should be removed.
Server is running on port 8080.
(node:14036) UnhandledPromiseRejectionWarning: SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
at ConnectionManager.connect (C:\Users\RARibeiro\OneDrive\ECOSTEEL\node-js-jwt-auth\node_modules\sequelize\lib\dialects\mysql\connection-manager.js:116:17)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:14036) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `–unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:14036) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I run into the same issue. This shows up when trying to setup the alternative postgres project.
Haven’t found a solution yet.
Hi, for Postgres, please visit:
Node.js JWT Authentication with PostgreSQL example
Hello, I;m stuck in “Unhandled rejection Error: WHERE parameter “username” has invalid “undefined” value”
i do :
// parse requests of content-type – application/json
app.use(bodyParser.json());
// parse requests of content-type – application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
And below it i put :
// routes
require(‘./app/routes/auth.routes’)(app);
require(‘./app/routes/user.routes’)(app);
Trying restart “node server.js” several times like a mention in comment before ,but still no luck still getting that error , maybe someone can help to resolve it ?. – Thanks –
Hi, as mentioned by Ahsan some days ago, in postman you should change the input from raw text to raw JSON and then you’ll have a success message.
I was stuck with this some time until noticed that.
using app.use(express.json()); solves the problem for me.
hello, how can retrieve a list of all the “mod” or “superadmin” from the table?
hi there,
i have an error for “message”: “No token provided!” and inside my postman there is no x-access token. is there something that I am missing ? on my postman there is content-type but not x-access
Running Ubuntu 20.04
It returns Cannot GET /api/auth/signin and Cannot GET /api/auth/signup. It does let me have access to the /api/test/user and /api/test/mod and /api/test/admin (these show {βmessageβ:βNo token provided!β}) and /api/test/all (shows Public Content.)
Does anyone know the issue?
Been trying to integrate the https://bezkoder.com/angular-10-jwt-auth/ into this. Does anyone know how to do it? Please share if you have any example?
I have same problem. try to change usage header in auth-header.js
// return { Authorization: ‘Bearer ‘ + user.accessToken }; // for Spring Boot back-end
return { ‘x-access-token’: user.accessToken }; // for Node.js Express back-end
How can we directly set roles for the user using a form from the frontend rather than using postman?
Hey, great work!
I had a question, How can we directly set roles for the user using a form from the frontend rather than using postman?
Hi and thx for very nice tutorial!
I have problem when I try to login with non-existing user – the node screams about UnhandledPromiseRejectionWarning but I don’t know how and what block should I put inside the try-catch to satisfy node. Do I have to somehow modify app.post(“/api/auth/signin”, controller.signin); ? The findOne already has catch. When I change the exports.signin into exports.signin = async (req, res) => {try {…} catch (err) {..} it isn’t solving the problem. Thank you very much!
Executing (default): SELECT “id”, “username”, “email”, “password”, “createdAt”, “updatedAt” FROM “users” AS “users” WHERE “users”.”username” = ‘testuser’ LIMIT 1;
(node:19868) UnhandledPromiseRejectionWarning: Error: WHERE parameter “email” has invalid “undefined” value (…)
at async Function.findOne (node_modules\sequelize\lib\model.js:1917:12)
(node:19868) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `–unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:19868) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
You need Content-Type:application/json in your request header
When i use post api -> localhost:8080/api/auth/signup
{
“username” : “ahmad”,
“email” : “[email protected]”,
“password”: “1245678”,
“roles” : [“admin”, “user”]
}
I face this error
Unhandled rejection Error: WHERE parameter “username” has invalid “undefined” value
at MySQLQueryGenerator.whereItemQuery (E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\dialects\abstract\query-generator.js:2184:13)
at E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\dialects\abstract\query-generator.js:2173:25
at Array.forEach ()
at MySQLQueryGenerator.whereItemsQuery (E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\dialects\abstract\query-generator.js:2171:35)
at MySQLQueryGenerator.getWhereConditions (E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\dialects\abstract\query-generator.js:2583:19)
at MySQLQueryGenerator.selectQuery (E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\dialects\abstract\query-generator.js:1315:28)
at QueryInterface.select (E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\query-interface.js:1127:27)
at E:\test\node-js-jwt-auth-master\node_modules\sequelize\lib\model.js:1759:34
at tryCatcher (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\promise.js:547:31)
at Promise._settlePromise (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\promise.js:604:18)
at Promise._settlePromise0 (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\promise.js:649:10)
at Promise._settlePromises (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\promise.js:729:18)
at _drainQueueStep (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\async.js:93:12)
at _drainQueue (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\async.js:86:9)
at Async._drainQueues (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (E:\test\node-js-jwt-auth-master\node_modules\bluebird\js\release\async.js:15:14)
at processImmediate (internal/timers.js:456:21)
Hi!
I have found solution. When I chose raw option then I selected Text instead of Json option.
Ok buddy, that’s good
adding app.use(express.json()); in server.js . resolved same in for me.
This was incredibly useful. I’ve recently started learning NodeJs. It’s an awesome framework.
hey bezkoder,
I have this error :
TypeError: Cannot read property ‘username’ of undefined
at exports.signin (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\app\controllers\auth.controller.js:46:26)
at Layer.handle [as handle_request] (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\index.js:275:10)
at C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\app\routes\auth.routes.js:10:5
at Layer.handle [as handle_request] (C:\Users\me\Desktop\env_node\JWT_mysql_node_tut\node_modules\express\lib\router\layer.js:95:5)
and unable to solve it till now. Any solution would be appreciated. Thank you!
Great guide thank you!
Posting this again as you may have missed it.
In your explanation of folder stucture, you have “middleware”.
However you refer to this folder throughout the guide as “middlewares” (plural), when we are creating the files authJwt, index, and verifySignUp.
But, inside the code, you are importing files from the folder “middleware” (singular).
Would advise changing to avoid any confusion on why code isn’t working if people are not checking this.
Again, love all the guides and options you are providing for different stacks.
Best,
Hi, thank you for you comment. I’ve just fixed that typo π
I also wanted to add to this as I had an issue with the correct board being displayed per the users role.
(User, Moderator, Admin)
In the auth-header.js file you have the following object being returned to the user.service.js GET requests:
return { Authorization: “Bearer ” + user.accessToken };
This results in an error of “No token provided”. as it is looking for the header “x-access-token”, not Authorization.bearer
I have changed it to reflect the following, which resulted in a correct display of the board being viewed by the users role.
return { “x-access-token” : user.accessToken };
If the way in which you have described the object in the guide is correct, could you explain a bit further on how that works?
Because I received the error stated above, I have kept my chgange I made until further notice.
Again, thank you!! π
Hi, it is because I use the frontend for 2 backend:
– Spring Boot: using Bearer token
– Node.js: using x-access-token
I write this notification in the frontend tutorial.
How you get roles in middlewares/authJwt.js, since you donβt include const Role?
Hi, please look at how we define Sequelize Associations in
app/models/index.js
. The methoduser.getRoles()
is supported without our implementation.UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Cannot drop table ‘roles’ referenced by a foreign key constraint ‘user_roles_ibfk_1’ on table ‘user_roles’. . this is happen when i try to execute server.js . I know this is an error when i try to delete table that has foreign key , how to fix this in node js .
Hi, try to drop
user_roles
table first.Hi copied your repository and ran it but I got no entries on roles table
Hi, you should change the code in server.js to:
It will create 3 necessary rows first. π
thanks, great tutorial π
Thank you for this article! you made my day <3
please i need an explanation; whats the setRole() for, is it a sequelize function.
.then(roles => {
user.setRoles(roles).then(() => {
res.send({ message: “User was registered successfully!” });
});
});
Hey thanks @bezKoder for such good blog
Hi and thanks bezkoder for this tutorial, it has helped me understand this process better considering I’ve rewritten parts to use node-postgres rather than sequelize since I’m more familiar with SQL than working with ORMs. The conversion “forced” me to learn more Postgresql functionality. Now to tackle the React frontend part where I’ll be using material-ui and formik but still following your React Hooks: JWT Authentication (without Redux) example. Excellent work.
Hi Bezkoder,
Thanks for this tutorial, very helpful. But I don’t understand one of the functions.
What does ‘getRoles()’ from authJwt.js file do?
I cannot see where it is defined or referenced in the project.
Hi, you can see that we use
belongsToMany()
so that Sequelize supports the methodsgetRoles()
for model User.Thank you. I just found more info in the docs: https://sequelize.org/master/class/lib/associations/belongs-to-many.js~BelongsToMany.html, after your comment.
I am trying my best to deconstruct your project without sequelize because I already have an ERD diagram prepared with views, procedures, triggers. I feel this would be more efficient for the DB.
hi, my token is throwing a 500 internal server error. It’s only the token that’s supposed to go in yeah?
fixed it, sorry. Thank you so much for this
Do you have similar example using just mysql and not sequilize? Also can the above examples done using mysql?
Hi Aak,
I’ve just completed this tutorial by converting to using node-postgres rather than use sequelize, so it will be possible. As I’m new to most of this myself and haven’t used MySql I can’t be specific but it should just be a matter of creating the appropriate SQL statements for each of the database queries required.
Best regards,
Everything looks great except I fear many people using this may not realize that adding roles in the signup route is a bad idea. Anyone could hit the api of the site using postgres and create an account with admin privileges if they knew the website used this. I would highly recommend removing removing everything in this if statement and only keeping what is in the else (default User role) in the signup function in auth.user.js
Hi, this is just for development and understand how to run authorization. In real app, we don’t accept anybody signup for all roles.
Hi,
For my use case it’s ideal as I expect the admin to do the signups and allocate roles, so the signup route will be admin role protected.
Hi,
I’m getting an error, When I start the server node server.js. Please find the below error log:
D:\Personal\NodeJS\node-js-jwt-auth>node server.js
D:\Personal\NodeJS\node-js-jwt-auth\server.js:23
db.sequelize.sync();
^
TypeError: Cannot read property ‘sync’ of undefined
at Object. (D:\Personal\NodeJS\node-js-jwt-auth\server.js:23:14)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
Thanks.
Harish
Hi,
I don’t know how to do this initialization.
If anyone has source code, Kindly the share to me.
Thank you so much for these tutorials.
Thanks,
Harish
That’s awesome, thanks!
One quick note: You’ve created the folder as “middlewares” but it’s importing it later as “middleware”. π
amazing, thank you very much greetings from Chile!
Hi greatesolution i tried the CRUD operations and it worked perfectly . I have an error in the api while trying the authentication with mysql. I’m not able to add a new user in both mysql db as well as in server (i.e) in the locahost:8080/api/auth/signup in server . in my db i’m getting the following error
Unhandled rejection SequelizeForeignKeyConstraintError: Cannot add or update a child row: a foreign key constraint fails (`mysql`.`user_roles`, CONSTRAINT `user_roles_ibfk_1` FOREIGN KEY (`roleId`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
Help needed. Thanks in advance!!!
I came across this myself when doing another one of these excellent tutorials. It may be because you already have data in the table. Try truncating that table (or any related tables as well – after backing up or exporting any data) and then run it and it may work. HTH.
Thanks a lot for the Tutorial, it helped me understand a lot I didn’t grasp before. It would be nice if you could make this post a bit clearer:
React + Node.js Express: User Authentication with JWT example
Scrolling through half the page was a little bit confusing to find the implementation.
Besides that I have one question maybe you or someone else here can answer.
const authJwt = {
verifyToken: verifyToken,
isAdmin: isAdmin,
isModerator: isModerator,
isModeratorOrAdmin: isModeratorOrAdmin
};
Everything in these is undefined for me and thus the arrow functions also don’t work. Do you have any idea why that could be the case? I think I’m probably missing something super simple but I don’t know what.
Thanks again for the great tutorial, even with my fails it was easy for me to follow and made some things clear.
First i want thenks for tutorial – it work great … but i dont have rules. I think i dont create or add something. I have profile component from github like everything else. When i try find ROLES_USER, ROLES_ADMIN or ROLES_MODERATOR i cant find it in my code. If i dont give what i have in my code for you please tell me and i add in next comment. Do you know what i miss ?Sorry i dont add “my” code but i dont know what i should add and want know exacly what create ROLES.
PS
Sorry for my english – i know im terrible π
I got this to work on my local development machine using SQL Server (MSSQL) rather than MySQL. Also using Tedious and Express4/Tedious. Now trying to publish the Express app to Azure and unable to get to any of the ‘auth’ routes. It returns Cannot GET /api/auth/signin and Cannot GET /api/auth/signup. It does let me have access to the /api/test/user and /api/test/mod and /api/test/admin (these show {“message”:”No token provided!”}) and /api/test/all (shows Public Content.) All my other routes are protected, so they also show up as {“message”:”No token provided!”}. How does one go about getting the auth routes to work in Azure?
Great work, quick question, why when i add a new model (table), it still enforces createdAt and updatedAt fields to be there? how can i remove this enforcement pls? much thankkkks
createdAt: {
type: Sequelize.DATE,
field: ‘creado’
},
This article is great.
The checkDuplicateUserNameOrEmail function check email only when username is already in use. Maybe you should check email only when username is not in use.
Thanks.
Hi, first of all, thank you for your guidance. Can you make a tutorial about Node.js Token Based Authentication & Authorization example without ORM Sequelize? Thank you!
If i see well in this app everybody can register as admin.
How would you add another protected route without sequelize?
I have a route /alignments that I would like to add as a protected route. I’m trying to get it to work like the user route. I tried to add it to /user/alignments but that didn’t work either. Please help!
Thanks for the great tutorial! I got this working with SQL Server using tedious and express4-tedious. Didn’t need mysql2 so uninstalled it. So I have a route set up in express4-tedious that I would like to only be available if a user (ROLE_USER) is logged in:
app.use(‘/alignments’, require(‘./app/routes/alignments’));
(in server.js)
I have nothing against myql. Just need to use a mssql database because of some spatial functions that are not available in mysql, for example:
/* GET alignments listing. */
router.get(‘/’, function (req, res) {
req.sql(“select id, fid, GeomCol1.AsTextZM() as alignmentwkt, GeomCol1.STSrid as srid, aligngrp1, aligngrp2, alignment, GeomCol1.STLength() as length, lrs.STStartMeasure(GeomCol1) as startm, lrs.STEndMeasure(GeomCol1) as endm, lrs.STMeasureRange(GeomCol1) as measure_range, hascurve, numsegs, thumbnail, mapurl from alignmentstest4 order by aligngrp1 asc, aligngrp2 asc, alignment asc for json path”)
.into(res, ‘[]’);
});
(in routes/alignments.js)
So how would you go about making this new /alignments route available to only users who are logged in?
Going further, there will be some POSTs and PUTs that I would like only moderators or admins to be able to get access to:
/* PUT update station/offset/point. */
router.put(‘/ptso/put/update/:ptid’, textParser, function (req, res) {
req.sql(“exec update_pt_so_h @ptid, @pts”)
.param(‘ptid’, req.params.ptid, TYPES.Int)
.param(‘pts’, req.body, TYPES.NVarChar)
.exec(res);
});
Any pointers you can give will be appreciated. I’m very new to Express and have been working with React for a couple of months.
Thanks again for a great tutorial!
Thank you very much! Very interesting and useful!!
can you write refresh token code
Hi, here you are: JWT Refresh Token implementation in Node.js example
Is this a micro service architecture ?
Hi bezkoder! Been working with some of your tutorials recently, which have been so great, and I’m trying to get a website up on my namecheap hosting server. When I have the API backend loaded and started server.js, I’m able to successfully register and login through the cPanel terminal using curl commands.
So today I went through your “Vue.js JWT Authentication with Vuex and Vue Router” tutorial, and everything works in testing when connecting to a MySQL database on my local computer, but after loading my build to the server, I’m getting “net::ERR_CONNECTION_REFUSED”. At first I was getting a CORS error, so I changed the corsOptions origin value to my domain, thinking that would work. I’m no longer getting the CORS error message.. just “net::ERR_CONNECTION_REFUSED”.
Any ideas? Thank you!!
Hi, please show me your browser console log.
Thanks for your help!!
https://auel.dev/dinner-robot/ERR_CONNECTION_REFUSED.png
Hi, the message said that: “username is already in use!”. So did you try to signup with another one?
Hi, great tutorial. btw have u tutorial for logout jwt? and is it good to save jwt in the database?
Hi, we’re gonna save the Refresh Token in the database. I will write a tutorial for this when having time π
node run server stuck at:
Executing (default): CREATE TABLE IF NOT EXISTS `roles` (`role_id` INTEGER , `role_code` VARCHAR(255), `role_descr` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`role_id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `roles`
Hi, please send more log details about the issue.
Thanks for your quick reply but I’ve figured out the issue. server was running fine there was some other error in my code.
i also stuck at ‘ SHOW INDEX FROM `user_roles`’ what is solution for that?
Great tutorial, thanks a lot.
Can you implement this with refresh token rotation method.
Thanks in Advance
Hi, I will write the tutorial when having time π
Hi, here you are: JWT Refresh Token implementation in Node.js example
bezkoder, excellent tutorial. Complete and well thought out. I’m facing an issue that you have appeared to solve, but for the life of me, I cant replicate from your tutorial into my own code.
I have react/redux front-end with express.js api.
Login works and returns a token.
Attempts to access endpoints with the x-access-token fail from localhost, but succeed from PostMan.
Attempts from localhost give the below error:
Access to fetch at ‘https:///dev/buyer’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Request header field x-access-token is not allowed by Access-Control-Allow-Headers in preflight response.
I have the below cors configuration
I dont understand why PostMan would work, but my localhost will not.
Hi, your server should return that it accepts custom headers:
Hi,
I am very new to backend. I follow the tutorial and also clone the repo but always showing the message “Coluld not get any response”. Please let me know what should I have to do. do I need to install any software along. like mySql?
Hi, the example works with MySQL database, so you MUST install MySQL and configure appropriate db parameters π
Love your tutorials! Quick question, can you explain why the corsOptions.origin is set to http://localhost:8081, when the server is setup to listen on http://localhost:8080?
You stated: “Notice that we set origin: http://localhost:8081“, but did not provide an explanation of why this is different from the listening port.
If you use a REST Client such as Postman, you call API from the same origin
http://localhost:8080
. It is ok and CORS doesn’t need to work here.But when you send HTTP request from another origin (another front-end app with another port: Angular, React, Vue…), for example:
http://localhost:8081
, you must accept the Cross-origin resource sharing (CORS). It is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.I am having an issue with
user.setRoles()
is not a function in mysignUp
request:{
“message”: “user.setRoles is not a function”
}
Hi, please make sure that you’ve initialized Sequelize object and models correctly.
Hi i have the same error, I was wondering if you could explain where the setRoles function is coming from, is it automatically generated?
Hi, it is automatically generated by Sequelize π
Hi, thanks for your tutorial π
I fixed this issue with an alias :
I hope that help you π
Hi really great tutorial.
how to insert data to multiple tables at a time – parent/child relationship in nodejs to mySql ?
Could you help me? Iβm new to node.js Development.
Relationship between Product & ProductDetails tables.
Sample JSON object:
Hi, I think you should rename the entities first, for example:
– ProductName -> Category
– ProductDetails -> Product
Then you can read this tutorial for working with One-to-Many Relationship in Node.js:
Sequelize One-to-Many Association example with Node.js & MySQL
Thank you so much , its improves productivity in less time and works fine π
Hi,
Really it’s a good tutorial.Is there anyway to generate( swagger integration) some default documentation without writing the API Documentations (comments) manually? Like in ASP.NET core.
Sample swagger documentation comments in each routing page:
/**
* @swagger
* /registerUser:
* post:
* tags:
* – Users
* name: Register
* summary: Register a new user
* consumes:
* – application/json
* produces:
* – application/json
* parameters:
* – name: body
* in: body
* schema:
* $ref: ‘#/definitions/User’
* type: object
* properties:
* first_name:
* type: string
* last_name:
* type: string
* username:
* type: string
* email:
* type: string
* password:
* type: string
* format: password
* required:
* – username
* – email
* – password
* responses:
* ‘200’:
* description: User created
* ‘403’:
* description: Username or email already taken
*/
Thanks in advance.
You can check out Sequelize, an ORM for Node. It is easy to use and provides ability to represent such relationships
how can i integrate in your existing crud application model? that is tutorials?
Hi, you can create more routes and controllers, then apply auth middleware on the routes π
Hi Mr Bezkoder,
Congratulations on this excellent tutorial. That’s what I’ve been looking for ever since.
However, I have a hard time integrating this Backend into uen Development FrontEnd React with Redux and JWT Passport.
Could you help me? I’m new to ReactJS Development.
Thank you
Hi, I will write the tutorial when having time π
Thanks for this useful tutorial. When I run the node server.js after cloned the source code from GitHub I have following error. Unfortunately I couldn’t find any solution for that. Do you have any suggestions for that?
Unhandled rejection SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
at C:\Users\ShojaMo\webApp\tasktracker\node_modules\sequelize\lib\dialects\mysql\connection-manager.js:123:19
at tryCatcher (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\promise.js:547:31)
at Promise._settlePromise (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\promise.js:604:18)
at Promise._settlePromise0 (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\promise.js:649:10)
at Promise._settlePromises (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\promise.js:725:18)
at _drainQueueStep (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\async.js:93:12)
at _drainQueue (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\async.js:86:9)
at Async._drainQueues (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (C:\Users\ShojaMo\webApp\tasktracker\node_modules\bluebird\js\release\async.js:15:14)
at processImmediate (internal/timers.js:456:21)
Hi, please make sure that you’ve already run MySQL database with correct configuration.
Thank you for quick response π
Hi, I’m connecting in my db normaly using MySQL Workbench, but when I try to conect the application with database I have the follow error:
Unhandled rejection SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
How said Mohsen , infortunately I couldnβt find any solution for that. Do you have any others suggestions for that?
Resolved! My config db was wrong kkkkkkk
Actually, I ran the code on Win and Mac and both have the same issue! It looks like something is wrong when it tries to run the database. Thanks in advance for any suggestions.
Bezkoder, your tutorials are just awesome, thank you very much for your work π
Maybe u have this version without roles(admin, moder) only user?
If yes, could you please share it?
Hi, admin or moderator is just a role. You can remove them in the define steps of the model.
Try your best to do it. π
Great article loved it..how would implement it with refresh tokens? Thanks in advance
Hi, here you are: JWT Refresh Token implementation in Node.js example
Thanks for sharing your code for this Node.js JWT auth. It works like a charm!
Thank you so much, this is one of the best Node.js JWT tutorial I’ve read!
HI, I love your work i found this walk through complete.
Hi, really Great Tutorial, but i have the problem,
when Access protected resources: GET /api/test/mod
Access protected resources: GET /api/test/mod
Error: Unhandled rejection TypeError: Cannot read property ‘getRoles’ of null
Access protected resources: GET /api/test/admin
Error: Unhandled rejection TypeError: Cannot read property βgetRolesβ of null
Hi, did you run
initial()
function to create 3 row inroles
table?Can we have a version without serialize please? I already made my tables using serialize messes my erd design π
Hi, you can find it here: Build Node.js Rest APIs with Express & MySQL
I am not able to signup and login based on User Mod,Admin
Hi, please make sure that you’ve inserted 3 rows into Roles table first.
hi, their are three rows in roles table with user, moderator and admin names but still when i signup on application, user always becomes user not admin or moderator?
Please help me with this problem?
Hi. I have a problem whereby every time I start the server through “node server.js” command everything in the database gets reset. It’s making development a bit harder. Can you help with this??
Hi, you can change:
db.sequelize.sync({force: true})
to:
db.sequelize.sync()
Hi, really Great Tutorial, but i have the problem, that the Signup doesnt work
I checked out your source code from github, but i get the following message:
Unhandled rejection Error: WHERE parameter “username” has invalid “undefined” value
I think it is inside the verifysignup middleware – maybe you can imagine whats wrong?
Thanks in Advance
Hi, how did you send POST request? Did you set appropriate Header:
Content-Type: application/json
?Thank you! In postman, I had to change the content type from Text to JSON, and now it works π
For those looking for it, it’s below the text field where you input “http://localhost:8080/api/auth/signup”
Hello
Do we need to use POSTMAN to put this link http://localhost:8080/api/auth/signup ?
shift these lines:
// routes
require(‘./app/routes/auth.routes’)(app);
require(‘./app/routes/user.routes’)(app);
below :
// parse requests of content-type – application/json
app.use(bodyParser.json());
// parse requests of content-type – application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
It will work, the issue is routes are called before parsing JSON so it gets undefined in the body.
Hope this will help someone facing the same issue.
Thanks a lot, bezkoder for this great tutorial π
Did not work.
TypeError: Cannot read property ‘username’ of undefined
Try to restart node server..
Thankyou Rahul, your solution works just awesome
I get a similar error, but when trying just to run the server (node server.js):
TypeError: Cannot read properties of undefined (reading ‘signup’)
at module.exports ([project path]\apps\routes\auth.routes.js:19:21)
at Object. ([project path]\server.js:9:37)
Since nobody else gets the same error, I’m thinking that I have something amiss in my code, but I checked against the code in GIT and I can’t find any discrepancy. What can you suggest?
Thank you!
Great Tutorial, thank you very much! It helped very much with my project π I still have one question though – I hope you’ll be able to help:
Everything is working and I am trying to build a page where an admin can change the User Roles of a specific user. Right now, I have no Idea what to change or how I would implement this on the backend site. How can I update a User and send a new array of roles to the backend and update the belongsToMany association?
Thanks in advance!
Hi, you can add a new route with
[authJwt.verifyToken, authJwt.isAdmin]
middlewares. This route calls controller method that updates just one table: user_roles.Hi Ben, I’m trying to implement the same thing.
Did you achieve a solution to it?
Solved, thanks a lot Bezkoder!
Great walkthrough! Helped a lot.
I like the way that you organize the models, controllers and routes in every tutorial.
Thanks! I’m so happy to here that.
Can u provide this in nestjs and in typeorm mysql.
I need to learn to work with nestjs.
Thanks
Great job, thanks a lot!
Just one question, can we integrate this with sequelize migrate due to the fact that it makes the job easier for entitites
Yes, we can. But in this tutorial, I want to keep everything simple and clean, so we don’t use sequelize migrate π
Thanks a lot, this is the best explanation I’ve found, I’m learning a lot from your articles, If I will find you on social media (Medium and others) I’ll be following you.
Great work, thanks a bunch.
I have a simple question, you’re using those methods which you didn’t define like user.getRoles() but you never defined these methods. I tried to read on sequelize custom setters and getters but about setters and getters they must be defined on a model but these were used without definition so I wanted to know where they’re coming from.
This is the magic of sequelize, please read the docs