Wordpress●

How to Set Up Auth for WordPress GraphQL in a Next.js Project

Learn how to set up auth for WordPress GraphQL in a Next.js project. This simple guide covers application passwords, JWT, and how to use your keys safely in API calls.

WordPress GraphQL Next.js Authentication Flow

If you use WordPress as a headless CMS with Next.js, sooner or later you will need to fetch private data. Maybe it is draft posts, a preview page, or content only logged in users should see. Public data works without any login, but private data needs authentication.

In this guide I will show you how to set up auth for WPGraphQL and how to use your credentials safely inside Next.js. I will keep it simple and go one step at a time.

What You Need Before You Start

  1. A WordPress site running on HTTPS
  2. The WPGraphQL plugin installed and active
  3. A Next.js project (App Router in this guide)
  4. Basic knowledge of fetch and environment variables

Step 1: Install and Check WPGraphQL

In your WordPress dashboard, go to Plugins, then Add New, and search for WPGraphQL. Install it and click Activate.

After that, you will see a new GraphQL menu in the sidebar. Your endpoint will be:

https://yourdomain.com/graphql

Open the GraphiQL IDE from the GraphQL menu and run a simple query to confirm everything works.

Step 2: Create an Application Password

This is built into WordPress. It is the easiest choice when your Next.js server needs to talk to WordPress, for example to read drafts. Think of it as your API key.

  1. In WordPress, go to Users, then Profile
  2. Scroll down to the Application Passwords section
  3. Type a name like “Nextjs Frontend”
  4. Click Add New Application Password
  5. Copy the password right away. WordPress shows it only once

A tip from experience: create a separate user with only the role it needs, like Editor, instead of using your admin account. If the key ever leaks, the damage stays small.

Step 4: Store the Credentials in Environment Variables

In the root of your Next.js project, open the .env.local file and add:

WORDPRESS_GRAPHQL_URL=https://yourdomain.com/graphql
WP_APP_USER=your_wordpress_username
WP_APP_PASSWORD=abcd efgh ijkl mnop qrst uvwx

Very important: do not add the NEXT_PUBLIC_ prefix to these names. Any variable with that prefix gets sent to the browser, and anyone can see it. Without the prefix, the value stays on the server only.

Also make sure .env.local is listed in your .gitignore file so it never goes to GitHub.

Step 5: Create a Helper Function for API Calls

Instead of writing the same fetch code again and again, make one helper. Create a file at lib/wp.js:

export async function wpFetch<T>(query: string): Promise<T> {
    const token = btoa(`${process.env.WP_USER}:${process.env.WP_APP_PASSWORD}`);

    const res = await fetch(process.env.WP_GRAPHQL_URL!, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            Authorization: `Basic ${token}`,
        },
        body: JSON.stringify({ query }),
        next: { revalidate: 60 }, 
    });

    const json = await res.json();
    if (json.errors) throw new Error(JSON.stringify(json.errors));
    return json.data;
}

Here is what this code does in simple words:

  1. It joins your username and application password, and turns them into a Base64 string.
  2. It sends that string in the Authorization header with the word Basic in front.
  3. WordPress reads the header, checks the user, and then returns data based on that user’s permissions.
  4. The revalidate: 60 line tells Next.js to refresh the cached data every 60 seconds.

Step 6: Use the Helper in a Page

Now let us fetch draft posts, which only logged in users can see. Create app/drafts/page.js:

import { wpFetch } from "@/lib/wp";

const QUERY = `
  query GetDrafts {
    posts(where: { status: DRAFT }) {
      nodes {
        id
        title
        slug
      }
    }
  }
`;

export default async function DraftsPage() {
  const data = await wpFetch(QUERY);
  const posts = data.posts.nodes;

  return (
    <main>
      <h1>Draft Posts</h1>
      {posts.map((post) => (
        <p key={post.id}>{post.title}</p>
      ))}
    </main>
  );
}

This is a Server Component, so the API call runs on the server. Your password never reaches the browser. If you run the same query without the auth header, WordPress returns an empty list. With the header, you see your drafts. That is how you know auth is working.

Common Mistakes to Avoid

  1. Using NEXT_PUBLIC_ on secret values
  2. Using an admin account when an Editor account is enough
  3. Running your site on HTTP. Application Passwords need HTTPS on live sites
  4. Forgetting to add .env.local to .gitignore
  5. Calling private queries from client components, which exposes your keys

Final Thoughts

Setting up auth for WordPress GraphQL is not hard once you know the flow. Create an application password, keep it in a server only environment variable, send it in the Authorization header, and always make private calls from the server side of Next.js. If you need user logins, add JWT on top.

I hope this guide saved you some time. If you get stuck on any step, leave a comment and I will try to help.