A guide to authentication tutorial with Express.js

A guide to authentication tutorial with Express.js

Authentication is an important issue when creating a dynamic web application. This article should clear things up and provide a guide to authentication tutorial with Express.js

Authentication is an important issue when creating a dynamic web application. This article should clear things up and provide a guide to authentication tutorial with Express.js

Building web pages with user authentication can be a huge pain. You typically need to set up some sort of database to manage users even if you're not using the database for anything else. You would then need to store their password hashes, and you almost need a degree on internet security to know the safest ways to do that.

What if I told you it didn't have to be so complicated? Using Okta and Express, I'll show you how to really quickly set up a website that has secure user authentication, without the need for a separate database. Everything you need you could deploy anywhere that you can run Node.

Create a New App in Express

Creating a new app in Express doesn't take a lot of code. You'll need to set up your project structure and install some dependencies, which you can do with just a few commands:

mkdir new-project
cd new-project
npm init -y
npm install [email protected] [email protected]
npm install --save-dev [email protected] [email protected]

Edit the "scripts" section of your package.json to look like this:

"scripts": {
  "start": "nodemon .",
  "test": "standard"
},

Now create a new file index.js :

index.js

const express = require('express')
const path = require('path')

const app = express()

app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'hbs')

app.use(express.urlencoded({ extended: true }))
app.use('/static', express.static('public'))

// @TODO add auth middleware
// @TODO add registration page
// @TODO add logout route

app.use('/', require('./routes/index'))

const port = process.env.PORT || 3000
app.listen(port, () => console.log(`App listening on port ${port}`))

Make a few new folders as well:

mkdir -p public/images routes views

Put a fun greeting image in public/images/greeting.jpg that you will use to greet users.

Express allows for a templating engine. You already set up Handlebars (hbs) above, so now you can create a couple of views. One will be the HTML skeleton that contains the basic markup, and the other will be your homepage (the index view).

views/layout.hbs










  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
    crossorigin="anonymous">

  Simple Auth in 15 Minutes





      [Navbar](/ "Navbar")
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup"
        aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">




          {{!-- @TODO add auth links --}}




  {{{body}}}








This layout will get rendered for each view, with the specific view replacing the {{{body}}} tag.

Now you can create the indexview. This will just display the image you put in public/images/greeting.jpg :

views/index.hbs


  ![](/static/images/greeting.jpg)

To tell the homepage to use that file when rendering, you'll also need to create a router. You already required routes/index.jsin the index.js file of your app, so now you just need to create that file:

routes/index.js

const express = require('express')
const router = express.Router()

router.get('/', (req, res) => {
  res.render('index')
})

module.exports = router

The call to res.render('index') tells Express to use the render the index.hbs view and respond with the results back to the client. You can also pass in some context, but it's not needed here just yet.

Now you can run your server with the following command (as you make changes, the server will reload and you'll just need to refresh the page):

npm start

Go to [http://localhost:3000](http://localhost:3000) to see your greeting.

A guide to authentication tutorial with Express.js

Add Authentication to Your Express App

You now have a simple web server with a homepage and a lovely greeting image. The next step I promised to show you is to add secure user authentication. This is where Okta comes in to play. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

  • Authenticate and authorize your users
  • Store data about your users
  • Perform password-based and social login
  • Secure your application with multi-factor authentication
  • And much more! Check out our product documentation

If you don't already have one, sign up for a forever-free developer account.

You're going to need to save some information to use in the app. Create a new file named .env in the root of your application. In it, enter your organization URL.

HOST_URL=http://localhost:3000
OKTA_ORG_URL=https://{yourOktaOrgUrl}

You will also need a random string to use as an App Secret for sessions. You can generate this with the following command:

npm install -g uuid-cli
echo "APP_SECRET=`uuid`" >> .env

Next, log in to your Okta developer console, navigate to Applications, then click Add Application. Select Web, then click Next.

A guide to authentication tutorial with Express.js

The page you come to after creating an application has some more information you need to save to your .env file. Copy in the client ID and client secret.

OKTA_CLIENT_ID={yourClientId}
OKTA_CLIENT_SECRET={yourClientSecret}

At the time of this writing, the default application creation page does not allow you to add a Logout redirect URI, but you can add one after creating the application. After creating the application, click Edit, then next to Logout redirect URIs click Add URI. Add a logout redirect URI of [http://localhost:3000](http://localhost:3000) and click Save.

The last piece of information you need from Okta is an API token. In your developer console, navigate to API -> Tokens, then click on Create Token. You can have many tokens, so just give this one a name that reminds you what it's for, like "15 Minute Auth". You'll be given a token that you can only see right now. If you lose the token, you'll have to create another one. Add this to .env also.

OKTA_TOKEN={yourOktaAPIToken}

Add Auth Middleware to Your Express App

Okta provides some middleware that will give you information about whether the user is registered or not. It also gives you a login page by default at /login . Add the following dependencies:

npm install [email protected] [email protected] @okta/[email protected] @okta/[email protected]

In your index.js page, replace the // @TODO add auth middleware comment with the following code:

app.use(require('express-session')({
  secret: process.env.APP_SECRET,
  resave: true,
  saveUninitialized: false
}))

const { ExpressOIDC } = require('@okta/oidc-middleware')
const oidc = new ExpressOIDC({
  issuer: `${process.env.OKTA_ORG_URL}/oauth2/default`,
  client_id: process.env.OKTA_CLIENT_ID,
  client_secret: process.env.OKTA_CLIENT_SECRET,
  redirect_uri: `${process.env.HOST_URL}/authorization-code/callback`,
  scope: 'openid profile'
})

app.use(oidc.router)

Also, make sure to add the following to the very top of index.js . This needs to be there before any other code in order to load your environment variables, so it should be the very first line of the file:

require('dotenv').config()

Create a Registration Page

You should now be able to login by going to /login . This will redirect you to your Okta developer page, and after you sign in you'll be redirected back to the homepage.

For people who aren't registered yet, they'll need a registration page. At the time of this writing, Okta doesn't provide a registration page out of the box, but you can build one pretty quickly. Create a new view for your route:

views/register.hbs


  {{#each fields}}

    {{this.label}}
    <input
      required
      name="{{this.name}}"
      type="{{this.type}}"
      class="form-control {{#if this.error}}is-invalid{{/if}}"
      value="{{this.value}}"
    />
    {{this.error}}


  {{/each}}
  Register

You'll also need a new route:

routes/register.js

const okta = require('@okta/okta-sdk-nodejs')
const express = require('express')

const router = express.Router()

const client = new okta.Client({
  orgUrl: process.env.OKTA_ORG_URL,
  token: process.env.OKTA_TOKEN
})

// Take the user to the homepage if they're already logged in
router.use('/', (req, res, next) => {
  if (req.userContext) {
    return res.redirect('/')
  }
  next()
})

const fields = [
  { name: 'firstName', label: 'First Name' },
  { name: 'lastName', label: 'Last Name' },
  { name: 'email', label: 'Email', type: 'email' },
  { name: 'password', label: 'Password', type: 'password' }
]

router.get('/', (req, res) => {
  res.render('register', { fields })
})

router.post('/', async (req, res) => {
  const { body } = req

  try {
    await client.createUser({
      profile: {
        firstName: body.firstName,
        lastName: body.lastName,
        email: body.email,
        login: body.email
      },
      credentials: {
        password: {
          value: body.password
        }
      }
    })

    res.redirect('/')
  } catch ({ errorCauses }) {
    const errors = {}

    errorCauses.forEach(({ errorSummary }) => {
      const [, field, error] = /^(.+?): (.+)$/.exec(errorSummary)
      errors[field] = error
    })

    res.render('register', {
      errors,
      fields: fields.map(field => ({
        ...field,
        error: errors[field.name],
        value: body[field.name]
      }))
    })
  }
})

module.exports = router

To tie this all together, in your root index.js file, make sure to replace the // @TODO add registration page comment with the following:

app.use('/register', require('./routes/register'))

You can now have users register. If they run into an error, it will be displayed with the field that caused the error.

A guide to authentication tutorial with Express.js

Add a Logout Route

At the time of this writing, Okta's middleware doesn't provide a default /logout route. Luckily, adding one is fairly simple. In your index.js file, replace the // @TODO add logout route comment with:

app.get('/logout', (req, res) => {
  if (req.userContext) {
    const idToken = req.userContext.tokens.id_token
    const to = encodeURI(process.env.HOST_URL)
    const params = id_token_hint=${idToken}&post_logout_redirect_uri=${to}
    req.logout()
    res.redirect(${process.env.OKTA_ORG_URL}/oauth2/default/v1/logout?${params})
  } else {
    res.redirect('/')
  }
})

If you're logged in, this will invalidate the token and delete the user's session. It will then redirect you back to the homepage. If you're not logged in, it just takes you back to the homepage.

To more easily expose these routes to the user, you can add some buttons. You'll need to expose the user context to the view to know if a user is logged in or not so you know which buttons to display, and potentially greet the user.

In routes/index.js replace the res.render('index') line with the following:

routes/index.js

const { userContext } = req
res.render('index', { userContext })

While you're at it, you can also prevent the user from seeing your greeting unless they're logged in. Change your views/index.hbs file to the following:

views/index.hbs

{{#if userContext}}
  # Hi {{userContext.userinfo.given_name}}!


    ![](/static/images/greeting.jpg)

{{else}}
  # Please log in

{{/if}}

Now to add the buttons. In views/layout.hbs, replace the {{!-- @TODO add auth links --}} comment with the following:

views/layout.hbs

{{#if userContext}}
  [Log out](/logout "Log out")
{{else}}
  [Log in](/login "Log in")
  [Register](/register "Register")
{{/if}}

Check out the final product to make sure it works

A guide to authentication tutorial with Express.js

node-js express web-development security

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Hire Node.JS Developers | Skenix Infotech

We are providing robust Node.JS Development Services with expert Node.js Developers. Get affordable Node.JS Web Development services from Skenix Infotech.

How to Hire Node.js Developers And How Much Does It Cost?

A Guide to Hire Node.js Developers who can help you create fast and efficient web applications. Also, know how much does it cost to hire Node.js Developers.

Top Node.js Development Companies and Expert NodeJS Developers

A thoroughly researched list of top NodeJS development companies with ratings & reviews to help hire the best Node.JS developers who provide development services and solutions across the world. List of Leading Node.js development Service Providers...

Building and Securing a Node.js and Express App using Passport.js and Auth0

Learn how to secure a simple Node.js and Express app by adding user authentication with Passport.js and Auth0.

Hire Node JS Developer from Expert Node JS Development Company

NodeJS Development Company-Hire Node JS developer from the most prominent NodeJS development company, Mobiweb and get remarkable Node.js app development services.