Skip to content

Graph Authentication Models

intermediate
📜CoreGraph

Optimizely Graph exposes your content through a public API endpoint. Authentication controls who can query that endpoint and what operations they can perform. Choosing the right authentication model affects security posture, caching behavior, and architectural flexibility.

Graph provides two authentication models, each designed for different deployment scenarios. Using the wrong model creates either unnecessary security exposure or unnecessary complexity.

Single Key authentication uses a static API key passed as a bearer token or query parameter. The key identifies your Graph instance and grants read-only access to published content.

Single Key authentication
javascript
const response = await fetch(
  'https://cg.optimizely.com/content/v2',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${SINGLE_KEY}`,
    },
    body: JSON.stringify({
      query: `query {
        ArticlePage(limit: 10) {
          items { Headline Author }
        }
      }`
    })
  }
);
bash
# Alternative: pass SingleKey as a query parameter
curl -X POST \
  'https://cg.optimizely.com/content/v2?auth=your-single-key' \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ ArticlePage(limit: 10) { items { Headline } } }"}'

Single Key is the right choice when:

  • Public content only — Your Graph instance serves only published, publicly visible content
  • Client-side queries — Browser-based or mobile applications need to query Graph directly
  • Static site generation — Build tools like Next.js, Astro, or Gatsby query Graph at build time
  • CDN caching is important — Single Key queries produce cache-friendly requests since the key is stable
  • The key is a read-only credential. It cannot modify, delete, or unpublish content.
  • The key is safe to include in client-side code, environment variables for build tools, or mobile app bundles.
  • Anyone with the key can query your published content. If your content is already publicly visible on a website, this is not an additional exposure.
  • Rotate the key through the Optimizely portal if it is compromised.

HMAC (Hash-based Message Authentication Code) authentication signs each request with a secret key. The signature is computed from the request body and a timestamp, making every request unique and tamper-proof.

HMAC authentication
javascript
import crypto from 'crypto';

function createHmacAuth(appKey, secret, body) {
  const timestamp = Math.floor(Date.now() / 1000);
  const message = `${appKey}${body}${timestamp}`;
  const signature = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('base64');

  return {
    'Authorization': `epi-hmac ${appKey}:${timestamp}:${signature}`,
    'Content-Type': 'application/json',
  };
}

const body = JSON.stringify({
  query: `query { ArticlePage(limit: 10) { items { Headline } } }`
});

const response = await fetch(
  'https://cg.optimizely.com/content/v2',
  {
    method: 'POST',
    headers: createHmacAuth(APP_KEY, SECRET, body),
    body,
  }
);
csharp
using System.Security.Cryptography;
using System.Text;

public class GraphHmacAuth
{
    public static Dictionary<string, string> CreateHeaders(
        string appKey, string secret, string body)
    {
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var message = $"{appKey}{body}{timestamp}";

        using var hmac = new HMACSHA256(
            Encoding.UTF8.GetBytes(secret));
        var hash = hmac.ComputeHash(
            Encoding.UTF8.GetBytes(message));
        var signature = Convert.ToBase64String(hash);

        return new Dictionary<string, string>
        {
            ["Authorization"] =
                $"epi-hmac {appKey}:{timestamp}:{signature}",
            ["Content-Type"] = "application/json"
        };
    }
}

HMAC is the right choice when:

  • Unpublished content access — You need to query draft or preview content for editorial previews
  • Server-to-server integrations — Backend services that should not expose credentials to clients
  • Content management operations — Administrative actions like triggering resyncs or managing webhooks
  • Sensitive content — Content that should not be accessible without proper authorization
  • HMAC provides elevated access including unpublished content and administrative operations
  • The Secret must never appear in client-side code, public repositories, or browser-accessible locations
  • Each request signature is unique due to the timestamp component, preventing replay attacks
  • HMAC requests bypass CDN caching because each signature is different
FactorSingle KeyHMAC
Access levelPublished content onlyAll content including drafts
Client safetySafe for browser/mobileServer-side only
CDN cachingYes (cache-friendly)No (unique signatures)
Request overheadMinimalSignature computation
Use casePublic frontends, SSGPreview systems, admin tools

Most architectures use both models:

  • Single Key for the production frontend that serves published content
  • HMAC for the preview environment that shows editors unpublished content

Credentials are available in the Optimizely portal under your Graph subscription:

  • AppKey — Identifies your Graph instance (used in both models)
  • Secret — Used only for HMAC signature generation (keep confidential)
  • SingleKey — Used for Single Key authentication (safe for client-side)

Rotate credentials periodically or immediately if compromised:

  1. Generate new credentials in the Optimizely portal
  2. Update all applications using the old credentials
  3. Verify queries succeed with new credentials
  4. Revoke the old credentials

Plan credential rotation during low-traffic periods. There is a brief window during rotation where both old and new credentials are valid.

Use separate Graph instances (or separate credential sets) for each environment:

EnvironmentAuth modelPurpose
DevelopmentSingle KeyLocal frontend development
StagingBothFull testing including preview
ProductionSingle Key (frontend) + HMAC (admin)Live site with preview capability