Securing Gatsby with Snapt Aria or Nova ADC

by Craig Risi on Security • July 27, 2021

One of the beauties of the software development world is that it’s never static. Tools and technologies are always evolving, so developers are always learning and advancing their knowledge and techniques. 

While this makes things incredibly exciting for developers, it also presents many risks, especially in understanding how each new tool, framework, and development language deals with security and ensuring that you as a development team are in a position to deal with this.

One of the newer frameworks to come out in the web development world is Gatsby which orchestrates things like GraphQL, CSS-in-JS, and API data (including others) into one easy-to-use and powerful framework with the intention for web developers to create websites in a shorter space of time.

I’m not going to go into detail on how it works and will assume that if you are reading this, you already have a working knowledge of Gatsby and its basic syntax and rules. In this blog, I want to talk about how to ensure your Gatsby site is built securely – and then how to connect it to a Snapt ADC for further security and load management applications.

 

Create a Protected Account Route

First, create a protected account route, which will allow you to easily route traffic through and ensure a secure flow of information. 

1. Create account.js

To start, create a new file called account.js in the src/pages/ folder and paste in the following code:

// src/pages/account.js

import React from "react"

const Account = () => (

  <div>

<p>This is going to be a protected route</p>

  </div>

)

export default Account

Doing this will allow you to protect anything related to this account route along with anything nested underneath it, like /account/settings or account/operations. Though things aren’t secure yet, this is simply the creation of a route that will make securing it far simpler.

2. Set Up a Client-Only Route

You’re also going to need to set up a client-only route. This will allow you to tap into Gatsby's server-side build pipeline and customize how it works. An example of which you can find below as part of an override of the default Gatsby createPage function:

// ./gatsby-node.js

// Implement the Gatsby API “onCreatePage”. This is

// called after every page is created.

exports.onCreatePage = async ({ page, actions }) => {

  const { createPage } = actions

  // page.matchPath is a special key that's used for matching pages

  // only on the client.

  if (page.path.match(/^\/account/)) {

page.matchPath = "/account/*"

// Update the page.

createPage(page)

  }

}

3. Set Up Client-Side Routing

Now that this is created, you can work on setting up the client-side routing, which you can use either the regular React Router, though Gatsby by default uses Reach under the hood, so I will make use if it in this example:

// src/pages/account.js

import React from "react"

import { Router } from "@react/router"

import { Link } from "gatsby"

 

const Home = () => <p>Home</p>

const Settings = () => <p>Settings</p>

const Billing = () => <p>Billing</p>

 

const Account = () => (

  <>

<nav>

   <Link to="/account">Home</Link>{" "}

   <Link to="/account/settings">Settings</Link>{" "}

   <Link to="/account/billing">Billing</Link>{" "}

</nav>

<Router>

   <Home path="/account" />

   <Settings path="/account/settings" />

   <Billing path="/account/billing" />

</Router>

  </>

)

export default Account

 

Set Up Gatsby With Snapt Aria

Now that you have set up a secure routing system for your Gatsby application, it’s time to configure it to work with a Snapt ADC – of which I will use Aria in this example. If you can get this working through Aria, then it will be straightforward to get it working through Snapt Nova.

Download your Aria trial

I am assuming at this point you have already got a node setup with the relevant account details, so again, I won’t go into details about how to do that and keep the focus squarely on the config in Gatsby.

1. Update Gatsby server-side config

To connect them, you will need to make a small change to Gatsby's server-side configuration. Add the following code to the end of gatsby-node.js:

// ./gatsby-node.js

// above code unchanged

exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

  if (stage === "build-html") {

actions.setWebpackConfig({

   module: {

     rules: [

       {

         test: /auth0-js/,

         use: loaders.null(),

       },

     ],

   },

})

  }

}

2. Create auth.js

Once that's done, create a new folder inside src called utils and a file called auth.js. Add the following code to it:

// src/utils/auth.js

import auth0 from "auth0-js"

const isBrowser = typeof window !== "undefined"

 

const auth = isBrowser

  ? new Aria.WebAuth({

   domain: process.env.AUTH0_DOMAIN,

   clientID: process.env.AUTH0_CLIENTID,

   redirectUri: process.env.AUTH0_CALLBACK,

   responseType: "token id_token",

   scope: "openid profile email",

})

: {}

3. Create environment files

You can update the Aria auth script here directly. Alternatively, you can create env. files to separate your application environment and then adjust the different .env files as follows:

# ./.env.development

# Get these values at https://manage.auth0.com

AUTH0_DOMAIN=<value>

AUTH0_CLIENTID=<value>

AUTH0_CALLBACK=http://localhost:8000/callback

4. Update Gatsby authentication files

In your Gatsby application, it's important to now update your authentication files with the appropriate code. There are multiple ways of doing this depending on your application, though I have provided a basic example below:

// src/utils/auth.js

import { navigate } from "gatsby"

// insert after auth const

const tokens = {

  accessToken: false,

  idToken: false,

  expiresAt: false,

}

let user = {}

export const isAuthenticated = () => {

  if (!isBrowser) {

return;

  }

  return localStorage.getItem("isLoggedIn") === "true"

}

export const login = () => {

  if (!isBrowser) {

return

  }

   auth.authorize()

}

const setSession = (cb = () => {}) => (err, authResult) => {

  if (err) {

navigate("/")

cb()

return

  }

  if (authResult && authResult.accessToken && authResult.idToken) {

let expiresAt = authResult.expiresIn * 1000 + new Date().getTime()

tokens.accessToken = authResult.accessToken

tokens.idToken = authResult.idToken

tokens.expiresAt = expiresAt

user = authResult.idTokenPayload

localStorage.setItem("isLoggedIn", true)

navigate("/account")

cb()

  }

}

export const handleAuthentication = () => {

  if (!isBrowser) {

return;

  }

  auth.parseHash(setSession())

}

export const getProfile = () => {

  return user

}

 

With this all done, your application will now be in a position to route traffic to your Aria ADC, with all components of your account routing flowing through Aria’s intelligent scanning and providing that additional layer of security to it.

Download Free Trial