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/schema.graphql was automatically generated.

Open this file and replace the contents with the below:

schema @auth( providers: [{ type: oidc, issuer: "{{ env.AUTH0_ISSUER_BASE_URL }}" }] ) { query: Query } type Message @model { author: String! body: String! }

Here we configure the Grafbase backend with the OpenID Connect (oidc) provider and a basic Message database model we can use to test authenticated requests.

Grafbase lets you restrict access to signed-in users only, as well as specific groups of users, and even control the types of operations users can perform — read, get, list, create, update, and delete.

Update the @auth directive with the rule that restricts access to signed-in users only:

schema @auth( providers: [{ type: oidc, issuer: "{{ env.AUTH0_ISSUER_BASE_URL }}" }] rules: [{ allow: private }] ) { query: Query }

Next add the AUTH0_ISSUER_BASE_URL to the file grafbase/.env:

AUTH0_ISSUER_BASE_URL

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

Now run the Grafbase development server:

npx grafbase dev

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

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 Grafbase backend 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 backend.

If you haven't any messages in your database yet you can go to http://localhost:4000 and add some using this GraphQL mutation:

mutation { messageCreate( input: { author: "Grafbase Admin", body: "Grafbase is awesome!" } ) { message { id } } }

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 */ ` { messageCollection(first: 100) { edges { node { id } } } } `, }), }) .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.