Blog A.Wolf

Blog Posts

No results for 'undefined'Powered by Algolia

How to use Contentful keys in a Client-Side app?

January 6th, 2020 - 4 min read

Two days ago, I read a question on Stackoverflow about a blog app created with React that is using Contentful as the data source.

The problem of the question was something related to React but in the comments, there was a question to the tokens and I'd like to explain each key and how to use them.

The last question in the Contentful FAQ doesn't help for client-side apps as you can not use environment variables to hide your keys.

Keep in mind, anything that is readable by a client-side script can be viewed in the browser console - so never put a personal access key into your code that is running on the client (e.g. a React App) because any malicious user can modify your data.

Glossar

Environment variables
"An environment variable is a dynamic-named value that can affect the way running processes will behave on a computer.
They are part of the environment in which a process runs. [...]
(from Wikipedia).
Space Id
The id used to identify your data and needed to query your data.
Content delivery / preview tokens
Read-only access to your data. Everyone with the token can read your content.
Personal access token (Content management token)
Full access to your data (read-write API). Everyone with the token can read and modify your data.

How to secure the access to your data in a client-side app?

If you're OK that anybody can read/use your content then it's OK to use the delivery token and space id on client side (see example below).

If you need more protection I think you need a server side or a serverless function (an AWS lambda) so you're not exposing any Contentful keys. With a serverless function you can work with environment variables (e.g. by using dotenv) and store the tokens securely on your hosting server in env. variables.

With Netlify you can use Netlify functions to query (or modify your data) with-out any token on the client.

How about static sites (e.g. Gatbsy)?

For Gatsby you're using the space id and access token with environment variables. For example, you can have a look at the source code of this blog.

The tokens are not visible in the created page as the query happens during build time and just the content will be served to the client.

For .env files just ensure that they're not committed to Github by adding it to .gitignore file. For local development, you create that file from .env.example (or .contentful.json.sample). For deployment, you need to add every required env. variable to your hosting server (e.g. for Netlify have a look in the env. docs).

Example with a delivery token

You can find an example React app that's using the delivery token in the following Codesandbox.

I'm just explaining the Contentful related parts here. The file src/api.js contains everything related to query Contentful.

import { createClient } from "contentful";

const config = {
  spaceId: process.env.CONTENTFUL_SPACE_ID,
  deliveryToken: process.env.CONTENTFUL_DELIVERY_TOKEN
};

const client = createClient({
  space: config.spaceId,
  accessToken: config.deliveryToken
});

export const getCourses = () =>
  client.getEntries({
    content_type: "course",
    order: "-sys.createdAt" // Ordering the entries by creation date
  });

We're first creating a client instance with createClient. The config is using the delivery token and space id. It's loaded from the .env file (required('dotenv').config() is called in index.js) but you could also hardcode the keys into the config constant.

The getCourses method is calling getEntries method from Contentful.js - It is returning a Promise that we can wait for with async/await or then.

  • content_type: "course" configures the get request so we only get entries of type course.
  • order: "-sys.createdAt" filters for the creation date. The - reverses the order (newest entry first). For more details about the ordering, you can have a look in the docs.

Conclusion

I think for a blog it is OK to use the delivery token client-side as I think it's very unlikely that it will be used somewhere else.

You could also revoke the key and use a new one or do a more complex setup by using a lambda to query your data. But I think the Lambda would make more sense if you also want to modify your data from your client-side app.

Anyway, I'll create an example with a Netlify function in a separate post to show how to query the data.

If anything is not right or I've missed a detail, please leave a comment below.

©2022 Alexander Wolf