Categories
Node.js Basics

Node.js Basics — Add Authentication to an Express App with jsonwebtoken

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Bearer Token Authentication

We can generate a token to identify authenticated users.

When they want to make requests to our server, they send in the auth token to our server to decode it.

If it’s decoded successfully, then we let the user make the request.

We can install the jsonwebtoken package by running:

npm i jsonwebtoken

Then we can use it by writing:

const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');

const users = {
  foo: {
    username: 'foo',
    password: 'bar',
    id: 1
  },
  bar: {
    username: 'bar',
    password: 'foo',
    id: 2
  }
}

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

app.use(express.static('public'));
app.get('/', (req, res) => {
  res.sendFile('public/index.html');
});

app.post(
  '/login',
  function(req, res) {
    const {
      username,
      password
    } = req.body;
    const user = users[username];
    if (user === undefined) {
      return res.status(401).send('invalid user')
    }
    if (user.password !== password) {
      return res.status(401).send('invalid password')
    }

    const {
      id
    } = user;
    jwt.sign({
      id,
      username
    }, 'shhhhh', function(err, token) {
      res.send(token);
    });
  }
);

app.listen(3000, () => console.log('server started'));

In the /login route, we get the username and password properties that we make a request within the JSON request body.

Then we check the user in the users object.

If the username or password is invalid, then we send the status 401 with a message indicating the error.

Once everything is valid, then we create the token with the jwt.sign method.

The first argument is the data that will be in the token.

Then 2nd is the secret that we sign the token with.

The last argument is the callback that’s run when the token is created.

Then we send the token back to the client.

So if we make a POST request with the /login route and the following request body:

{
    "username": "foo",
    "password": "a"
}

We get 'invalid password' return with the 401 status.

If we make the same request with a valid body like:

{
    "username": "foo",
    "password": "bar"
}

Then we get a signed token like:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJmb28iLCJpYXQiOjE2MDA2MjUzOTd9.05p7hoD3Qma4ShXIVWi0pKBQIv4wqSvEIvuNhaJtens

Once we decode it, we should get all the data in the object returned.

To verify the token, we can use the jwt.verify method. For example, we can write:

const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');

const users = {
  foo: {
    username: 'foo',
    password: 'bar',
    id: 1
  },
  bar: {
    username: 'bar',
    password: 'foo',
    id: 2
  }
}

const app = express();
const SECRET= 'shhhhh';

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

app.use(express.static('public'));
app.get('/', (req, res) => {
  res.sendFile('public/index.html');
});

app.post(
  '/login',
  function(req, res) {
    const {
      username,
      password
    } = req.body;
    const user = users[username];
    if (user === undefined) {
      return res.status(401).send('invalid user')
    }
    if (user.password !== password) {
      return res.status(401).send('invalid password')
    }

const {
      id
    } = user;
    jwt.sign({
      id,
      username
    }, SECRET, function(err, token) {
      res.send(token);
    });
  }
);

app.get('/secret', (req, res, next) => {
  console.log(req.headers)
  jwt.verify(req.headers.authorization, SECRET, function(err, decoded) {
    if (err){
      return res.status(403).send('unauthorized')
    }
    req.user = decoded;
    next()
  });
}, (req, res)=>{
  res.json(req.user);
})

app.listen(3000, () => console.log('server started'));

We added the /secret route that has a middleware that checks the Authorization header for the token.

Then we pass that into the jwt.verify method to check the token.

The 2nd argument is the same secret string that we used to sign the token.

We need this to do the check properly.

Then once we decoded the string, we return 403 error if there’s an error.

Otherwise, we set req.user to the decoded token object so we can use it in our route.

Then we call next to call the route handler.

If we make a GET request to the /secret route, we should get the user data returned in the response.

Conclusion

We can use the jsonwebtoken package to issue and verify JSON web tokens for authentication.

Categories
Node.js Basics

Node.js Basics — Add 3rd Party Authentication to an Express App with Auth0

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Set Up Our App in Auth0

Before we write our app, we have to set up our Node app in Auth0.

To create our app in Auth0, we log into Auth0, then we go to https://manage.auth0.com/dashboard/us/dev-v7h077zn/applications to go to the Applications page.

Then we click Create Application to create a new application.

Once we did that, we click on Regular Web App, then click Create.

Then we click on Node.js to create our app.

Create the Express App

Once we created our Express app, we can write the following to create our app:

const express = require('express');
const bodyParser = require('body-parser');
const { auth } = require('express-openid-connect');
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

const config = {
    authRequired: false,
    auth0Logout: true,
    secret: 'a long, randomly-generated string stored in env',
    baseURL: 'http://localhost:3000',
    clientID: 'client id',
    issuerBaseURL: 'https://<domain>.us.auth0.com'
};

// auth router attaches /login, /logout, and /callback routes to the baseURL
app.use(auth(config));

// req.isAuthenticated is provided from the auth router
app.get('/', (req, res) => {
    res.send(req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out');
});

app.listen(3000, () => console.log('server started'));

We install the express-openid-connect package to let us add authentication with Open ID.

To install it, we run:

npm i express-openid-connect

to install the package.

We call the app.use(auth(config)); to add the routes for login, logout, and the callback route that’s called after authentication succeeds.

Then we can go to the / route and see if we’re authenticated or not.

We check if we’re authenticated by calling the req.oidc.isAuthenticated() method.

The config object has the clientID, issuerBaseURL, baseURL, and the secret properties.

We can get all them all from the app’s page in our Auth0 account.

issuerBaseURL is the domain that our app is hosted on.

Now when we go to http://localhost:3000/login , we should be able to log in with a Google account.

Getting Logged in User’s Data

To get the data of the currently logged in user, we can write:

const express = require('express');
const bodyParser = require('body-parser');
const { auth, requiresAuth } = require('express-openid-connect');
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

const config = {
    authRequired: false,
    auth0Logout: true,
    secret: 'a long, randomly-generated string stored in env',
    baseURL: 'http://localhost:3000',
    clientID: 'client id',
    issuerBaseURL: 'https://<domain>.us.auth0.com'
};

// auth router attaches /login, /logout, and /callback routes to the baseURL
app.use(auth(config));

// req.isAuthenticated is provided from the auth router
app.get('/', (req, res) => {
    res.send(req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out');
});

app.get('/profile', requiresAuth(), (req, res) => {
    res.send(JSON.stringify(req.oidc.user));
});

app.listen(3000, () => console.log('server started'));

We add the /profile route with the middleware returned by the requiresAuth function to make it available only to authenticated users.

Then the req.oidc.user property has the user data.

Once we logged into the Google account, we should see the data from the /profile route.

Conclusion

We can add 3rd party auth into our Express app easily with Auth0.

Categories
Node.js Basics

Node.js Basics — HTTP

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

HTTP

The http module is a module that comes with the Node.js runtime environment.

We can use it to create a simple HTTP server.

All we have to do is to require the HTTP package by writing:

const http = require('http');
const server = http.createServer();
server.listen(8080, () => {
  console.log( 'Listening on port 8080' );
});

We require the HTTP module and then call the createServer method on the imported module to create our server.

Then we call the listen method on the server object to listen for requests on port 8080.

If we want to to handle requests and return responses, we can use the request and response parameters to get the request data and create the response respectively.

For example, we can write:

const http = require('http');
let count = 0;
const server = http.createServer((request, response) => {
  count += 1;
  response.writeHead(201, {
    'Content-Type': 'text/plain'
  });
  const message = `count: ${count}`;
  response.end(message);
});
server.listen(8080, () => {
  console.log('Listening on port 8080');
});

We use the methods in the response object to create the response that we return to the user.

We call the writeHead method with the status code and the response headers that we want to return.

The Content-Type header is set to text/plain so that we can let the client know what the data type of the response is.

201 status means a new object is created.

The response.end method lets us return the response body to the client.

To get request data, we can use the properties of the request parameter.

For example, we can write:

const http = require('http');
let count = 0;
const server = http.createServer((request, response) => {
  count += 1;
  response.writeHead( 201, {
    'Content-Type': 'text/plain'
  });
  const message = `count: ${count}, path: ${request.url}`;
  response.end(message);
});
server.listen(8080, () => {
  console.log('Listening on port 8080');
});

to get the path of the URL with the request.url property and return it with the response body.

Routing

Since we have access to the URL that the request is made to, we can do something according to the URL that the user is accessing.

For example, we can write:

const http = require('http');
let count = 0;
const server = http.createServer((request, response) => {
  let message,
    status = 200;
  count += 1;
  switch (request.url) {
    case '/count':
      message = count.toString();
      break;
    case '/hello':
      message = 'World';
      break;
    default:
      status = 404;
      message = 'Not Found';
      break;
  }
  response.writeHead(status, {
    'Content-Type': 'text/plain'
  });
  response.end(message);
});
server.listen(8080, () => {
  console.log('Listening on port 8080');
});

to send different responses according to the URL that is given.

If request.url is /count then we return the value of the count with the 200 status.

If request.url is /hello , then we return 'World' with the 200 status.

Otherwise, we return 'Not Found' with a 404 status.

Conclusion

We can create a simple HTTP server with the Node.js’s built-in http module.

Categories
Node.js Basics

Node.js Basics — Handle Complex HTTP Requests

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Complex Routing

It’s easy to do simple routing with our own code with our own HTTP server, but if we want to add more complex routing, then we can use the router module to help us do this.

To use it, we install the router and finalhandler packages by running:

npm i router finalhandler

to install the packages.

Then we can use it to handle requests by writing:

const finalhandler = require('finalhandler')
const http = require('http')
const Router = require('router')

const router = Router()
router.get('/', (req, res) => {
  res.setHeader('Content-Type', 'text/plain; charset=utf-8')
  res.end('Hello World!')
})

const server = http.createServer((req, res) => {
  router(req, res, finalhandler(req, res))
})

server.listen(8080)

We create the Router instance and then call the get method on it to create a GET route to let us handle GET requests to the / route.

The res.setHeader method lets us set the response header.

And the res.end method lets us set the response body.

To accept URL parameters, we can write:

const finalhandler = require('finalhandler')
const http = require('http')
const Router = require('router')

const router = Router({ mergeParams: true })
router.route('/pet/:id')
  .get(function (req, res) {
    res.setHeader('Content-Type', 'application/json')
    res.end(JSON.stringify({ name: 'tobi', id: req.params.id }))
  })
  .delete(function (req, res) {
    res.end()
  })
  .all(function (req, res) {
    res.statusCode = 405
    res.end()
  })

const server = http.createServer((req, res) => {
  router(req, res, finalhandler(req, res))
})

server.listen(8080)

We pass in an object to the Router function with the mergParams property set to true so that we can accept URL parameters.

Then we can use the route method to define routes that takes the id parameter.

The :id substring is the URL parameter placeholder for the id parameter.

Then we call res.setHeader to set the header.

And we use the req.params.id property to get the value of the id URL parameter.

We set the res.statusCode property to set the response status code.

The delete method lets us define a route to handle a DELETE request.

We can also add a middleware that runs before our routes run.

For example, we can write:

const finalhandler = require('finalhandler')
const http = require('http')
const Router = require('router')

const router = Router({
  mergeParams: true
})
router.use(function(request, response, next) {
  console.log('middleware executed');
  next(null);
});
router.route('/pet/:id')
  .get(function(req, res) {
    res.setHeader('Content-Type', 'application/json')
    res.end(JSON.stringify({
      name: 'tobi',
      id: req.params.id
    }))
  })
  .delete(function(req, res) {
    res.end()
  })
  .all(function(req, res) {
    res.statusCode = 405
    res.end()
  })

const server = http.createServer((req, res) => {
  router(req, res, finalhandler(req, res))
})

server.listen(8080)

We call the use method with a function. This function is called before any route handler is called.

Therefore, we should see 'middleware executed' string logged in the console.

The next function lets us call the route handler.

Conclusion

We can create more complex route handlers for our HTTP server with the router package.

Categories
Node.js Basics

Node.js Basics — Getting Started

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Installation

We can install the latest Node.js version at https://nodejs.org/en/download/

This lets us download binaries for Windows and macOS.

If we’re using Linux, then we can run:

# Using Ubuntu
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -sL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs

to install Node.js 14.x.

Then we can create a file called example.js and write:

console.log("Hello world")

If we run node example.js , we should see ‘Hello world’ displayed.

Requiring Packages

Node.js comes with its own module system.

It uses the CommonJS module system which lets us import modules.

Modules are just JavaScript files that export something so other modules can use the exported items.

For example, to create and use modules, we can write:

index.js

const util = require("./utils");
util.logger.log("cool");

utils/index.js

const Logger = require("./logger");
exports.logger = new Logger();

utils/logger.js

class Logger{
  log(...args) {
    console.log(args);
  };
}
module.exports = Logger;

In the utils folder, we have 2 modules, which are index.js and logger.js

logger.js exports the Logger class by setting the class as the value of the module.exports property.

Then in utils/index.js , we called require with the relative path to the logger.js file to import the Logger class.

We export the logger by creating the exports.logger property and then assigning the Logger instance to it.

Then in index.js , we call require to import utils/index.js by writing:

const util = require("./utils");

If the file we require is called index.js , then we don’t need to include the file name.

Also, we don’t need to include the file extension for JavaScript modules.

Then to call the log method, we run:

util.logger.log("This is pretty cool");

We access exports.logger by using the utils.logger property.

Now we should see 'cool' displayed on the screen.

NPM

NPM is the most popular package manager for JavaScript apps.

To download packages with it, we can run the npm install command.

For example, if we want to install the chalk package so that we can see colored text on our console, we run npm install chalk .

Then we can use the package by writing:

const chalk = require("chalk");
console.log("I am just normal text")
console.log(chalk.green( "I am green text" ))

We call chalk.green by calling the chalk.green method from the chalk package.

The module will be installed into the node_modules folder of your project folder.

When we require it, it’ll automatically be picked up by Node.js from that folder.

Then package.json and package-lock.json file will be created when we install the packages.

If they aren’t there, we can run:

npm init

to add those files.

We’ll be asked some questions like the project name and other project data.

Conclusion

We can create Node.js apps by creating modules or using third party modules and use them in our own modules.