Just-add-water Auth0 authorization in your GatsbyJS app
This is Auth0 authorization plugin built upon such concept as Gatsby Themes. It will allow you to set up a full-fledged user authorization flow in your Gatsby app in a matter of minutes.
- 🔲 Minimal setup without dependencies overhead
- 🚝 Uses modern approach with functional components and hooks
- 💎 No crutches and cumbersome custom functionality, every line of code is easily explainable and written with Gatsby/Auth0 recommendations and best practices in mind
- 👌
/auth/callback
page comes out of the box. Easily tweakable viacallbackPath
- ⚙️ Fully customisable thanks to Shadowing
$ npm install --save gatsby-theme-auth0-minimal
Before we begin you have to create .env
file at the root of your project. There are actually a few other approaches to provide variables into your app, but we will stick with simplest possible.
Here is example of how .env
should look:
# required
GATSBY_AUTH0_DOMAIN=your-auth-app.auth0.com
GATSBY_AUTH0_CLIENTID=ADG34DG236YQ2DGQXB345
GATSBY_AUTH0_CALLBACK=https://localhost:9000/auth/callback
# optional
GATSBY_AUTH0_AUDIENCE=https://your-auth-app.auth0.com/api/v2/
GATSBY_AUTH0_SCOPE='profile email'
GATSBY_AUTH0_CALLBACK_PATH=/callback
The same structure you can spot in our example. Feel free to copy that and use in your project.
Here is detailed explanation:
Key | Default | Required | Description |
---|---|---|---|
GATSBY_AUTH0_DOMAIN |
true |
Configure Auth0 Domain . |
|
GATSBY_AUTH0_CLIENTID |
true |
Configure Auth0 Client ID |
|
GATSBY_AUTH0_CALLBACK |
true |
Configure Auth0 Callback URL |
|
GATSBY_AUTH0_AUDIENCE |
false | false |
Configure Auth0 Audience |
GATSBY_AUTH0_SCOPE |
"openid email profile" |
false |
Configure Auth0 Scope |
GATSBY_AUTH0_CALLBACK_PATH |
"/auth/callback" |
false |
Change callback URL path |
Note
⚠️ Originally Auth0 also allows to set up theresponseType
field with exact three options in our case of Implicit Flow , those aretoken
,id_token
andtoken id_token
. To offer you maximum flexibility and prevent potential bugs we removed ability to tweak this parameter and set it totoken id_token
by default.
This theme uses React Context mechanism as the single source of truth in terms of auth state for the whole app, so the first step would be wrapping our root component with our AuthProvider
.
This is our custom wrapper:
// with-auth-provider.js
import React from 'react';
import { AuthProvider } from 'gatsby-theme-auth0-minimal';
export default ({ element }) => {
return <AuthProvider>{element}</AuthProvider>;
};
Here is it's example source code
Next step we are filling our gatsby-browser.js
and gatsby-ssr.js
as described in Gatsby's doc:
// gatsby-ssr.js
import withAuthProvider from './path/to/with-auth-provider';
export const wrapRootElement = withAuthProvider;
gatsby-ssr.js example source code
// gatsby-browser.js
import withAuthProvider from './path/to/with-auth-provider';
export const wrapRootElement = withAuthProvider;
gatsby-browser.js example source code
And yes, this duplication is intentional.
The last part, we are getting access to authState
via exposed useAuth
hook:
import React from 'react';
import { useAuth } from 'gatsby-theme-auth0-minimal';
export default () => {
const {
isAuthenticated,
login,
logout,
checkSession,
authState: {
// handful
token, // access token for API requests
user, // auth0 user data
// just in case
idToken, // contains user payload
expiresAt, // how long token are going to live
unschedule, // auxillary field to manually unschedule token renewing
isLoading, // flag that reflects auth request state, helpes handle the UI
},
handleAuthentication, // would be useful implementing you own callback component
} = useAuth();
// set this up at highest level of your protected client routes
// to automatically handle the authentication (this is called silent auth)
useEffect(() => {
if (localStorage.getItem('isLoggedIn') === 'true') {
checkSession();
}
}, []);
if (isLoading) {
return <p>Loading...</p>;
}
return (
<div>
{user && <p>Hello {user.name}</p>}
{isAuthenticated ? (
<button onClick={logout}>Logout</button>
) : (
<button onClick={login}>Login</button>
)}
</div>
);
};
useAuth()
return value under the microscope:
name | args | description |
---|---|---|
login | - | Wrapper for auth0 native login function. Logs the user in with username and password using the implicit flow. Sets postLoginUrl value into localStorage where user is being redirected after he successful logs in. |
logout | - | Wrapper for auth0 native logout function. Redirects to the auth0 logout endpoint. Refreshes authState with default values. Removes any isLoggedIn flag from localStorage . |
checkSession | - | Wrapper for auth0 native checkSession function. Renews an existing session on Auth0's servers using response_mode=web_message . Changes isLoading during execution (true -> false ). Exploits postLoginUrl value. |
handleAuthentication | - | Wrapper for auth0 native parseHash function. Parse the url hash and extract the Auth response from a Auth flow. Changes isLoading during execution (true -> false ). Exploits postLoginUrl value. |
name | type | description |
---|---|---|
isLoading | Boolean | Flag that reflects current state of possible auth0 requests |
isAuthenticated | Boolean | Flag that reflects current authentication state, binded to authState.expiresAt property. |
authState | Object | Object representing auth data. Contains: |
- accessToken | String | null | String with auth0 access token |
- idToken | String | null | String with auth0 id token |
- userProfile | Object | null | Object with user data |
- expiresAt | Date | 0 | Lifespan amount of a token |
- unschedule | Function | null | Function that serves as a flag that reflects state of token auto renewal. Clears schedule on execution. |
- Live at gatsby-theme-auth0-minimal.netlify.com
- Code at this repo
Gatsby Themes has a concept called Shadowing, which allows users to override a file in a gatsby theme. This allows the theme to be fully customizable.
To start shadowing, create a folder with the theme name gatsby-theme-auth0
in your project's src
directory.
Now you're able to override any file in the theme. For example, if you want to override the callback
component, create a file:
src/gatsby-theme-auth0-minimal/components/common/callback.js
There is a number of authentication flow exist, but for Gatsby its the Implicit Flow since its basically SPA when it comes to authorization business. Keep in mind that tokens are short-lived and refresh tokens are not available in this flow.
- The user clicks Login within the SPA.
- Auth0's SDK redirects the user to the Auth0 Authorization Server (/authorize endpoint) passing along a
response_type
parameter that indicates the type of requested credential. - Your Auth0 Authorization Server redirects the user to the login and authorization prompt.
- The user authenticates using one of the configured login options and may see a consent page listing the permissions Auth0 will give to the SPA.
- Your Auth0 Authorization Server redirects the user back to the SPA with an ID token and an Access Token.
- Your SPA can use the Access Token to call an API.
- The API responds with requested data.
By default, an Access Token for a custom API is valid for 86400 seconds (24 hours) .
To learn how to change the Access Token expiration time, see Update Access Token Lifetime.
Access Tokens issued strictly for the purpose of accessing the OpenID Connect (OIDC) /userinfo
endpoint have a default lifetime and can't be changed. The length of lifetime in implicit flow is equal to 7200 seconds (2 hours).
To leave an active user out of pointless interaction when his token is expired but he IS actually authorized, silent authentication concept is being used here. Here is how it works:
-
Schedule renewal initiation is happening during
setSession
method by callingscheduleRenewal
function. This will occur after every authentication flow, either when the user explicitly logs in, or when the silent authentication happens. -
scheduleRenewal
sets up a time at which authentication should be silently renewed, which is equal to 30 seconds before the actual token expires. Also updatesAuthProvider
state with a reference tounschedule
function which allows to remove last scheduled renewal on call. -
If the renewal is successful, use the existing
setSession
method to set the new tokens in local storage AND schedule a new token renewal.
Contributions of any kind are welcome! If you know, how to make it better, add a new exciting functionality or simply fix a typ0 in this README file - go for it! Your previous coding experience doesn't matter as long as you understand what are you trying to do 😄
In order to start contributing, run
git clone git@github.com:pixel-point/gatsby-theme-auth0-minimal.git && yarn install
that will get you a local copy of the project with all deps installed, but make sure you read next chapters before you put your hands on the code.
This project is using Yarn's workspaces concept, which allows to skip the mess with npm link
, mantain both example and actual theme's code in the same repo and painless development. More info on that you can find in this awesome post by Brent Jackson.
To use this example, certain application settings must be set correctly, otherwise unexpected behavior will occur.
Set the following fields to the values shown below, where {portNumber} is whatever port number you are using (e.g., port 8000 in development mode):
-
Allowed Callback URLs
http://localhost:{portNumber}/auth/callback
-
Allowed Web Origins
http://localhost:{portNumber}
-
Allowed Logout URLs
http://localhost:{portNumber}
Make sure that there is no trailing '/' after the port number in the Allowed Web Origins and Allowed Logout URLs fields.
To be able to work on that locally you should get an acc on Auth0 (its' free), follow their initiation procedure and grab values from your dashboard.
Go to example directory, copy the env.example
-> .env.development
. Fill in the required environment variables before starting up the client dev server.
This will run the demo app in development mode using .env.development
.
Navigate to http://localhost:8000 to view it in the browser.
This will build the demo app for production using .env.production
.
Outputs to the example/public
folder.
This will serve previously built demo app for production using .env.production
.
Outputs to the example/public
folder.
This will remove contents of example/public
and its cache by running gatsby clean
in example
dir
This will format all files with js
, js
, json
or md
extensions in the repo, excluding those in .prettierignore
Same as above, but with linting.
If you experiencing any issue or believe there is a bug, feel free leave an issue with thorough description and how to reproduce step-by-step instruction. However, don't hesitate to make a PR, as was previously mentioned, contributions of any kind are welcome.
- gatsby-theme-auth0
- gatsby-auth0
- gatsby-auth0-app
- Heavily undervalued Rewrite Auth0 Example with React Hooks by terrierscript
- Gatsby docs
- Auth0 docs
MIT (C) 2020