> ## Documentation Index
> Fetch the complete documentation index at: https://help.plannotator.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure Cloudflare Access for Workspaces

> Protect the Workspaces app origin with Cloudflare Access while keeping API-key access and raw file links available.

Protect the Workspaces browser app origin with Cloudflare Access. Leave the API
and usercontent origins public. Workspaces checks the Access assertion and adds
each person who signs in to the instance organization as a member.

## Before you start

You need three custom domains in a Cloudflare zone:

* an app domain for the browser app and live editing;
* an API domain for API-key requests, MCP, and read-only Git; and
* a usercontent domain for raw file bytes.

You can test the deployment at the default `workers.dev` address, but supported
Access login requires a custom domain.

Use [Deploy Workspaces on Your Cloudflare
Account](/workspaces/self-hosting/cloudflare/deploy) for the shared resources
and two-Worker setup. Complete the Access steps below before the final app
Worker deploy.

## Create the Access application

<Steps>
  <Step title="Add a self-hosted application">
    In Cloudflare Zero Trust, open **Access** > **Applications**. Add a
    **Self-hosted** application for the app domain.
  </Step>

  <Step title="Add an allow policy">
    Choose the people who may sign in. Use your identity-provider groups,
    email domain, or an explicit list.
  </Step>

  <Step title="Copy the team domain">
    In Zero Trust settings, find the team domain. Set
    `CLOUDFLARE_ACCESS_TEAM_DOMAIN` in the app Worker config to its full HTTPS
    address.
  </Step>

  <Step title="Copy the application audience">
    Open the Access application's overview and copy its **Application Audience
    (AUD) tag**. Set `CLOUDFLARE_ACCESS_AUDIENCE` in the app Worker config to
    that value.
  </Step>

  <Step title="Set the instance organization">
    Set one stable `SELF_HOST_ORG_ID` and the displayed `SELF_HOST_ORG_NAME`.
    Cloudflare Access does not assign Workspaces roles. Every signed-in person
    becomes a member.
  </Step>

  <Step title="Deploy the app config">
    Deploy or redeploy the app Worker after you change its config. The
    usercontent Worker does not need the Access values.
  </Step>
</Steps>

## Keep API keys and raw links outside Access

Do not create an Access application for the API domain. Tools and agents use a
Workspaces API key on that public origin. The app Worker checks the bearer key
before it checks for an Access assertion.

Do not create an Access application for the usercontent domain. The usercontent
Worker has no browser session or app cookie. A living raw URL works only while
the workspace uses an open sharing setting. Anyone with a complete
version-pinned raw URL can read that stored version until the workspace is
deleted.

Putting the raw origin behind Access requires recipients and tools to sign in.
It also breaks **Copy raw link**.

## Verify human sign-in

<Steps>
  <Step title="Open the app domain">
    Use a private browser window so an existing Access session does not skip the
    sign-in test. Cloudflare should show the Access sign-in screen.
  </Step>

  <Step title="Sign in">
    Sign in with an account allowed by the policy. Cloudflare should return the
    browser to Workspaces.
  </Step>

  <Step title="Check the Workspaces account">
    Open **Settings** > **Account**. Confirm the expected email under **Signed in
    as**.
  </Step>

  <Step title="Create and revoke an API key">
    Open **Settings** > **API keys** and create a test key. Use it for one request
    to the public API origin, revoke it, and confirm the next request fails with
    `401 unauthorized`.
  </Step>
</Steps>

Cloudflare Access manages the browser session. Workspaces does not create its
own login cookie in this mode. **Sign out** opens Cloudflare's logout address.

## Fix common Access failures

| Result                                              | Check                                                                                         |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| The app opens without an Access screen              | Confirm the Access application covers the exact app custom domain.                            |
| Access denies an expected person                    | Review the allow policy and the identity-provider claims used by that policy.                 |
| Workspaces returns `401 unauthorized` after Access  | Confirm the team domain and audience match the assertion for this application.                |
| Workspaces treats the browser request as signed out | Confirm Access sends its assertion with every request to the app domain.                      |
| An API-key request opens an Access screen           | Send the request to the public API domain and remove that domain from the Access application. |
| Raw links ask recipients to sign in                 | Remove Access from the usercontent domain. Protect only the app domain.                       |

Disabling a person's Access login does not revoke an existing Workspaces API
key. The key owner must revoke it before you remove their sign-in access.

*Reviewed July 21, 2026. Maintained by the Plannotator documentation team.*
