How to Integrate Descope with Your Headless CMS
Connect Descope to your headless CMS so auth roles, tenants, and gated content rules stay in sync the moment editors publish.
What is Descope?
Descope is a customer identity and access management platform for adding authentication, authorization, and user lifecycle flows to apps. Teams use it for passkeys, magic links, OTP, social login, SSO, MFA, session handling, roles, tenants, and B2B user onboarding. It’s used by SaaS teams, marketplaces, partner portals, and internal platforms that need identity flows without building every auth screen and security control from scratch.
Why integrate Descope with a headless CMS?
Auth rules usually start simple. A docs page is public, a pricing page is public, and a partner guide is private. Then you add enterprise-only docs, regional content, tenant-specific announcements, beta feature pages, and role-based training. If those access rules live in code while the content lives somewhere else, every content change becomes an engineering ticket.
Connecting Descope to a headless CMS lets editors control content and access metadata in one place, while Descope handles sign-in, sessions, roles, tenants, and MFA. For example, an editor can publish a partner-only guide with a required Descope role of partner_admin, and the app can check the user’s Descope token before serving that content. With Sanity, that access metadata is structured JSON in the Content Lake, so you don’t have to parse HTML or copy role names between tools. Webhooks can fire on publish, and Functions can run server-side sync logic without a separate queue or worker.
The alternative is usually brittle. Someone keeps a spreadsheet of role mappings, someone else hard-codes route guards, and nobody knows whether the content preview matches production auth behavior. The trade-off is that you need a clear boundary: Sanity should hold content access metadata, Descope should remain the authority for identity, sessions, and authentication policy. Don’t put secrets in content fields, and don’t trust client-side checks for protected content.
Architecture overview
A typical Descope and Sanity integration starts with structured documents in the Content Lake. You might model gatedPage, accessRole, accessPlan, organizationProfile, and memberProfile documents in Sanity Studio. Each document stores explicit fields such as requiredRoles, tenantId, planSlug, descopeRoleKey, or descopeLoginId. When an editor publishes or updates one of those documents, a Sanity webhook fires with the document ID and type. A Sanity Function or webhook handler validates the webhook secret, then uses GROQ to fetch exactly the fields Descope needs, including joins across references. For example, a memberProfile can resolve its related accessPlan and accessRole documents into Descope role keys and user custom attributes. That server-side handler calls Descope’s Management API through @descope/node-sdk using a Project ID and Management Key stored as environment variables. Depending on your model, it can update a Descope user’s custom attributes, assign roles, update tenant metadata, or keep permission names aligned with content access rules. The frontend then uses a Descope SDK to sign the user in, verifies the Descope session on the server, and queries Sanity for content that matches the user’s roles, tenant, or plan. The end user sees the right content, and a publish event can update the auth metadata path in seconds instead of waiting for a manual deploy.
Common use cases
Role-gated documentation
Let editors tag docs with Descope role keys such as customer_admin or partner_viewer, then serve only the pages a signed-in user can read.
Tenant-aware portals
Sync Sanity organization profiles, plan tiers, and portal settings into Descope tenant metadata for B2B SaaS workspaces.
User profile enrichment
Publish member profiles in Sanity Studio, then update Descope user custom attributes like locale, plan, region, and onboarding stage.
Passwordless onboarding pages
Connect invite-only onboarding content with Descope magic link or OTP flows so new users land on content matched to their role.
Step-by-step integration
- 1
Set up Descope
Create a Descope project, configure your authentication flow in the Descope Console, and copy your Project ID. Create a Management Key for server-side API calls, then install @descope/node-sdk for the sync layer and a frontend SDK such as @descope/react-sdk or @descope/nextjs-sdk for sign-in.
- 2
Model access metadata in Sanity Studio
Create schema fields that map content to identity rules. Common fields include descopeLoginId on memberProfile, descopeRoleKey on accessRole, tenantId on organizationProfile, requiredRoles on gatedPage, and planSlug on accessPlan. Keep these values typed and validated so editors don’t paste mismatched role names.
- 3
Create a publish trigger
Add a Sanity webhook or Sanity Function that runs when relevant documents are created, updated, published, or deleted. Include the document ID and type in the payload, sign the webhook, and keep the handler server-side so your Descope Management Key never reaches the browser.
- 4
Fetch the exact fields with GROQ
In the handler, use @sanity/client and a GROQ query to fetch only the fields Descope needs. Resolve references in the query, such as access roles attached to a member profile or a plan attached to an organization.
- 5
Call Descope’s Management API
Use @descope/node-sdk with your Project ID and Management Key to update users, roles, permissions, or tenants. Treat Descope as the source of truth for authentication and sessions, and treat Sanity as the source of truth for content access metadata.
- 6
Test the frontend path
Sign in as at least 2 test users with different roles. Publish a gated document in Sanity Studio, confirm the webhook ran, inspect the user or tenant in Descope, and verify that your frontend serves protected content only through a server-side check.
How Sanity + Descope works
Build your Descope integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Descope roles, tenants, and user metadata to the content your teams publish.
Start building free →CMS approaches to Descope
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Role and permission metadata | Access rules often live in plugins, page settings, or custom code, which makes role names hard to validate across environments. | Schema-as-code lets you model Descope role keys as reusable documents, validate values in Sanity Studio, and query them as structured JSON. |
| Real-time sync to Descope | Teams often rely on deploys, scheduled exports, or plugin hooks that vary by installation. | Webhooks can trigger on publish, and Functions can run server-side sync logic for Descope without you operating separate infrastructure. |
| Tenant-aware content | Tenant rules are usually added through custom tables or plugin-specific settings, which can be hard to reuse across apps. | GROQ can join organization profiles, plans, required roles, and pages in one query before you update Descope tenant metadata or filter content. |
| Protected content delivery | The page renderer often decides access, which can mix auth checks with presentation logic. | Your app can verify the Descope session on the server, then query the Content Lake for only the content matching the user’s roles, tenant, or plan. |
| Editorial preview for gated pages | Preview may not match production auth rules, especially when access logic is hidden in plugins or templates. | Presentation Tool and structured access fields let editors preview gated content while developers keep production Descope checks server-side. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Auth0
Connect structured content with Auth0 roles, organizations, and JWT claims for gated web and app experiences.
Sanity + Clerk
Use Clerk authentication with Sanity-powered member profiles, account pages, and role-based content.
Sanity + Firebase Auth
Pair Firebase Auth users with structured Sanity content for signed-in mobile apps, portals, and personalized onboarding.