Graph Authentication Models
Why authentication matters
Section titled “Why authentication matters”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
Section titled “Single Key authentication”How it works
Section titled “How it works”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.
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 }
}
}`
})
}
); # 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 } } }"}' When to use Single Key
Section titled “When to use Single Key”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
Security characteristics
Section titled “Security characteristics”- 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 authentication
Section titled “HMAC authentication”How it works
Section titled “How it works”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.
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,
}
); 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"
};
}
} When to use HMAC
Section titled “When to use HMAC”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
Security characteristics
Section titled “Security characteristics”- 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
Choosing the right model
Section titled “Choosing the right model”| Factor | Single Key | HMAC |
|---|---|---|
| Access level | Published content only | All content including drafts |
| Client safety | Safe for browser/mobile | Server-side only |
| CDN caching | Yes (cache-friendly) | No (unique signatures) |
| Request overhead | Minimal | Signature computation |
| Use case | Public frontends, SSG | Preview 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
Key management
Section titled “Key management”Finding your credentials
Section titled “Finding your credentials”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)
Rotation
Section titled “Rotation”Rotate credentials periodically or immediately if compromised:
- Generate new credentials in the Optimizely portal
- Update all applications using the old credentials
- Verify queries succeed with new credentials
- 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.
Environment separation
Section titled “Environment separation”Use separate Graph instances (or separate credential sets) for each environment:
| Environment | Auth model | Purpose |
|---|---|---|
| Development | Single Key | Local frontend development |
| Staging | Both | Full testing including preview |
| Production | Single Key (frontend) + HMAC (admin) | Live site with preview capability |