Securing Gatsby with Auth0

Perfect to hear that!

@sam.julien Do you have any updates on the article to set up Gatsby with auth0-spa-js?

Also, wanted to flag comment #29 from @dmitriy.movch

Am I correct, anybody can set the flag isLoggedIn to ‘true’ in local storage in his browser and get access to the route /account and he doesn’t need to login? It is not secure.

In testing my site, I easily bypassed Auth0 by manually setting isLoggedIn to true in the browser devtools. Then I was able to continue to access ‘protected’ pages since isAuthenticated() ONLY checks if isLoggedIn is true. It was surprisingly easy to figure out how get around authentication.

Are there more checks I can run as part of isAuthenticated()? Should I be calling checkSession()? Should I be using a nonce as mentioned in the docs and in Mitigate Replay Attacks When Using the Implicit Flow? Is there a way to verify the accessToken and idToken in the following way?

export const isAuthenticated = () => {
  if (!inBrowser) {
    return;
  }
  const isLoggedIn = localStorage.getItem(IS_LOGGED_IN) === 'true';
  const hasValidAccessToken = validateToken(tokens.accessToken);
  const hasValidIdToken = validateToken(tokens.idToken);

  return isLoggedIn && hasValidAccessToken && hasValidIdToken;
};

const validateToken = (token) => {
  // validate JWT?
  // send to Auth0 for validation?
  // call checkSession and make sure the tokens and/or nonce match up?
}

It just seems like there’s a lot of room for improvement here and I’m not sure where to start :sweat_smile:

Another bug I found is when a user goes to the website and logs in. isLoggedIn is set to true. Then, let’s say the user forgets to log out and then returns a few days later. isLoggedIn is still set to true, but the session and token have all expired. The user is still able to get to ‘protected’ pages since isAuthenticated() only checks if isLoggedIn is true.

My attempt to fix this is the following:

  1. in gatsby-browser.js, componentDidMount calls silentAuth()
  2. silentAuth() calls checkSession()
  3. checkSession calls setSession() with an error since the session is expired
  4. my fix: in the if (err) block of setSession(), set isLoggedIn to false
  5. now isAuthenticated() returns false
  6. when the user tries to go to /account, it calls login()

Does this sound like the right way to fix this?

Hey there @dc.gaudium!

I’m sure @sam.julien will look at it once he’s online

Hmmm… Quickly glancing through the docs for the auth0-spa SDK, it looks like it solves a lot of the problems I mentioned. If the Gatsby-specific SPA article is still in the works, I’m looking at the following articles:

Looks like those are good places to start. @sam.julien Are there any other articles that would help or other articles that I’m missing?

Hey @dc.gaudium, thanks for following up. Yes, the SPA SDK will solve nearly everything we’ve mentioned in this thread. We’re coming out with a new article on Gatsby auth this week, so stay tuned for that. It will be used in conjunction with the new React SDK.

Another resource that may help is my talk on auth in Gatsby from Byteconf React: https://www.youtube.com/watch?v=GdsKB6_6pdk

The slides and sample code and stuff is all here: http://samj.im/byteconf-react

That talk is not specific to Auth0 but shows the same approach we use for the SPA SDK. Just know that the new React SDK will abstract away the need to create your own context and hooks.

Hello. I have done everything on tutorial. On local works perfect. But when I deploy to Netlify or Vercel. Login page only showing loading. I have done all the credentials true. And local build also not working. Can anyone know the issue?

Thanks, for the post. We took this solution and applied it to the auth0-lock. It works for gastby-develop and the lock shows up just fine on the localhost. However, on gatsby-build, the build is successful, but the lock is failing to load. We get the following error.
Uncaught (in promise) Error: page resources for /signup/ not found. Not rendering React at production-app.js:128
We have signup component which renders fine, but inside that component, it is not able to import these:

import { Auth0Lock, Auth0LockPasswordless } from "auth0-lock"
At this point we are stuck. Not sure how to proceed.

Additional information is that we had to apply resolutions as suggested from this post. Otherwise, it would break immediately. I am not sure if the resolution is causing any issues. If anyone had any luck running auth0-lock with Gatsby, please kindly chime in. Thank you!

Hello,
I am trying to get Auth0-Lock working on our Gatsby site. It works great on the local. However, after publishing the site, it is not redirecting.
Essentially, what we found was it is not firing the lock.on('authenticated', function(authResult) {....
We followed the instructions from the blog post (https://auth0.com/blog/securing-gatsby-with-auth0/) and created this repo with our modifications: https://github.com/GreenOn/auth0-lock-gatsby.

And here is the hosted site: http://gatsby-auth0-lock-test.s3-website.us-east-2.amazonaws.com/.
We tried all kinds of things, but unable to get our site redirected. Could anyone take a look and help, please?
Thanks!
Pramod

The above message was merged into this thread not to complicate communication. Thanks!

1 Like

We had to comment out the loaders.null() part out of the gatsby-node-js file to get rid of the Uncaught (in promise) Error: page resources for /signup/ not found.

// exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
  //   if (stage === "build-html") {
  //     /*
  //      * During the build step, `auth0-js` will break because it relies on
  //      * browser-specific APIs. Fortunately, we don’t need it during the build.
  //      * Using Webpack’s null loader, we’re able to effectively ignore `auth0-js`
  //      * during the build. (See `src/utils/auth.js` to see how we prevent this
  //      * from breaking the app.)
  //      */
  //     actions.setWebpackConfig({
  //       module: {
  //         rules: [
  //           {
  //             test: /auth0-lock/,
  //             use: loaders.null(),
  //           },
  //         ],
  //       },
  //     })
  //   }
  // }

Now we at least get the lock.show() getting fired but no luck in getting the lock.on working.
Again, it works on the localhost but not on the hosted site.

–> Reproducible Repo and Hosted Site.

I think we figured this out. On the localhost, it is a like a singlepage app, so after successfully logging in, it was able to find lock object on any page. However, on the production site, it is converting everything to static pages. So, lock object is only available on the signin page. When it returns to the index page, since the auth.js file out of utils is not referenced there, it doesn’t do anything. So, to solve the problem, auth.js reference was added to the index.js file and it works fine now. This was a bit tricky and glad that it is finally working.

1 Like

Perfect! Glad to hear that!