Skip to main content
Docs

Integrate Grafbase with Clerk

You will learn the following:

  • Create a JWT template in Clerk to generate Grafbase JWTs
  • Configure Grafbase to accept JWTs from Clerk
  • Use the Grafbase JWTs to authenticate Grafbase requests

Integrating Grafbase with Clerk gives you the benefits of using a Grafbase database while leveraging Clerk's authentication, prebuilt components, and webhooks.

This tutorial will show you how to integrate Clerk into your Grafbase application.

Create a JWT template based on Grafbase

  1. In the Clerk Dashboard, navigate to the JWT templates page.
  2. Select New template and then from the list of templates, select Grafbase. You'll be redirected to the template's settings page.
  3. Copy and save the Issuer URL somewhere secure. This URL is the issuer domain for Clerk's JWT templates, which is your application's Frontend API URL. In development, it's format will be https://verb-noun-00.clerk.accounts.dev. In production, it's format will be https://clerk.<your-domain>.com.

Map additional claims (optional)

In the Claims section, the default claims required by Grafbase are pre-mapped. You can include additional claims as necessary. For example, if your GraphQL API restricts access based on groups, you'll need to specify the user groups in the groups claim. So you would add something like:

{
  "groups": ["org:admin", "org:member"]
}

Configure Grafbase with the issuer domain

  1. In your env file, add your Issuer URL as the CLERK_FRONTEND_API_URL environment variable. If you already have it set, great!
    .env
    NEXT_PUBLIC_CLERK_FRONTEND_API_URL=YOUR_FRONTEND_API_URL
  2. In your Grafbase app, update your schema with the following:
    schema
      @auth(
        providers: [{ type: oidc, issuer: "{{ process.env.NEXT_PUBLIC_CLERK_FRONTEND_API_URL }}" }]
        rules: [{ allow: private }]
      ) {
      query: Query
    }
  3. If you're working with group-based user access, add allow: groups to the @auth rules, and provide an array of your user groups to the groups property:
    schema
      @auth(
        providers: [{ type: oidc, issuer: "{{ process.env.NEXT_PUBLIC_CLERK_FRONTEND_API_URL }}" }]
        rules: [{ allow: groups, groups: ["backend", "admin"] }]
      ) {
      query: Query
    }

Authenticate requests

When making requests to your Grafbase API, you must send Clerk's session token as a Bearer token in the Authorization header.

To retrieve Clerk's session token, use the getToken() method returned by the useAuth() hook. You'll need to pass the template name you created in the previous step to the getToken() method. The following example uses the default template name, grafbase.

export const useQuery = (query, variables) => {
  if (!query) {
    throw Error('No query provided to `useQuery`')
  }

  // Use Clerk's `useAuth()` hook to access the `getToken()` method
  const { getToken } = useAuth()

  const fetcher = async () => {
    // Retrieve Clerk's session token using the template you created in the Clerk Dashboard
    const token = await getToken({ template: 'grafbase' })

    try {
      const response = await fetch('YOUR_GRAFBASE_API', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          authorization: `Bearer ${token}`, // Send the session token as a Bearer token in the `Authorization` header
        },
        body: JSON.stringify({ query, variables }),
      })
      return response.json()
    } catch (err) {
      console.error(err)
    }
  }
  return useSWR(query, fetcher)
}

const YOUR_GRAPHQL_QUERY = `
	query {
		__schema {
			types {
				name
			}
		}
	}
`

const SchemaPage = () => {
  const { data, error } = useQuery(YOUR_GRAPHQL_QUERY)
  if (error) {
    return <div>error</div>
  }
  return <pre>{JSON.stringify({ data }, 2, null)}</pre>
}

export default SchemaPage

Feedback

What did you think of this content?

Last updated on