{{announcement.body}}
{{announcement.title}}

Create a Secure Blog With Gatsby, React, and Netlify

DZone 's Guide to

Create a Secure Blog With Gatsby, React, and Netlify

Let's learn how to use Gatsby to create your own blogging application that uses the Netlify CMS, git, and Okta.

· Web Dev Zone ·
Free Resource

In this tutorial, you’ll learn how to use Gatsby to create a blog app that integrates with the Netlify content management system (CMS) for content. Your app will allow you to author posts in Markdown and add or edit posts from your browser or Git. As a last step, you’ll secure a section of your app with Okta.

First, let’s take a step back. What is Gatsby? Gatsby is a tool for creating static websites with React. With Gatsby, you can pull data from CMSs, Markdown files, APIs, databases, and more. Gatsby uses GraphQL and webpack to combine your data and React code to generate static files for your website. 

Another piece of the puzzle here is the JAMstack. You can deliver JAM—JavaScript, APIs, and Markup—apps by pre-rendering files and serving them directly from a CDN, so you don’t have to manage or run web servers.

And as one final point of explanation before we get started, Netlify, which we’ll integrate with for content, is a hosting company for static sites that offers continuous integrations, HTML forms, AWS Lambda functions, and, (most relevant for us) content management.

Before you begin, there’s a few things you’ll need:

If you’d prefer to watch a video, you can watch this tutorial as a screencast.

Install Gatsby CLI

To create a Gatsby site, you’ll need to install the Gatsby CLI. This tool gets you up and running with a Gatsby app in no time. It also runs a development server and builds your Gatsby application for production.

npm install -g gatsby-cli

Create a New Project with Gatsby

Run gatsby new to create an app using Gatsby’s Hello World starter:

gatsby new gatsby-netlify-okta gatsbyjs/gatsby-starter-hello-world

If prompted to choose between yarn and npm, choose npm. This process creates a directory layout, adds a package.json with dependencies, and prints out instructions to continue.

Your new Gatsby site has been successfully bootstrapped. Start developing it by running:

  cd gatsby-netlify-okta
  gatsby develop

NOTE: You can also use npm start as an alias for gatsby develop. I use npm start to do the default tasks on most of my Node projects. I love this attention to detail from the Gatsby developers! ❤️

You can use the tree command to view your new project’s directory structure.

$ cd gatsby-netlify-okta
$ tree -I node_modules
.
├── LICENSE
├── README.md
├── gatsby-config.js
├── package-lock.json
├── package.json
├── src
│   └── pages
│       └── index.js
└── static
    └── favicon.ico

Run npm start and check out your “Hello World” app at http://localhost:8000.

Now let’s move on to adding a neat feature, sourcing content from Netlify CMS!

Add Netlify CMS for Content Management

Netlify CMS is a single-page React app too! Its features include custom-styled previews, UI widgets, editor plugins, and backends to support different Git platform APIs.

You can install Netlify CMS and the Gatsby plugin for it using npm:

npm i netlify-cms-app@2.11.20 gatsby-plugin-netlify-cms@4.1.40

In gatsby-config.js, register the Netlify CMS plugin:

module.exports = {
  plugins: [`gatsby-plugin-netlify-cms`],
}

Then create a static/admin directory and a config.yml file in it.

.static/admin/config.yml

backend:
  name: test-repo
  
media_folder: static/assets
public_folder: assets
  
collections:
  - name: blog
    label: Blog
    folder: blog
    create: true
    fields:
      - { name: path, label: Path }
      - { name: date, label: Date, widget: datetime }
      - { name: title, label: Title }
      - { name: body, label: Body, widget: markdown }

Restart your app using Ctrl+C and npm start.

You’ll now be able to edit content at http://localhost:8000/admin/.

Click the Login button and you’ll see the screen below.

Everyone can log in and everything is in-memory at this point. You can even add a new blog post:

Click Publish and you’re in business!

Unfortunately, you’ll lose your post as soon as you restart your development server. However, you can update Netlify CMS to store files in Git instead!

Integrate Netlify CMS with GitHub for Continuous Deployment

To save to a Git repository, you can create a repo on GitHub, for example, I created one at oktadeveloper/gatsby-netlify-okta-example.

You can add Git to your Gatsby project using the following commands:

git init
git add .
git commit -m "Add project to Git"
git remote add origin git@github.com:${user}/${repo}.git
git push origin master

Now you can publish your Gatsby site straight from GitHub using Netlify’s create a new site page.

You’ll be prompted for a Git hosting provider. Click on GitHub.

Find the repository you deployed to.

Accept all the default deploy settings and click Deploy site.

You’ll return to your site’s dashboard and the build will be in progress.

In a couple of minutes, your site will be live!

If you scroll down to the Production deploys section, you can click on the build and see what happened.

You’ve built a React app, checked it into source control, and published it to production - that’s pretty cool!

Not only that, but you automated the deployment process. Any changes you push to your GitHub repo will be automatically deployed by Netlify. ��

Add Your GitHub Repo as a Netlify CMS Backend

Netlify CMS will need to authenticate with GitHub to save your content changes to your repo.

Modify static/admin/config.yml to use your GitHub repo:

backend:
  name: github
  repo: your-username/your-repo-name

In my case, I used:

backend:
  name: github
  repo: oktadeveloper/gatsby-netlify-okta-example

Save config.yml, commit the change, and push it to your GitHub repo.

git add .
git commit -m "Add GitHub Backend"
git push origin master

When your changes finish deploying on Netlify (it should take around 30 seconds), navigate to your site’s /admin/ endpoint. You’ll be prompted to log in with GitHub.

Click Login with GitHub and you’ll see a page that says “No Auth Provider Found”.

On Netlify, go to Site settings and navigate to Access control > (scroll down) OAuth.

Click Install provider. It will prompt you for a client ID and secret. To get this, navigate to GitHub Developer settings > OAuth Apps > New OAuth App.

Register a new application with the following settings:

  • Application name: My Gatsby Blog
  • Homepage URL: <copy URL from Netlify>
  • Authorization callback URL: https://api.netlify.com/auth/done

Click Register application and you’ll be provided with the client ID and secret you were looking for.

Copy and paste these values into your Netlify OAuth provider dialog and click Install.

Now if you go to your site’s /admin/ endpoint and log in with GitHub, you’ll be prompted for authorization. Click the green Authorize button at the bottom to continue.

If you see an error the first time it loads, you can ignore it. It happens because no blogs exist. Add a new one and it’ll go away. For the path, use something like /blog/first-post.

In a terminal window, run git pull origin master and you’ll see your project is updated with the post you created.

git pull origin master
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
From github.com:oktadeveloper/gatsby-netlify-okta-example
 * branch            master     -> FETCH_HEAD
   c1b8722..421a113  master     -> origin/master
Updating c1b8722..421a113
Fast-forward
 blog/1st-post.md | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 blog/1st-post.md

Run npm start locally to see the blog at http://localhost/admin/. But how can others (without admin access) read it?

Render Blogs with a New BlogRoll React Component

Create a src/components/BlogRoll.js file. This file will contain a React component that queries for blog posts using GraphQL.

JavaScript
 




xxxxxxxxxx
1
81


1
import React from 'react'
2
import PropTypes from 'prop-types'
3
import { Link, graphql, StaticQuery } from 'gatsby'
4
 
          
5
class BlogRoll extends React.Component {
6
  render() {
7
    const { data } = this.props;
8
    const { edges: posts } = data.allMarkdownRemark;
9
 
          
10
    return (
11
      <div className="columns is-multiline">
12
        {posts &&
13
          posts.map(({ node: post }) => (
14
            <div className="is-parent column is-6" key={post.id}>
15
              <article
16
                className={`blog-list-item tile is-child box notification ${
17
                  post.frontmatter.featuredpost ? 'is-featured' : ''
18
                }`}
19
              >
20
                <header>
21
                  <p className="post-meta">
22
                    <Link
23
                      className="title has-text-primary is-size-4"
24
                      to={post.frontmatter.path}
25
                    >
26
                      {post.frontmatter.title}
27
                    </Link>
28
                    <span> &bull; </span>
29
                    <span className="subtitle is-size-5 is-block">
30
                      {post.frontmatter.date}
31
                    </span>
32
                  </p>
33
                </header>
34
                <p>
35
                  {post.excerpt}
36
                  <br />
37
                  <br />
38
                  <Link className="button" to={post.frontmatter.path}>
39
                    Keep Reading →
40
                  </Link>
41
                </p>
42
              </article>
43
            </div>
44
          ))}
45
      </div>
46
    )
47
  }
48
}
49
 
          
50
BlogRoll.propTypes = {
51
  data: PropTypes.shape({
52
    allMarkdownRemark: PropTypes.shape({
53
      edges: PropTypes.array,
54
    }),
55
  }),
56
};
57
 
          
58
export default () => (
59
  <StaticQuery
60
    query={graphql`
61
      query BlogRollQuery {
62
        allMarkdownRemark(
63
          sort: { order: DESC, fields: [frontmatter___date] }
64
        ) {
65
          edges {
66
            node {
67
              excerpt(pruneLength: 400)
68
              id
69
              frontmatter {
70
                path
71
                title
72
                date(formatString: "MMMM DD, YYYY")
73
              }
74
            }
75
          }
76
        }
77
      }
78
    `}
79
    render={(data, count) => <BlogRoll data={data} count={count} />}
80
  />
81
)



Then add a link to it in src/pages/index.js:

JavaScript
 




xxxxxxxxxx
1
10


1
import React from 'react'
2
import { Link } from 'gatsby'
3
 
          
4
export default () => {
5
  return (
6
    <>
7
      Hello world!
8
      <p><Link to="/blog">View Blog</Link></p>
9
    </>)
10
}


Restart your Gatsby app using npm start and navigate to http://localhost:8000.

You’ll receive an error because your project doesn’t have Markdown support.

JavaScript
 




xxxxxxxxxx
1


1
Generating development JavaScript bundle failed
2
 
          
3
/Users/mraible/blog/gatsby-netlify-okta/src/components/BlogRoll.js
4
  62:9  error  Cannot query field "allMarkdownRemark" on type "Query"  graphql/template-strings
5
 
          
6
 1 problem (1 error, 0 warnings)
7
 
          
8
File: src/components/BlogRoll.js


Add Markdown Support to Gatsby

Gatsby’s Add Markdown Pages docs show the process that it uses to create pages from Markdown files:

  1. Read files into Gatsby from the filesystem
  2. Transform Markdown to HTML and frontmatter to data
  3. Add a Markdown file
  4. Create a page component for the Markdown files
  5. Create static pages using Gatsby’s Node.js createPage() API

Install a couple of Gatsby plugins to make this happen.

npm i gatsby-source-filesystem gatsby-transformer-remark

Then configure them in gatsby-config.js:

JavaScript
 




xxxxxxxxxx
1
13


 
1
module.exports = {
2
  plugins: [
3
    `gatsby-plugin-netlify-cms`,
4
    {
5
      resolve: `gatsby-source-filesystem`,
6
      options: {
7
        path: `${__dirname}/blog`,
8
        name: `markdown-pages`,
9
      },
10
    },
11
    `gatsby-transformer-remark`
12
  ]
13
}


Restart everything and you’ll be able to see your blog posts at /blog.

However, if you try to navigate into a blog, it doesn’t work because you didn’t tell Gatsby to generate pages for each one.

Use Gatsby’s Node API to Generate Static Blog Pages

Create a gatsby-node.js in the root directory of your project and add code to create a static page for each blog.

JavaScript
 




xxxxxxxxxx
1
38


 
1
onst path = require(`path`);
2
 
          
3
exports.createPages = async ({actions, graphql, reporter}) => {
4
  const {createPage} = actions;
5
 
          
6
  const blogPostTemplate = path.resolve(`src/templates/blog.js`);
7
 
          
8
  const result = await graphql(`
9
    {
10
      allMarkdownRemark(
11
        sort: { order: DESC, fields: [frontmatter___date] }
12
        limit: 1000
13
      ) {
14
        edges {
15
          node {
16
            frontmatter {
17
              path
18
            }
19
          }
20
        }
21
      }
22
    }
23
  `);
24
 
          
25
  // Handle errors
26
  if (result.errors) {
27
    reporter.panicOnBuild(`Error while running GraphQL query.`);
28
    return
29
  }
30
 
          
31
  result.data.allMarkdownRemark.edges.forEach(({node}) => {
32
    createPage({
33
      path: node.frontmatter.path,
34
      component: blogPostTemplate,
35
      context: {}, // additional data can be passed via context
36
    })
37
  })
38
};


You might notice this JavaScript code uses a template at src/templates/blog.js. Create this file with the following code in it.

JavaScript
 




xxxxxxxxxx
1
32


 
1
import React from "react"
2
import { graphql } from "gatsby"
3
export default function Template({
4
  data, // this prop will be injected by the GraphQL query below.
5
}) {
6
  const { markdownRemark } = data // data.markdownRemark holds your post data
7
  const { frontmatter, html } = markdownRemark
8
  return (
9
    <div className="blog-post-container">
10
      <div className="blog-post">
11
        <h1>{frontmatter.title}</h1>
12
        <h2>{frontmatter.date}</h2>
13
        <div
14
          className="blog-post-content"
15
          dangerouslySetInnerHTML={{ __html: html }}
16
        />
17
      </div>
18
    </div>
19
  )
20
}
21
export const pageQuery = graphql`
22
  query($path: String!) {
23
    markdownRemark(frontmatter: { path: { eq: $path } }) {
24
      html
25
      frontmatter {
26
        date(formatString: "MMMM DD, YYYY")
27
        path
28
        title
29
      }
30
    }
31
  }
32
`


Restart your app to see Markdown rendering properly!

Commit your changes and verify everything works in production.

git add .
git commit -m "Add /blog and Markdown support"
git push origin master

Add an Account Section

Add an Account section for your site by creating a file at src/pages/account.js.

JavaScript
 




xxxxxxxxxx
1
24


1
import React from 'react'
2
import { Router } from '@reach/router'
3
import { Link } from 'gatsby'
4
 
          
5
const Home = () => <p>Home</p>;
6
const Settings = () => <p>Settings</p>;
7
const Account = () => {
8
  return (
9
    <>
10
      <nav>
11
        <Link to="/">Home</Link>{' '}
12
        <Link to="/account">My Account</Link>{' '}
13
        <Link to="/account/settings">Settings</Link>{' '}
14
      </nav>
15
      <h1>My Account</h1>
16
      <Router>
17
        <Home path="/account"/>
18
        <Settings path="/account/settings"/>
19
      </Router>
20
    </>
21
  )
22
};
23
 
          
24
export default Account


Add a link to the account page in src/pages/index.js:

JavaScript
 




xxxxxxxxxx
1
11


 
1
import React from 'react'
2
import { Link } from 'gatsby'
3
 
          
4
export default () => {
5
  return (
6
    <>
7
      Hello world!
8
      <p><Link to="/blog">View Blog</Link></p>
9
      <p><Link to="/account">My Account</Link></p>
10
    </>)
11
}


Since this section will have dynamic content that shouldn’t be rendered statically, you need to exclude it from the build. Add the following JavaScript to the bottom of gatsby-node.js to indicate that /account is a client-only route.

JavaScript
 




xxxxxxxxxx
1


1
exports.onCreatePage = async ({ page, actions }) => {
2
  const { createPage } = actions;
3
  
4
  if (page.path.match(/^\/account/)) {
5
    page.matchPath = "/account/*";
6
    createPage(page)
7
  }
8
};


Restart with npm start and you should be able to navigate to this new section.

Register Your App with Okta

To begin with Okta, you’ll need to register your app, just like you did with GitHub. Log in to your Okta developer account and navigate to Applications > Add Application.

  • Choose Single-Page App and Next
  • Enter a name like Gatsby Account
  • Specify the following Login redirect URIs:
    • http://localhost:8000/account
    • http://localhost:9000/account
    • https://<your-site>.netlify.com/account
  • Specify the following Logout redirect URIs:
    • http://localhost:8000
    • http://localhost:9000
    • https://<your-site>.netlify.com
  • Click Done

Your Okta application settings should resemble the screenshot below.

Add Trusted Origins for Your Gatsby Sites

Gatsby can run on two different ports (8000 and 9000) locally. One is for development and one is for production (invoked with gatsby build and gatsby serve). You also have your production Netlify site. Add all of these as Trusted Origins in API > Trusted Origins.

Click Add Origin, select CORS and Redirect for Type, and add each of the following:

  • http://localhost:8000
  • http://localhost:9000
  • https://<your-site>.netlify.com

When you’re finished, your screen should resemble the following.

Protect Your Gatsby Account Section with Okta

Install Okta’s Sign-In Widget:

npm i @okta/okta-signin-widget@3.7.2

Create a Login component in src/components/Login.js:

JavaScript
 




xxxxxxxxxx
1
72


 
1
import OktaSignIn from '@okta/okta-signin-widget';
2
import '@okta/okta-signin-widget/dist/css/okta-sign-in.min.css';
3
import React from 'react';
4
 
          
5
const config = {
6
  baseUrl: '<okta-org-url>',
7
  clientId: '<okta-client-id>',
8
  logo: '//logo.clearbit.com/gatsbyjs.org',
9
  redirectUri: typeof window !== 'undefined' && window.location.origin + '/account',
10
  el: '#signIn',
11
  authParams: {
12
    pkce: true,
13
    responseType: ['token', 'id_token']
14
  }
15
};
16
 
          
17
export const signIn = typeof window !== 'undefined' && new OktaSignIn(config);
18
 
          
19
export default class Login extends React.Component {
20
  constructor(props) {
21
    super(props);
22
 
          
23
    this.state = {
24
      user: false
25
    };
26
 
          
27
    this.signIn = signIn;
28
  }
29
 
          
30
  async componentDidMount() {
31
    const authClient = this.signIn.authClient;
32
    const session = await authClient.session.get();
33
    console.log('session.status', session.status);
34
    // Session exists, show logged in state.
35
    if (session.status === 'ACTIVE') {
36
      // clear parameters from browser window
37
      window.location.hash = '';
38
      // set username in state
39
      this.setState({user: session.login});
40
      localStorage.setItem('isAuthenticated', 'true');
41
      // get access and ID tokens
42
      authClient.token.getWithoutPrompt({
43
        scopes: ['openid', 'email', 'profile'],
44
      }).then((tokens) => {
45
        tokens.forEach(token => {
46
          if (token.idToken) {
47
            authClient.tokenManager.add('idToken', token);
48
          }
49
          if (token.accessToken) {
50
            authClient.tokenManager.add('accessToken', token);
51
          }
52
        });
53
 
          
54
        // Say hello to the person who just signed in
55
        authClient.tokenManager.get('idToken').then(idToken => {
56
          console.log(`Hello, ${idToken.claims.name} (${idToken.claims.email})`);
57
          window.location.reload();
58
        });
59
      }).catch(error => console.error(error));
60
      return;
61
    } else {
62
      this.signIn.remove();
63
    }
64
    this.signIn.renderEl({el: '#signIn'})
65
  }
66
 
          
67
  render() {
68
    return (
69
      <div id="signIn"/>
70
    )
71
  }
72
}


Replace the placeholders near the top of this file with your Okta app settings.

JavaScript
 




xxxxxxxxxx
1


 
1
const config = {
2
  baseUrl: '<okta-org-url>',
3
  clientId: '<okta-client-id>',
4
  ...
5
};


For example:

JavaScript
 




xxxxxxxxxx
1


 
1
const config = {
2
  baseUrl: 'https://dev-133320.okta.com',
3
  clientId: '0oa2ee3nvkHIe8vzX357',
4
  ...
5
};


Modify src/pages/account.js to include an Account component that uses Login to get ID tokens and logout.

JavaScript
 




xxxxxxxxxx
1
73


 
1
import React from 'react'
2
import { navigate, Router } from '@reach/router'
3
import { Link } from 'gatsby'
4
import Login, { signIn } from '../components/Login'
5
 
          
6
const Home = () => <p>Account Information</p>;
7
const Settings = () => <p>Settings</p>;
8
 
          
9
const isAuthenticated = () => {
10
  if (typeof window !== 'undefined') {
11
    return localStorage.getItem('isAuthenticated') === 'true';
12
  } else {
13
    return false;
14
  }
15
};
16
 
          
17
class Account extends React.Component {
18
  constructor(props) {
19
    super(props);
20
 
          
21
    this.state = {user: false};
22
    this.logout = this.logout.bind(this);
23
  }
24
 
          
25
  async componentDidMount() {
26
    const token = await signIn.authClient.tokenManager.get('idToken');
27
    if (token) {
28
      this.setState({user: token.claims.name});
29
    } else {
30
      // Token has expired
31
      this.setState({user: false});
32
      localStorage.setItem('isAuthenticated', 'false');
33
    }
34
  }
35
 
          
36
  logout() {
37
    signIn.authClient.signOut().catch((error) => {
38
      console.error('Sign out error: ' + error)
39
    }).then(() => {
40
      localStorage.setItem('isAuthenticated', 'false');
41
      this.setState({user: false});
42
      navigate('/');
43
    });
44
  }
45
 
          
46
  render() {
47
    if (!isAuthenticated()) {
48
      return (
49
        <Login/>
50
      );
51
    }
52
 
          
53
    return (
54
      <>
55
        <nav>
56
          <Link to="/">Home</Link>{' '}
57
          <Link to="/account">My Account</Link>{' '}
58
          <Link to="/account/settings">Settings</Link>{' '}
59
        </nav>
60
        <h1>My Account</h1>
61
        <React.Fragment>
62
          <p>Welcome, {this.state.user}. <button onClick={this.logout}>Logout</button></p>
63
        </React.Fragment>
64
        <Router>
65
          <Home path="/account"/>
66
          <Settings path="/account/settings"/>
67
        </Router>
68
      </>
69
    )
70
  }
71
}
72
 
          
73
export default Account


Restart your app with npm start, open http://localhost:8000 in a private window, and click on My Account. You’ll be prompted to log in.

Enter your credentials and click Sign In to browse the account section. You should also see your name and be able to logout.

Fix Gatsby Production Build

To test building your app for production, run gatsby build. You’ll get an error because Okta’s Sign-In Widget doesn’t expect to be compiled for server-side rendering.

JavaScript
 




xxxxxxxxxx
1
36


 
1
failed Building static HTML for pages - 1.730s
2
 
          
3
 ERROR #95312 
4
 
          
5
"window" is not available during server side rendering.
6
 
          
7
See our docs page for more info on this error: https://gatsby.dev/debug-html
8
 
          
9
  12 | 
10
  13 | (function (){
11
> 14 |   var isChrome = 'chrome' in window && window.navigator.userAgent.indexOf('Edge') < 0;
12
     | ^
13
  15 |   if ('u2f' in window || !isChrome) {
14
  16 |     return;
15
  17 |   }
16
 
          
17
 
          
18
  WebpackError: ReferenceError: window is not defined
19
  
20
  - u2f-api-polyfill.js:14 
21
    node_modules/u2f-api-polyfill/u2f-api-polyfill.js:14:1
22
  
23
  - u2f-api-polyfill.js:754 Object../node_modules/u2f-api-polyfill/u2f-api-polyfill.js
24
    node_modules/u2f-api-polyfill/u2f-api-polyfill.js:754:2
25
  
26
  - okta-sign-in.entry.js:3 webpackUniversalModuleDefinition
27
    node_modules/@okta/okta-signin-widget/dist/js/okta-sign-in.entry.js:3:104
28
  
29
  - okta-sign-in.entry.js:10 Object../node_modules/@okta/okta-signin-widget/dist/js/okta-sign-in.entry.js
30
    node_modules/@okta/okta-signin-widget/dist/js/okta-sign-in.entry.js:10:2
31
  
32
  - Login.js:1 Module../src/components/Login.js
33
    src/components/Login.js:1:1
34
  
35
  - account.js:1 Module../src/pages/account.js
36
    src/pages/account.js:1:1


To fix this, you can exclude it from the compilation process. Modify the webpack build to exclude it from compilation by configuring webpack. Add the JavaScript below to the bottom of gatsby-node.js.

JavaScript
 




xxxxxxxxxx
1
15


1
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
2
  if (stage === 'build-html') {
3
    // Exclude Sign-In Widget from compilation path
4
    actions.setWebpackConfig({
5
      module: {
6
        rules: [
7
          {
8
            test: /okta-sign-in/,
9
            use: loaders.null(),
10
          }
11
        ],
12
      },
13
    })
14
  }
15
};


Try gatsby build again and it should work this time. Run gatsby serve to see if the production build works on http://localhost:9000. Rejoice when it does!

Add User Registration

To give people the ability to sign-up for accounts, go to your Okta dashboard > Users > Registration, and enable it.

Modify src/components/Login.js to add Okta’s user registration feature.

JavaScript
 




x
10


 
1
const config = {
2
  ...
3
  authParams: {
4
    pkce: true,
5
    responseType: ['token', 'id_token']
6
  },
7
  features: {
8
    registration: true
9
  }
10
};


Then build for production and serve it up again.

gatsby build
gatsby serve

You will now see a Sign Up link at the bottom of the login form.

Click the link to see the user registration form.

Hooray - you did it! Check-in your code and rejoice in your new-found knowledge. ��

Extend Your Gatsby Account Functionality

Armed with Okta for authentication, you could develop features in the account settings of your application. For example, a setting where people can sign up for a newsletter (e.g., with TinyLetter). You could store this setting in Okta by creating a Node app that uses the Okta Node SDK to update user attributes.

In fact, you might even develop a Java or .NET backend to handle this and communicate to it from your Gatsby application using fetch() and an OAuth 2.0 access token retrieved from the Sign-In Widget.

async componentDidMount() {
  try {
    const response = await fetch('http://<node-server-url>/user/settings', {
      headers: {
        Authorization: 'Bearer ' + await signIn.authClient.tokenManager.get('accessToken')
      }
    });
    const data = await response.json();
    this.setState({ settings: data.settings });
  } catch (err) {
    // handle error as needed
    console.error(err);
  }
}

Learn More about Netlify, Gatsby, React, and Authentication

Phew! This tutorial packed a punch! ����

You learned how to build a new site with Gatsby, automate its deployment with Netlify, integrate Gatsby with Netlify CMS, process Markdown files, store your files in Git, and use Okta for authentication. Okta leverages OAuth 2.0 and OpenID Connect for its developer APIs. They’re awesome!

You can find the source code for this example on GitHub in the oktadeveloper/gatsby-netlify-okta-example repository.

If you want to make your Gatsby site even more secure, you can use the Gatsby Netlify plugin as it adds a bunch of basic security headers. After installing, configuring, and deploying, you can test your site’s security with securityheaders.com.

I learned a bunch about Gatsby and authentication from Jason Lengstorf and Aaron Parecki in their Add authentication to your apps with Okta video.

Gatsby’s documentation was extremely helpful in writing this post, as was the Gatsby + Netlify CMS Starter.

To see how the Okta Sign-In Widget can be customized, check out developer.okta.com/live-widget.

To learn more about Netlify, React, OAuth 2.0, and OIDC, I recommend some of our other blog posts:

If you liked this tutorial, please follow @oktadev on Twitter. We also like to do screencasts and post them to our YouTube channel. If you have any questions, I’d be happy to answer them in the comments below. 

Topics:
gatsbyjs, git, javascript, javascript api, markdown, netlify, okta, tutorial, web dev

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}