Skip to content

[wrangler] Add Access Service Token support for CI/non-interactive environment#13031

Open
WalshyDev wants to merge 1 commit intomainfrom
walshy/access-service-token-support
Open

[wrangler] Add Access Service Token support for CI/non-interactive environment#13031
WalshyDev wants to merge 1 commit intomainfrom
walshy/access-service-token-support

Conversation

@WalshyDev
Copy link
Member

@WalshyDev WalshyDev commented Mar 23, 2026

Fixes #11881.

When running wrangler dev with remote bindings (or vitest-pool-workers with remote bindings) behind a Cloudflare Access-protected domain, Wrangler spawns cloudflared access login which opens a browser for interactive authentication. This is impossible in CI/CD environments.

This PR adds support for Cloudflare Access Service Token authentication via two new environment variables:

  • CLOUDFLARE_ACCESS_CLIENT_ID -- the Access Service Token Client ID
  • CLOUDFLARE_ACCESS_CLIENT_SECRET -- the Access Service Token Client Secret

When both are set, Wrangler authenticates by sending CF-Access-Client-Id and CF-Access-Client-Secret headers to the Access-protected domain, extracting the CF_Authorization JWT from the response, and using it for subsequent requests -- completely bypassing the interactive cloudflared flow.

Additionally, when running in a non-interactive environment (no TTY or CI detected) without these credentials, Wrangler now throws a clear, actionable UserError instead of hanging on cloudflared access login:

The domain "example.workers.dev" is behind Cloudflare Access, but no Access Service Token
credentials were found and the current environment is non-interactive.
Set the CLOUDFLARE_ACCESS_CLIENT_ID and CLOUDFLARE_ACCESS_CLIENT_SECRET environment variables
to authenticate with an Access Service Token.
See https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/service-tokens/

Usage

export CLOUDFLARE_ACCESS_CLIENT_ID="<your-client-id>.access"
export CLOUDFLARE_ACCESS_CLIENT_SECRET="<your-client-secret>"
wrangler dev --remote


Open with Devin

…vironments

Support authenticating with Cloudflare Access-protected domains via
CLOUDFLARE_ACCESS_CLIENT_ID and CLOUDFLARE_ACCESS_CLIENT_SECRET env vars.
This enables wrangler dev with remote bindings in CI where cloudflared
access login is not possible.

When running in a non-interactive environment without these credentials,
throw a clear, actionable error instead of hanging on cloudflared.

Fixes #11881
@WalshyDev WalshyDev requested a review from a team as a code owner March 23, 2026 23:46
@changeset-bot
Copy link

changeset-bot bot commented Mar 23, 2026

🦋 Changeset detected

Latest commit: a6bb5a2

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-project-automation github-project-automation bot moved this to Untriaged in workers-sdk Mar 23, 2026
@WalshyDev WalshyDev changed the title [wrangler] Add Access Service Token support for CI/non-interactive en… [wrangler] Add Access Service Token support for CI/non-interactive environment Mar 23, 2026
@workers-devprod
Copy link
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • packages/workers-utils/src/environment-variables/factory.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/access.test.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/tests/helpers/msw/handlers/access.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/user/access.ts: [@cloudflare/wrangler]
  • packages/wrangler/src/user/auth-variables.ts: [@cloudflare/wrangler]

@ask-bonk
Copy link
Contributor

ask-bonk bot commented Mar 23, 2026

APIError: Not Found: Not found

github run

@ask-bonk
Copy link
Contributor

ask-bonk bot commented Mar 23, 2026

@WalshyDev Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 23, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@13031

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@13031

miniflare

npm i https://pkg.pr.new/miniflare@13031

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@13031

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@13031

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@13031

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@13031

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@13031

wrangler

npm i https://pkg.pr.new/wrangler@13031

commit: a6bb5a2

```sh
export CLOUDFLARE_ACCESS_CLIENT_ID="<your-client-id>.access"
export CLOUDFLARE_ACCESS_CLIENT_SECRET="<your-client-secret>"
wrangler dev --remote
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
wrangler dev --remote
wrangler dev

remote binding works without --remote (but I guess that the env vars still apply to --remote as well?)

Comment on lines +131 to +132
// Warn if only one of the two env vars is set
if (clientId || clientSecret) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check doesn't seem correct, doesn't it mean that we show the warning even when both variables are set? (true || true) === true

// Non-interactive so it will throw after the warning
setIsTTY(false);

await expect(getAccessToken("access-protected.com")).rejects.toThrow(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about toThrowErrorMatchingInlineSnapshot to include the whole error message instead of just non-interactive? 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This applies to all the other rejects.toThrow below, also I think the rejects.toEquals could be updated to just be toThrowErrorMatchingInlineSnapshot calls

);
});

it("should warn when only CLOUDFLARE_ACCESS_CLIENT_ID is set", async ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this and the following test, are saying should warn but then are not actually testing the warning message 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

Not possible to cloudflared access login on CI

3 participants