Skip to content

Application

Source: src/Cloudflare/Access/Application.ts

A Cloudflare Zero Trust Access application.

Replaces the curl-based POST /accounts/{accountId}/access/apps workflow with an Alchemy-managed resource. Supports every Cloudflare application type including warp, which Cloudflare requires for device enrolment via the WARP client.

Access policies are authored as standalone Policy resources and referenced here by id — there is no inline-policy support.

Self-hosted application gated by a reusable Access policy

const allowMyOrg = yield* Cloudflare.Access.Policy("AllowMyOrg", {
name: "Allow example.com via Google",
decision: "allow",
include: [{ emailDomain: { domain: "example.com" } }],
});
const app = yield* Cloudflare.Access.Application("InternalDashboard", {
type: "self_hosted",
domain: "dashboard.example.com",
sessionDuration: "24h",
policies: [allowMyOrg],
});

Managed OAuth for an MCP server

const app = yield* Cloudflare.Access.Application("McpServer", {
type: "self_hosted",
domain: "mcp.example.com",
oauthConfiguration: {
enabled: true,
grant: {
sessionDuration: "24h",
accessTokenLifetime: "15m",
},
dynamicClientRegistration: {
enabled: true,
allowAnyOnLocalhost: true,
allowAnyOnLoopback: true,
},
},
});

Require Access on a specific Worker

// The application owns the policies (inline here — no separate Policy
// resource needed); the Worker enrolls itself via its `access` prop,
// covering its custom domains, routes, workers.dev URL, and version
// preview URLs.
const App = Cloudflare.Access.Application("TeamOnly", {
type: "self_hosted",
policies: [
{ decision: "allow", include: [{ emailDomain: "example.com" }] },
],
});
export default class Api extends Cloudflare.Worker<Api>()("Api", {
main: import.meta.url,
access: { application: App },
}, /* ... *​/) {}

Require Access on every Worker in the account

// Covers all current AND future Workers. Hostname-level policies beat
// Worker-level policies, which beat this account-level policy — so an
// individual Worker can still be opened up with its own application.
yield* Cloudflare.Access.Application("ProtectAllWorkers", {
type: "self_hosted",
destinations: [
Cloudflare.Access.AllWorkers, // production traffic of every Worker
Cloudflare.Access.AllWorkerPreviews, // every Worker's preview URLs
],
policies: [
{ decision: "allow", include: [{ emailDomain: "example.com" }] },
],
});
// There can only be ONE warp app per account; Cloudflare auto-derives the
// domain (`${authDomain}/warp`) so do not pass `domain` for this type.
const allowCorp = yield* Cloudflare.Access.Policy("AllowCorpUsers", {
name: "Allow corp users",
decision: "allow",
include: [{ emailDomain: { domain: "example.com" } }],
});
const enroll = yield* Cloudflare.Access.Application("warp-login", {
type: "warp",
allowedIdps: [googleIdpId],
autoRedirectToIdentity: true,
sessionDuration: "720h",
policies: [allowCorp],
});
const admins = yield* Cloudflare.Access.Policy("AdminsOnly", {
name: "Admins only",
decision: "allow",
include: [
{
gsuite: {
email: "admins@example.com",
identityProviderId: googleIdpUuid,
},
},
],
});
const app = yield* Cloudflare.Access.Application("AdminConsole", {
type: "self_hosted",
domain: "admin.example.com",
allowedIdps: [googleIdpUuid],
autoRedirectToIdentity: true,
policies: [admins],
});