Using Auth0 as your Identity Provider with Grafbase

Using Auth0 as your Identity Provider with Grafbase

Auth0 prides itself on easy setup, adaptable authentication and authorization patterns. It ships with a hosted auth page, and plugins for your frontend application for managing user sessions.

Grafbase provides the ability to configure rules to allow accessing data stored in your Grafbase Database for signed-in users, specific groups of users, and rules for only reading, creating, updating, or deleting data.

In this guide we'll show you how to configure Auth0 as your Grafbase Identity Provider for authenticating, and authorizing requests.

We'll be using Next.js but if you're something else on the frontend, Auth0 has lots of plugins that are easy to get started with.

Start by creating a new application, or locating an existing application you want to use with Grafbase from your Auth0 Dashboard.

Create new Auth0 application

Once you've created the application, go to the Settings > Basic Information panel and copy the following values for use later:

  • Domain
  • Client ID
  • Client Secret

Auth0 Basic Information

Now inside the panel for Application URIs add these settings:

  • Allowed Callback URLs: http://localhost:3000/api/auth/callback
  • Allowed Logout URLs: http://localhost:3000/

Let's begin by creating the frontend for our Auth0 app.

npx create-next-app nextjs-auth0

You'll then be asked some questions on how the CLI should initialize your new Next.js app. Pick your own preferences here but if here's the configuration we'll use for the rest of the guide:

✔ Would you like to use TypeScript with this project? … Yes ✔ Would you like to use ESLint with this project? … Yes ✔ Would you like to use `src/` directory with this project? … No ✔ Would you like to use experimental `app/` directory with this project? … No ✔ What import alias would you like configured? … @/*

We'll be using the nextjs-auth0 library to reduce the boilerplate needed when working with Next.js and Auth0.

Run the following NPM command inside the root of your new nextjs-auth0 application:

npm install @auth0/nextjs-auth0

Now create the file pages/api/auth/[...auth0].ts and add the following:

import { handleAuth } from '@auth0/nextjs-auth0' export default handleAuth()

Now update pages/_app.tsx to import UserProvider and wrap your Component with it:

import { UserProvider } from '@auth0/nextjs-auth0/client' import type { AppProps } from 'next/app' export default function App({ Component, pageProps }: AppProps) { return ( <UserProvider> <Component {...pageProps} /> </UserProvider> ) }

Finally finish by updating pages/index.tsx to contain some basic code to allow users to login and logout:

import { useUser } from '@auth0/nextjs-auth0/client' export default function Index() { const { user, error, isLoading } = useUser() if (isLoading) return <div>Loading...</div> if (error) return <div>{error.message}</div> if (user) { return ( <> Signed in <br /> <a href="/api/auth/logout">Logout</a> </> ) } return <a href="/api/auth/login">Login</a> }

We're almost there but before we can test everything works, we must first add the environment variables.

We need to generate a secret value for AUTH0_SECRET that is used to encrypt the session cookie:

node -e "console.log(crypto.randomBytes(32).toString('hex'))"

Then create the file .env in the root of your project and add the values obtained in step 1:

AUTH0_SECRET= AUTH0_BASE_URL=http://localhost:3000 AUTH0_ISSUER_BASE_URL= AUTH0_CLIENT_ID= AUTH0_CLIENT_SECRET= AUTH0_AUDIENCE=https://grafbase.com NEXT_PUBLIC_GRAFBASE_API_URL=http://localhost:4000/graphql

We'll be using the Grafbase CLI locally which we'll setup later. Make sure to set NEXT_PUBLIC_GRAFBASE_API_URL to http://localhost:4000/graphql.

If you now start the Next.js development sever and go to http://localhost:3000 you should be redirected to the Auth0 page to login or create an account.

npm run dev

Create new Auth0 application

Once you've signed in you should now see the see the text Signed in:

Auth0 Signed in

In the root of your nextjs-auth0 project directory run the following command:

npx grafbase init

You should now see that the file grafbase.config.ts was automatically generated.

Open the configuration file and replace the contents with the below:

import { auth, config, graph } from '@grafbase/sdk' const g = graph.Standalone() const provider = auth.OpenIDConnect({ issuer: g.env('AUTH0_ISSUER_BASE_URL'), }) const message = g.type('Message', { id: g.id(), content: g.string(), }) g.query('messages', { returns: g.ref(message).list(), resolver: 'messages', }) export default config({ graph: g, auth: { providers: [provider], rules: rules => { rules.private() }, }, })

Here we configure the OpenID Connect (oidc) provider and a messages field resolver we can use to test authenticated requests.

Next add the AUTH0_ISSUER_BASE_URL to the file .env:

AUTH0_ISSUER_BASE_URL

The AUTH0_ISSUER_BASE_URL value must match the value set in the root .env (provided by Auth0).

Now start the Grafbase development server:

npx grafbase dev

Make sure to add AUTH0_ISSUER_BASE_URL as an Environment Variable inside your Grafbase graph settings when deploying your API.

So that we can successfully send a request to Auth0 we must first generate an access token.

We can do this using the method getAccessToken from @auth0/nextjs-auth0.

Create the file pages/api/auth/token.ts and add the following:

import { getAccessToken, withApiAuthRequired } from '@auth0/nextjs-auth0' import { NextApiRequest, NextApiResponse } from 'next' async function handler(req: NextApiRequest, res: NextApiResponse) { const { accessToken: token } = await getAccessToken(req, res, { authorizationParams: { audience: 'https://grafbase.com', }, }) res.json({ token }) } export default withApiAuthRequired(handler)

We're now ready to make requests to our GraphQL API from the Next.js frontend using the access token generated by Auth0.

We'll now update pages/index.tsx to contain a query to fetch messages from the API.

Next inside pages/index.tsx add the following functions:

const fetchToken = async () => await fetch('/api/auth/token').then(res => res.json()) const fetchMessages = async () => { const { token } = await fetchToken() return fetch(process.env.NEXT_PUBLIC_GRAFBASE_API_URL!, { method: 'POST', headers: { Authorization: `Bearer ${token}`, }, body: JSON.stringify({ query: /* GraphQL */ ` { messages { content } } `, }), }) .then(res => res.json()) .catch(err => console.log(err)) }

You can see above that the fetchMessages function makes a request to fetchToken (the API route /api/auth/token we created previously) and returns the response as JSON.

Once the token is received we then pass that onto the Grafbase backend inside of the Authorization header.

Now update the Index component to import useState and add a button that calls the fetchMessages function:

import { useState } from 'react' export default function Index() { const [data, setData] = useState() const { user, error, isLoading } = useUser() if (isLoading) return <div>Loading...</div> if (error) return <div>{error.message}</div> if (user) { return ( <> Signed in <br /> <a href="/api/auth/logout">Logout</a> <br /> <button onClick={() => fetchMessages().then(({ data: res }) => setData(res))} > Fetch messages with token </button> <pre>{JSON.stringify({ data }, null, 2)}</pre> </> ) } return <a href="/api/auth/login">Login</a> }

That's it! You should now be able to authenticate with your Grafbase backend using the access token issued by Auth0.

Request success

Get Started

Secure your GraphQL gateway with a JWT token generated by Auth0.